|
|
@@ -1,22 +1,26 @@
|
|
|
|
#!/usr/bin/env python
|
|
|
|
#!/usr/bin/env python3
|
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
|
|
|
|
|
|
|
|
from __future__ import division
|
|
|
|
from __future__ import division
|
|
|
|
|
|
|
|
from __future__ import print_function
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
|
|
|
import configparser
|
|
|
|
|
|
|
|
except ImportError:
|
|
|
|
|
|
|
|
import ConfigParser as configparser # Python 2.x import
|
|
|
|
|
|
|
|
|
|
|
|
from os import path
|
|
|
|
from os import path
|
|
|
|
from sys import argv
|
|
|
|
from sys import argv
|
|
|
|
from math import ceil
|
|
|
|
from math import ceil
|
|
|
|
from getpass import getpass
|
|
|
|
from getpass import getpass
|
|
|
|
from optparse import OptionParser
|
|
|
|
from optparse import OptionParser
|
|
|
|
from curses import textpad, panel
|
|
|
|
|
|
|
|
import ConfigParser
|
|
|
|
|
|
|
|
import subprocess
|
|
|
|
import subprocess
|
|
|
|
import base64
|
|
|
|
import base64
|
|
|
|
import curses
|
|
|
|
|
|
|
|
import time
|
|
|
|
import time
|
|
|
|
|
|
|
|
import curses
|
|
|
|
|
|
|
|
from curses import textpad, panel
|
|
|
|
|
|
|
|
|
|
|
|
# https://github.com/zlaxy/sshch
|
|
|
|
# https://github.com/zlaxy/sshch
|
|
|
|
version = "0.7"
|
|
|
|
version = "0.9"
|
|
|
|
# path to conf file, default: ~/.config/sshch.conf
|
|
|
|
# path to conf file, default: ~/.config/sshch.conf
|
|
|
|
conf_file = path.expanduser("~") + '/.config/sshch.conf'
|
|
|
|
conf_file = path.expanduser("~") + '/.config/sshch.conf'
|
|
|
|
|
|
|
|
|
|
|
@@ -54,6 +58,7 @@ def ConnectAlias(alias, command=False):
|
|
|
|
password = base64.b32decode(base64.b16decode(
|
|
|
|
password = base64.b32decode(base64.b16decode(
|
|
|
|
base64.b64decode(conf.get(alias, "password"))))
|
|
|
|
base64.b64decode(conf.get(alias, "password"))))
|
|
|
|
exec_string = 'sshpass -p "' + password + '" '
|
|
|
|
exec_string = 'sshpass -p "' + password + '" '
|
|
|
|
|
|
|
|
if conf.has_option(alias, "exec_string"):
|
|
|
|
exec_string = exec_string + conf.get(alias, "exec_string")
|
|
|
|
exec_string = exec_string + conf.get(alias, "exec_string")
|
|
|
|
if command:
|
|
|
|
if command:
|
|
|
|
exec_string = exec_string + " " + command
|
|
|
|
exec_string = exec_string + " " + command
|
|
|
@@ -62,7 +67,7 @@ def ConnectAlias(alias, command=False):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def HoldConnection(alias):
|
|
|
|
def HoldConnection(alias):
|
|
|
|
print "Connecting to " + alias + ". Press CTRL+C to cancel."
|
|
|
|
print("Connecting to " + alias + ". Press CTRL+C to cancel.")
|
|
|
|
time.sleep(1)
|
|
|
|
time.sleep(1)
|
|
|
|
while True:
|
|
|
|
while True:
|
|
|
|
ConnectAlias(alias)
|
|
|
|
ConnectAlias(alias)
|
|
|
@@ -76,10 +81,10 @@ def CMDAdd(alias):
|
|
|
|
"(example: ssh user@somehost.com):\n"]))
|
|
|
|
"(example: ssh user@somehost.com):\n"]))
|
|
|
|
string = ""
|
|
|
|
string = ""
|
|
|
|
while string == "":
|
|
|
|
while string == "":
|
|
|
|
string = raw_input(prompt_add)
|
|
|
|
string = input(prompt_add)
|
|
|
|
SetAliasString(alias, string)
|
|
|
|
SetAliasString(alias, string)
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
print result
|
|
|
|
print(result)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def CMDEdit(alias):
|
|
|
|
def CMDEdit(alias):
|
|
|
@@ -88,10 +93,10 @@ def CMDEdit(alias):
|
|
|
|
"(example: ssh user@somehost.com):\n"]))
|
|
|
|
"(example: ssh user@somehost.com):\n"]))
|
|
|
|
string = ""
|
|
|
|
string = ""
|
|
|
|
while string == "":
|
|
|
|
while string == "":
|
|
|
|
string = raw_input(prompt_edit)
|
|
|
|
string = input(prompt_edit)
|
|
|
|
SetAliasString(alias, string)
|
|
|
|
SetAliasString(alias, string)
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
print "error: '" + alias + "' alias is not exists"
|
|
|
|
print("error: '" + alias + "' alias is not exists")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def CMDPassword(alias):
|
|
|
|
def CMDPassword(alias):
|
|
|
@@ -102,56 +107,57 @@ def CMDPassword(alias):
|
|
|
|
if not string == "":
|
|
|
|
if not string == "":
|
|
|
|
SetPassword(alias, string)
|
|
|
|
SetPassword(alias, string)
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
print "error: '" + alias + "' alias is not exists"
|
|
|
|
print("error: '" + alias + "' alias is not exists")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def CMDRemove(alias):
|
|
|
|
def CMDRemove(alias):
|
|
|
|
if conf.has_section(alias):
|
|
|
|
if conf.has_section(alias):
|
|
|
|
prompt_remove = ("Type 'yes' if you sure to remove '" + alias + "' alias: ")
|
|
|
|
prompt_remove = ("Type 'yes' if you sure to remove '" + alias + "' alias: ")
|
|
|
|
string = raw_input(prompt_remove)
|
|
|
|
string = input(prompt_remove)
|
|
|
|
if string == "yes":
|
|
|
|
if string == "yes":
|
|
|
|
RemoveAliases([alias])
|
|
|
|
RemoveAliases([alias])
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
print "'" + alias + "' alias was not deleted."
|
|
|
|
print("'" + alias + "' alias was not deleted.")
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
print "error: '" + alias + "' alias is not exists."
|
|
|
|
print("error: '" + alias + "' alias is not exists.")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def CMDConnect(aliases, command=False):
|
|
|
|
def CMDConnect(aliases, command=False):
|
|
|
|
for alias in aliases:
|
|
|
|
for alias in aliases:
|
|
|
|
if conf.has_section(alias):
|
|
|
|
if conf.has_section(alias):
|
|
|
|
print "Connecting to " + alias + "..."
|
|
|
|
print("Connecting to " + alias + "...")
|
|
|
|
ConnectAlias(alias, command)
|
|
|
|
ConnectAlias(alias, command)
|
|
|
|
print "... " + alias + " session finished."
|
|
|
|
print("... " + alias + " session finished.")
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
print "error: '" + alias + "' alias is not exists"
|
|
|
|
print("error: '" + alias + "' alias is not exists")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def CMDList(option, opt, value, parser):
|
|
|
|
def CMDList(option, opt, value, parser):
|
|
|
|
print ', '.join(str(p) for p in conf.sections())
|
|
|
|
print(', '.join(str(p) for p in conf.sections()))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def CMDFullList(option, opt, value, parser):
|
|
|
|
def CMDFullList(option, opt, value, parser):
|
|
|
|
for p in conf.sections():
|
|
|
|
for p in conf.sections():
|
|
|
|
to_print = "".join([str(p), " - ", conf.get(p, "exec_string"),
|
|
|
|
to_print = "".join([str(p), " - ", (conf.get(p, "exec_string") if
|
|
|
|
(" [password]" if conf.has_option(p, "password") else ""), "\n"])
|
|
|
|
conf.has_option(p, "exec_string") else ""),
|
|
|
|
|
|
|
|
(" [password]" if conf.has_option(p, "password") else "")])
|
|
|
|
print(to_print)
|
|
|
|
print(to_print)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def CursesConnect(screen, aliases, command=False):
|
|
|
|
def CursesConnect(screen, aliases, command=False):
|
|
|
|
curses.endwin()
|
|
|
|
curses.endwin()
|
|
|
|
for alias in aliases:
|
|
|
|
for alias in aliases:
|
|
|
|
print "Connecting to " + alias + "..."
|
|
|
|
print("Connecting to " + alias + "...")
|
|
|
|
ConnectAlias(alias, command)
|
|
|
|
ConnectAlias(alias, command)
|
|
|
|
print "... " + alias + " session finished."
|
|
|
|
print("... " + alias + " session finished.")
|
|
|
|
print "Press 'enter' to continue."
|
|
|
|
print("Press 'enter' to continue.")
|
|
|
|
screen.getch()
|
|
|
|
screen.getch()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def CursesExit(error=False):
|
|
|
|
def CursesExit(error=False):
|
|
|
|
curses.endwin()
|
|
|
|
curses.endwin()
|
|
|
|
if error:
|
|
|
|
if error:
|
|
|
|
print error
|
|
|
|
print(error)
|
|
|
|
exit()
|
|
|
|
exit()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -332,8 +338,9 @@ def CursesMain():
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
password = ""
|
|
|
|
password = ""
|
|
|
|
exec_string = ["[", selected_strings[i], "] ", str(i), " ",
|
|
|
|
exec_string = ["[", selected_strings[i], "] ", str(i), " ",
|
|
|
|
strings[i - 1], " (", conf.get(strings[i - 1], "exec_string"),
|
|
|
|
strings[i - 1], " (", (conf.get(strings[i - 1],
|
|
|
|
")", password]
|
|
|
|
"exec_string") if conf.has_option(strings[i - 1],
|
|
|
|
|
|
|
|
"exec_string") else ""), ")", password]
|
|
|
|
if (i == position):
|
|
|
|
if (i == position):
|
|
|
|
box.addnstr(i, 2, "".join(exec_string), width - 6, highlight_text)
|
|
|
|
box.addnstr(i, 2, "".join(exec_string), width - 6, highlight_text)
|
|
|
|
else:
|
|
|
|
else:
|
|
|
@@ -386,7 +393,9 @@ def CursesMain():
|
|
|
|
while edit_string.rstrip() == "":
|
|
|
|
while edit_string.rstrip() == "":
|
|
|
|
string_textpad = CursesTextpad(screen, 3, width - 8,
|
|
|
|
string_textpad = CursesTextpad(screen, 3, width - 8,
|
|
|
|
(height // 2) - 1, 4, "Enter new execution string:",
|
|
|
|
(height // 2) - 1, 4, "Enter new execution string:",
|
|
|
|
conf.get(strings[position - 1], "exec_string"),
|
|
|
|
(conf.get(strings[position - 1],
|
|
|
|
|
|
|
|
"exec_string") if conf.has_option(strings[position - 1],
|
|
|
|
|
|
|
|
"exec_string") else ""),
|
|
|
|
normal_text, highlight_text)
|
|
|
|
normal_text, highlight_text)
|
|
|
|
edit_string = string_textpad.edit(CursesTextpadConfirm)
|
|
|
|
edit_string = string_textpad.edit(CursesTextpadConfirm)
|
|
|
|
SetAliasString(strings[position - 1],
|
|
|
|
SetAliasString(strings[position - 1],
|
|
|
@@ -533,8 +542,9 @@ def CursesMain():
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
password = ""
|
|
|
|
password = ""
|
|
|
|
exec_string = ["[", selected_strings[i], "] ", str(i), " ",
|
|
|
|
exec_string = ["[", selected_strings[i], "] ", str(i), " ",
|
|
|
|
strings[i - 1], " (", conf.get(strings[i - 1], "exec_string"),
|
|
|
|
strings[i - 1], " (", (conf.get(strings[i - 1],
|
|
|
|
")", password]
|
|
|
|
"exec_string") if conf.has_option(strings[i - 1],
|
|
|
|
|
|
|
|
"exec_string") else ""), ")", password]
|
|
|
|
if (i + (max_row * (page - 1)) == (position + (max_row * (page - 1)))):
|
|
|
|
if (i + (max_row * (page - 1)) == (position + (max_row * (page - 1)))):
|
|
|
|
box.addnstr(i - (max_row * (page - 1)), 2, "".join(
|
|
|
|
box.addnstr(i - (max_row * (page - 1)), 2, "".join(
|
|
|
|
exec_string), width - 6, highlight_text)
|
|
|
|
exec_string), width - 6, highlight_text)
|
|
|
@@ -550,7 +560,12 @@ def CursesMain():
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
if __name__ == "__main__":
|
|
|
|
conf = ConfigParser.RawConfigParser()
|
|
|
|
try:
|
|
|
|
|
|
|
|
input = raw_input # Fix for Python 2.x
|
|
|
|
|
|
|
|
except NameError:
|
|
|
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
conf = configparser.RawConfigParser()
|
|
|
|
if not path.exists(conf_file):
|
|
|
|
if not path.exists(conf_file):
|
|
|
|
open(conf_file, 'w')
|
|
|
|
open(conf_file, 'w')
|
|
|
|
conf.read(conf_file)
|
|
|
|
conf.read(conf_file)
|
|
|
@@ -559,15 +574,15 @@ if __name__ == "__main__":
|
|
|
|
CMDOptions()
|
|
|
|
CMDOptions()
|
|
|
|
except KeyboardInterrupt:
|
|
|
|
except KeyboardInterrupt:
|
|
|
|
exit()
|
|
|
|
exit()
|
|
|
|
except ConfigParser.Error:
|
|
|
|
except configparser.Error:
|
|
|
|
print ("Error: can't parse your config file, please check it manually or make new one")
|
|
|
|
print("Error: can't parse your config file, please check it manually or make new one")
|
|
|
|
exit()
|
|
|
|
exit()
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
try:
|
|
|
|
try:
|
|
|
|
CursesMain()
|
|
|
|
CursesMain()
|
|
|
|
except KeyboardInterrupt:
|
|
|
|
except KeyboardInterrupt:
|
|
|
|
CursesExit()
|
|
|
|
CursesExit()
|
|
|
|
except ConfigParser.NoOptionError:
|
|
|
|
except configparser.NoOptionError:
|
|
|
|
CursesExit("".join(["Error: can't parse your config file, please ",
|
|
|
|
CursesExit("".join(["Error: can't parse your config file, please ",
|
|
|
|
"check it manually or make new one"]))
|
|
|
|
"check it manually or make new one"]))
|
|
|
|
except curses.error:
|
|
|
|
except curses.error:
|
|
|
|