Compare commits
16 Commits
GHPS/maste
...
tempb
| Author | SHA1 | Date | |
|---|---|---|---|
| ba9fa303ba | |||
| 1b9acdcc4a | |||
| b7fdcf119d | |||
| b48081be65 | |||
| 32013bdb8d | |||
| 450b30b196 | |||
| 8e930115a5 | |||
| ec8a2ca14a | |||
| 9c361bbe00 | |||
| 37a20a0c48 | |||
| e430142fdc | |||
| c8069554eb | |||
|
|
6fdcf8ae6d | ||
| c528af6414 | |||
|
|
9ea667f201 | ||
| 2c8f072499 |
21
LICENSE
21
LICENSE
@@ -4,27 +4,26 @@ sshch is released under the DWTW license
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under the terms of the Do What Thou Wilt License.
|
||||
|
||||
DO WHAT THAU WILT
|
||||
Boundless Public License
|
||||
DO WHAT THOU WILT
|
||||
TO PUBLIC LICENSE
|
||||
|
||||
Version 2.5
|
||||
Version 2.55
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim or modified copies of this license document, and changing it is allowed as long as the name is changed.
|
||||
Everyone is permitted to copy and distribute verbatim or modified copies of this license document, and changing it in full or in part is allowed without any restrictions.
|
||||
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. Do what thou wilt shall be the whole of the Law.
|
||||
|
||||
Anyone is allowed to copy and distribute the copies of this license agreement in whole or in part, as well as modify it without any other limitations.
|
||||
DWTWL – a license with a single requirement: DO WHAT THOU WILT
|
||||
|
||||
DWTW – a license with a single requirement: DO WHAT THOU WILT
|
||||
The license provides more freedom than any other one (such as GPL or BSD) and does not require saving the license text on copying.
|
||||
|
||||
The license provides more freedom than any other one (such as GPL or BSD) and does not require saving the license text on copying.
|
||||
DWTWL – an accomplished and eligible license for free text, code and any other symbols (including the software, documentation and artwork).
|
||||
|
||||
DWTW – an accomplished and eligible license for free text (including the software, documentation and artwork).
|
||||
The license does not contain a "no warranty" clause. DWTWL can be used in countries that do not legally acknowledge the transition to public domain.
|
||||
|
||||
The license does not contain "no warranty" clause. DWTW can be used in countries that do not legally acknowledge the transition to public domain.
|
||||
Summary:
|
||||
|
||||
Summary:
|
||||
|
||||
An author-creator gives his or her source code to the world for free, without becoming distracted by worldly thinking regarding how and why the others will use it.
|
||||
An author-creator gives their source code to the world for free, without becoming distracted by worldly thinking regarding how and why the others will use it.
|
||||
|
||||
39
README.md
39
README.md
@@ -1,31 +1,48 @@
|
||||
SSH connection manager with curses interface
|
||||
SSH connection and aliases manager with curses and command line interface
|
||||
======
|
||||
sshch is released under DWTWL 2.5 license
|
||||
sshch is released under DWTWL 2.55 license
|
||||
|
||||
sshch compatible with pyhon2 and python3, no additional libraries are required
|
||||
### Screenshot
|
||||

|
||||
### Installing
|
||||
To install for all users:
|
||||
**You can install a release version from pip:**
|
||||
```bash
|
||||
pip install sshch
|
||||
```
|
||||
**Manual installation from the package or git repository also available:**
|
||||
|
||||
To install for all users:
|
||||
```bash
|
||||
sudo python setup.py install
|
||||
```
|
||||
To install just for current user:
|
||||
```
|
||||
```bash
|
||||
mkdir ~/.local/bin
|
||||
cp sshch/sshch ~/.local/bin/
|
||||
```
|
||||
### Using
|
||||
To run curses interface:
|
||||
```
|
||||
```bash
|
||||
sshch
|
||||
```
|
||||
To run command line help:
|
||||
```
|
||||
```bash
|
||||
sshch -h
|
||||
```
|
||||
**If you want to use unsafe 'password' feature you must install 'sshpass' first.**
|
||||
For exit from current ssh session press `Ctrl+D`.
|
||||
|
||||
If you want to use bash autocompletion function with sshch, copy autocompletion script to /etc/bash_completion.d/:
|
||||
**Additional Features**
|
||||
- If you want to use unsafe 'password' feature you must install `sshpass` first.
|
||||
- If you want to use bash autocompletion function with sshch, copy autocompletion script to /etc/bash_completion.d/:
|
||||
```bash
|
||||
sudo cp completion/sshch_bash_completion.sh /etc/bash_completion.d/sshch
|
||||
```
|
||||
sudo cp sshch_bash_completion.sh /etc/bash_completion.d/sshch
|
||||
```
|
||||
(changes will come into effect with new bash session)
|
||||
(changes will come into effect with new bash session)
|
||||
- If you want to use zsh autocompletion:
|
||||
1) Place File in a Directory where ZSH can find it
|
||||
|
||||
-> Search Path is Stored in $fpath
|
||||
|
||||
-> echo $fpath
|
||||
2) Rename File to '_sshch'
|
||||
|
||||
@@ -2,7 +2,7 @@ _sshch_complete()
|
||||
{
|
||||
local cur_word alias_list
|
||||
cur_word="${COMP_WORDS[COMP_CWORD]}"
|
||||
alias_list=`sshch -l | sed 's/,//g'`
|
||||
alias_list=`sshch -l`
|
||||
COMPREPLY=($(compgen -W "$alias_list" -- $cur_word))
|
||||
return 0
|
||||
}
|
||||
27
completion/sshch_zsh_completion.sh
Normal file
27
completion/sshch_zsh_completion.sh
Normal file
@@ -0,0 +1,27 @@
|
||||
#compdef sshch
|
||||
#
|
||||
# ZSH Completion for SSHCH
|
||||
# Usage:
|
||||
# 1) Place File in a Directory where ZSH can find it
|
||||
# -> Search Path is Stored in $fpath
|
||||
# -> echo $fpath
|
||||
# 2) Rename File to '_sshch'
|
||||
#
|
||||
_arguments '::aliasname:->getAlias' \
|
||||
'-e[Edit Alias]:aliasname:->getAlias' '--edit[Edit Alias]:aliasname:->getAlias' \
|
||||
'-p[Set Password]:aliasname:->getAlias' '--password[Set Password]:aliasname:->getAlias' \
|
||||
'-r[Remove Alias]:aliasname:->getAlias' '--remove[Remove Alias]:aliasname:->getAlias' \
|
||||
'-k[Keep Connection]:aliasname:->getAlias' '--keep[Keep Connection]:aliasname:->getAlias' \
|
||||
'-a[Add Alias]' '--add[Add Alias]'\
|
||||
'-c[Add Command for Executing Alias]' '--command[Add Command for Executing Alias]'\
|
||||
'-h[Show Help Message]' '--help[Show Help Message]'\
|
||||
'-l[List Existing Alias]' '--list[List Existing Alias]'\
|
||||
'-f[List Existing Alias with Connection String]' '--fulllist[List Existing Alias with Connection String]'\
|
||||
'--version[Show Program Version]'
|
||||
case "$state" in
|
||||
getAlias)
|
||||
local -a alias_list
|
||||
alias_list=($(sshch -l))
|
||||
_values -s ' ' 'Aliases' $alias_list
|
||||
;;
|
||||
esac
|
||||
15
setup.py
15
setup.py
@@ -7,22 +7,27 @@ def main():
|
||||
|
||||
setup(name='sshch',
|
||||
author='zlaxy',
|
||||
author_email='zlaxyi@gmail.com',
|
||||
url='https://github.com/zlaxy/sshch/',
|
||||
description='Ssh connection manager',
|
||||
license='DWTWL 2.5',
|
||||
version='0.8',
|
||||
description='Ssh connection and aliases manager',
|
||||
long_description='SSH connection and aliases manager with curses and command line interface',
|
||||
long_description_content_type='text/x-rst',
|
||||
license='DWTWL 2.55',
|
||||
version='1.0',
|
||||
py_modules=['sshch'],
|
||||
scripts=['sshch/sshch'],
|
||||
keywords='sshch ssh aliases manager',
|
||||
python_requires='>=2.6, !=3.0.*, !=3.1.*, !=3.2.*, <4',
|
||||
|
||||
# http://pypi.python.org/pypi?%3Aaction=list_classifiers
|
||||
classifiers=[
|
||||
'Development Status :: 4 - Beta',
|
||||
'Development Status :: 5 - Production/Stable',
|
||||
'Environment :: Console :: Curses',
|
||||
'Intended Audience :: System Administrators',
|
||||
'License :: Freeware',
|
||||
'Natural Language :: English',
|
||||
'Operating System :: POSIX',
|
||||
'Programming Language :: Python :: 2.7',
|
||||
'Programming Language :: Python',
|
||||
'Topic :: Internet',
|
||||
'Topic :: System :: Networking',
|
||||
'Topic :: System :: Systems Administration',
|
||||
|
||||
427
sshch/sshch
427
sshch/sshch
@@ -20,9 +20,11 @@ import curses
|
||||
from curses import textpad, panel
|
||||
|
||||
# https://github.com/zlaxy/sshch
|
||||
version = "0.9"
|
||||
version = "1.0"
|
||||
# path to conf file, default: ~/.config/sshch.conf
|
||||
conf_file = path.expanduser("~") + '/.config/sshch.conf'
|
||||
# expand groups by default
|
||||
expand_default = True
|
||||
|
||||
|
||||
def AddNewAlias(alias):
|
||||
@@ -31,7 +33,7 @@ def AddNewAlias(alias):
|
||||
conf.write(open(conf_file, "w"))
|
||||
return True
|
||||
else:
|
||||
return "error: '" + alias + "' already exists"
|
||||
return "error: '" + alias + "' alias or group already exists"
|
||||
|
||||
|
||||
def SetAliasString(alias, string):
|
||||
@@ -39,10 +41,20 @@ def SetAliasString(alias, string):
|
||||
conf.write(open(conf_file, "w"))
|
||||
|
||||
|
||||
def SetGroupString(alias, string):
|
||||
conf.set(alias, "group", string)
|
||||
conf.write(open(conf_file, "w"))
|
||||
|
||||
|
||||
def SetPassword(alias, string):
|
||||
string = base64.b64encode(base64.b16encode(
|
||||
base64.b32encode(string)))
|
||||
conf.set(alias, "password", string)
|
||||
if string == "" or string == b'':
|
||||
conf.remove_option(alias, "password")
|
||||
else:
|
||||
string = string.encode()
|
||||
string = base64.b64encode(base64.b16encode(
|
||||
base64.b32encode(string)))
|
||||
string = string.decode('utf-8')
|
||||
conf.set(alias, "password", string)
|
||||
conf.write(open(conf_file, "w"))
|
||||
|
||||
|
||||
@@ -56,27 +68,35 @@ def ConnectAlias(alias, command=False):
|
||||
exec_string = ""
|
||||
if conf.has_option(alias, "password"):
|
||||
password = base64.b32decode(base64.b16decode(
|
||||
base64.b64decode(conf.get(alias, "password"))))
|
||||
exec_string = 'sshpass -p "' + password + '" '
|
||||
base64.b64decode(conf.get(alias, "password"))))
|
||||
exec_string = 'sshpass -p "' + password.decode('utf-8') + '" '
|
||||
if conf.has_option(alias, "exec_string"):
|
||||
exec_string = exec_string + conf.get(alias, "exec_string")
|
||||
if command:
|
||||
exec_string = exec_string + " " + command
|
||||
# Variables bellow is newer used
|
||||
subprocess.Popen(exec_string, shell=True).communicate()[0]
|
||||
|
||||
|
||||
def HoldConnection(alias):
|
||||
print("Connecting to " + alias + ". Press CTRL+C to cancel.")
|
||||
time.sleep(1)
|
||||
while True:
|
||||
ConnectAlias(alias)
|
||||
time.sleep(5)
|
||||
groups = []
|
||||
connectaliases = []
|
||||
for a in conf.sections():
|
||||
if conf.has_option(a, "group"):
|
||||
groups.append(a)
|
||||
if alias in groups:
|
||||
print("Can't hold connection with group.")
|
||||
else:
|
||||
print("Connecting to " + alias + ". Press CTRL+C to cancel.")
|
||||
time.sleep(1)
|
||||
while True:
|
||||
ConnectAlias(alias)
|
||||
time.sleep(5)
|
||||
|
||||
|
||||
def CMDAdd(alias):
|
||||
alias = alias.split()[0].strip()
|
||||
result = AddNewAlias(alias)
|
||||
if result:
|
||||
if result == True:
|
||||
prompt_add = ("".join(["Enter connection string for new alias ",
|
||||
"(example: ssh user@somehost.com):\n"]))
|
||||
string = ""
|
||||
@@ -87,66 +107,161 @@ def CMDAdd(alias):
|
||||
print(result)
|
||||
|
||||
|
||||
def CMDEdit(alias):
|
||||
if conf.has_section(alias):
|
||||
prompt_edit = ("".join(["Enter connection string for existing alias ",
|
||||
"(example: ssh user@somehost.com):\n"]))
|
||||
def CMDGroup(group):
|
||||
group = group.split()[0].strip()
|
||||
result = AddNewAlias(group)
|
||||
if result == True:
|
||||
prompt_add = ("".join(["Enter aliases for new group ",
|
||||
"(example: alias1 alias2):\n"]))
|
||||
string = ""
|
||||
while string == "":
|
||||
string = input(prompt_edit)
|
||||
SetAliasString(alias, string)
|
||||
string = input(prompt_add)
|
||||
SetGroupString(group, string)
|
||||
else:
|
||||
print("error: '" + alias + "' alias is not exists")
|
||||
print(result)
|
||||
|
||||
|
||||
def CMDEdit(alias):
|
||||
if conf.has_section(alias):
|
||||
if conf.has_option(alias, "exec_string"):
|
||||
prompt_edit = ("".join(["Enter connection string for existing alias ",
|
||||
"(example: ssh user@somehost.com):\n"]))
|
||||
string = ""
|
||||
while string == "":
|
||||
string = input(prompt_edit)
|
||||
SetAliasString(alias, string)
|
||||
elif conf.has_option(alias, "group"):
|
||||
prompt_edit = ("".join(["Enter aliases for existing group ",
|
||||
"(example: alias1 alias2):\n"]))
|
||||
string = ""
|
||||
while string == "":
|
||||
string = input(prompt_edit)
|
||||
SetGroupString(alias, string)
|
||||
else:
|
||||
print("error: '" + alias + "' is not correct alias or group")
|
||||
else:
|
||||
print("error: '" + alias + "' alias or group does not exists")
|
||||
|
||||
|
||||
def CMDPassword(alias):
|
||||
if conf.has_section(alias):
|
||||
prompt_pass = ("[UNSAFE] Enter password for sshpass: ")
|
||||
string = ""
|
||||
string = getpass(prompt_pass)
|
||||
if not string == "":
|
||||
SetPassword(alias, string)
|
||||
groups = []
|
||||
connectaliases = []
|
||||
for a in conf.sections():
|
||||
if conf.has_option(a, "group"):
|
||||
groups.append(a)
|
||||
if alias in groups:
|
||||
print("Can't set password for group.")
|
||||
else:
|
||||
print("error: '" + alias + "' alias is not exists")
|
||||
if conf.has_section(alias):
|
||||
prompt_pass = ("[UNSAFE] Enter password for sshpass (Ctrl+C - cancel, blank - clear password):\n")
|
||||
string = ""
|
||||
string = getpass(prompt_pass)
|
||||
SetPassword(alias, string)
|
||||
else:
|
||||
print("error: '" + alias + "' alias does not exists")
|
||||
|
||||
|
||||
def CMDRemove(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 or group: ")
|
||||
string = input(prompt_remove)
|
||||
if string == "yes":
|
||||
RemoveAliases([alias])
|
||||
else:
|
||||
print("'" + alias + "' alias was not deleted.")
|
||||
print("'" + alias + "' alias or group was not deleted.")
|
||||
else:
|
||||
print("error: '" + alias + "' alias is not exists.")
|
||||
print("error: '" + alias + "' alias or group does not exists.")
|
||||
|
||||
|
||||
def CMDConnect(aliases, command=False):
|
||||
groups = []
|
||||
connectaliases = []
|
||||
for a in conf.sections():
|
||||
if conf.has_option(a, "group"):
|
||||
groups.append(a)
|
||||
for alias in aliases:
|
||||
if alias in groups:
|
||||
group_aliases = conf.get(alias, "group").split()
|
||||
for ga in group_aliases:
|
||||
if not ga in connectaliases:
|
||||
connectaliases.append(ga)
|
||||
else:
|
||||
if not alias in connectaliases:
|
||||
connectaliases.append(alias)
|
||||
for alias in connectaliases:
|
||||
if conf.has_section(alias):
|
||||
print("Connecting to " + alias + "...")
|
||||
ConnectAlias(alias, command)
|
||||
print("... " + alias + " session finished.")
|
||||
else:
|
||||
print("error: '" + alias + "' alias is not exists")
|
||||
print("error: '" + alias + "' alias does not exists")
|
||||
|
||||
|
||||
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 GetTreeList(strings=True, expandlist=True):
|
||||
aliases = []
|
||||
groups = []
|
||||
resultalias = []
|
||||
resultstring = []
|
||||
for a in conf.sections():
|
||||
if conf.has_option(a, "group"):
|
||||
groups.append(a)
|
||||
elif conf.has_option(a, "exec_string"):
|
||||
aliases.append(a)
|
||||
for g in groups:
|
||||
resultalias.append(g)
|
||||
resultstring.append(">> "+g)
|
||||
group_aliases = conf.get(g, "group").split()
|
||||
for ga in group_aliases:
|
||||
if expandlist == False:
|
||||
pass
|
||||
elif expandlist == True or g in expandlist:
|
||||
if conf.has_option(ga, "exec_string"):
|
||||
resultalias.append(ga+" "+g)
|
||||
result = "".join([" ", str(ga), " (", (conf.get(ga, "exec_string") if
|
||||
conf.has_option(ga, "exec_string") else ""), ")",
|
||||
(" [password]" if conf.has_option(ga, "password") else "")])
|
||||
resultstring.append(result)
|
||||
try:
|
||||
aliases.remove(ga)
|
||||
except ValueError:
|
||||
pass
|
||||
for a in aliases:
|
||||
resultalias.append(a)
|
||||
result = "".join([str(a), " (", (conf.get(a, "exec_string") if
|
||||
conf.has_option(a, "exec_string") else ""), ")",
|
||||
(" [password]" if conf.has_option(a, "password") else "")])
|
||||
resultstring.append(result)
|
||||
if strings:
|
||||
return resultstring;
|
||||
else:
|
||||
return resultalias;
|
||||
|
||||
def CMDFullList(option, opt, value, parser):
|
||||
for p in conf.sections():
|
||||
to_print = "".join([str(p), " - ", (conf.get(p, "exec_string") if
|
||||
conf.has_option(p, "exec_string") else ""),
|
||||
(" [password]" if conf.has_option(p, "password") else "")])
|
||||
print(to_print)
|
||||
for p in GetTreeList():
|
||||
print (p)
|
||||
|
||||
|
||||
def CursesConnect(screen, aliases, command=False):
|
||||
curses.endwin()
|
||||
groups = []
|
||||
connectaliases = []
|
||||
for a in conf.sections():
|
||||
if conf.has_option(a, "group"):
|
||||
groups.append(a)
|
||||
for alias in aliases:
|
||||
if alias in groups:
|
||||
group_aliases = conf.get(alias, "group").split()
|
||||
for ga in group_aliases:
|
||||
if not ga in connectaliases:
|
||||
connectaliases.append(ga)
|
||||
else:
|
||||
if not alias in connectaliases:
|
||||
connectaliases.append(alias)
|
||||
for alias in connectaliases:
|
||||
print("Connecting to " + alias + "...")
|
||||
ConnectAlias(alias, command)
|
||||
print("... " + alias + " session finished.")
|
||||
@@ -216,7 +331,7 @@ def CursesPanel(screen, h, w, y, x, text,
|
||||
position = position - 1
|
||||
hidden_password = hidden_password[0:-1]
|
||||
if keych > 31 and keych < 127:
|
||||
hidden_password += curses.keyname(keych)
|
||||
hidden_password += curses.keyname(keych).decode('utf-8')
|
||||
sub_window.addstr(1, position, "*", text_colorpair)
|
||||
if position < w - 4:
|
||||
position += 1
|
||||
@@ -259,24 +374,29 @@ def CMDOptions():
|
||||
opts.add_option('-a', '--add', action="store", type="string",
|
||||
dest="add", metavar="alias", default=False,
|
||||
help="add new alias for connection string")
|
||||
opts.add_option('-g', '--group', action="store", type="string",
|
||||
dest="group", metavar="group", default=False,
|
||||
help="add new group for aliases")
|
||||
opts.add_option('-c', '--command', action="store", type="string",
|
||||
dest="command", metavar="command", default=False,
|
||||
help="add command for executing alias")
|
||||
help="execute command for aliases or group")
|
||||
opts.add_option('-k', '--keep', action="store", type="string",
|
||||
dest="keep", metavar="alias", default=False,
|
||||
help="hold connection with specified alias")
|
||||
opts.add_option('-e', '--edit', action="store", type="string",
|
||||
dest='edit', metavar="alias", default=False,
|
||||
help="edit existing connection string")
|
||||
help="edit existing alias or group")
|
||||
opts.add_option('-p', '--password', action="store", type="string",
|
||||
dest='password', metavar="alias", default=False,
|
||||
help="set and store password for sshpass [UNSAFE]")
|
||||
opts.add_option('-r', '--remove', action="store", type="string",
|
||||
dest='remove', metavar="alias", default=False,
|
||||
help="remove existing alias of connection string")
|
||||
help="remove existing alias or group")
|
||||
options, alias = opts.parse_args()
|
||||
if options.add:
|
||||
CMDAdd(options.add)
|
||||
if options.group:
|
||||
CMDGroup(options.group)
|
||||
if options.edit:
|
||||
CMDEdit(options.edit)
|
||||
if options.password:
|
||||
@@ -294,19 +414,33 @@ def CMDOptions():
|
||||
def CursesMain():
|
||||
help_screen = ("".join([" Press:\n",
|
||||
" 'z'/'x' or arrows - navigation\n",
|
||||
" 'a'/'F2' - add new alias\n",
|
||||
" 'e'/'F4' - edit existing alias\n",
|
||||
" 'a'/'F2' - add new alias (without spaces)\n",
|
||||
" 'g'/'F5' - add new group (spaces will be stripped)\n",
|
||||
" 'e'/'F4' - edit existing alias/group\n",
|
||||
" 'p'/'F6' - set alias's password for sshpass [UNSAFE]\n",
|
||||
" 'space'/'insert' - select\n",
|
||||
" 'r'/'F8' - remove selected alias/aliases\n",
|
||||
" 'c'/'F3' - execute specific command with selected alias/aliases\n",
|
||||
" 'k'/'F7' - hold connection with selected alias\n",
|
||||
" 'enter'/'F9' - connect to selected alias/aliases\n",
|
||||
" 'enter'/'F9' - connect to selected alias/aliases,\n",
|
||||
" expand/collapse group\n",
|
||||
" 'q'/'F10' - quit\n",
|
||||
" Run program with '--help' option to view command line help.\n",
|
||||
" Also, you can edit config file manually:\n",
|
||||
" ", conf_file]))
|
||||
strings = conf.sections()
|
||||
if expand_default == True:
|
||||
groups = []
|
||||
for a in conf.sections():
|
||||
if conf.has_option(a, "group"):
|
||||
groups.append(a)
|
||||
expanded = groups
|
||||
strings = GetTreeList(False, expanded)
|
||||
stringsfull = GetTreeList(True, expanded)
|
||||
elif expand_default == False:
|
||||
groups = []
|
||||
expanded = groups
|
||||
strings = GetTreeList(False, expanded)
|
||||
stringsfull = GetTreeList(True, expanded)
|
||||
row_num = len(strings)
|
||||
selected_strings = [" " for i in range(0, row_num + 1)]
|
||||
screen = curses.initscr()
|
||||
@@ -333,14 +467,7 @@ def CursesMain():
|
||||
box.addnstr(1, 1, "There aren't any aliases yet. Press 'a' to add new one.",
|
||||
width - 6, highlight_text)
|
||||
else:
|
||||
if conf.has_option(strings[i - 1], "password"):
|
||||
password = " [password]"
|
||||
else:
|
||||
password = ""
|
||||
exec_string = ["[", selected_strings[i], "] ", str(i), " ",
|
||||
strings[i - 1], " (", (conf.get(strings[i - 1],
|
||||
"exec_string") if conf.has_option(strings[i - 1],
|
||||
"exec_string") else ""), ")", password]
|
||||
exec_string = ["[", selected_strings[i], "] ", stringsfull[i - 1]]
|
||||
if (i == position):
|
||||
box.addnstr(i, 2, "".join(exec_string), width - 6, highlight_text)
|
||||
else:
|
||||
@@ -361,55 +488,125 @@ def CursesMain():
|
||||
help_screen, normal_text, highlight_text)
|
||||
if key_pressed == ord('a') or key_pressed == ord(
|
||||
'A') or key_pressed == curses.KEY_F2:
|
||||
curses.curs_set(1)
|
||||
new_alias_textpad = CursesTextpad(screen, 1, width - 8,
|
||||
(height // 2) - 1, 4, "Enter new alias:", "",
|
||||
normal_text, highlight_text)
|
||||
add_alias = new_alias_textpad.edit(CursesTextpadConfirm)
|
||||
if not add_alias.rstrip() == "":
|
||||
add_result = AddNewAlias(add_alias.rstrip())
|
||||
if not add_result:
|
||||
CursesPanel(screen, 3,
|
||||
width - 6, (height // 2) - 1, 3, add_result,
|
||||
normal_text, highlight_text)
|
||||
else:
|
||||
add_alias = add_alias.split()[0].strip()
|
||||
if not add_alias == "":
|
||||
add_result = AddNewAlias(add_alias)
|
||||
if add_result == True:
|
||||
add_string = ""
|
||||
while add_string.rstrip() == "":
|
||||
while add_string == "":
|
||||
string_textpad = CursesTextpad(screen, 3,
|
||||
width - 8, (height // 2) - 1, 4,
|
||||
"Enter full execution string:",
|
||||
"ssh ", normal_text, highlight_text)
|
||||
add_string = string_textpad.edit(
|
||||
CursesTextpadConfirm)
|
||||
SetAliasString(add_alias.rstrip(),
|
||||
SetAliasString(add_alias,
|
||||
add_string.replace("\n", "").rstrip())
|
||||
strings = conf.sections()
|
||||
strings = GetTreeList(False, expanded)
|
||||
stringsfull = GetTreeList(True, expanded)
|
||||
row_num = len(strings)
|
||||
selected_strings.append(" ")
|
||||
pages = int(ceil(row_num / max_row))
|
||||
box.refresh()
|
||||
else:
|
||||
curses.curs_set(0)
|
||||
CursesPanel(screen, 3,
|
||||
width - 6, (height // 2) - 1, 3, add_result,
|
||||
normal_text, highlight_text)
|
||||
curses.curs_set(0)
|
||||
if key_pressed == ord('g') or key_pressed == ord(
|
||||
'G') or key_pressed == curses.KEY_F5:
|
||||
curses.curs_set(1)
|
||||
new_group_textpad = CursesTextpad(screen, 1, width - 8,
|
||||
(height // 2) - 1, 4, "Enter group name (without spaces):", "",
|
||||
normal_text, highlight_text)
|
||||
add_group = new_group_textpad.edit(CursesTextpadConfirm)
|
||||
add_group = add_group.split()[0].strip()
|
||||
if not add_group == "":
|
||||
add_result = AddNewAlias(add_group)
|
||||
if add_result == True:
|
||||
add_string = ""
|
||||
while add_string.rstrip() == "":
|
||||
string_textpad = CursesTextpad(screen, 3,
|
||||
width - 8, (height // 2) - 1, 4,
|
||||
"Enter aliases for new group (example: alias1 alias2):",
|
||||
"", normal_text, highlight_text)
|
||||
add_string = string_textpad.edit(
|
||||
CursesTextpadConfirm)
|
||||
SetGroupString(add_group,
|
||||
add_string.replace("\n", "").rstrip())
|
||||
expanded.append(add_group)
|
||||
strings = GetTreeList(False, expanded)
|
||||
stringsfull = GetTreeList(True, expanded)
|
||||
row_num = len(strings)
|
||||
selected_strings = [" " for i in range(0, row_num + 1)]
|
||||
pages = int(ceil(row_num / max_row))
|
||||
box.refresh()
|
||||
else:
|
||||
curses.curs_set(0)
|
||||
CursesPanel(screen, 3,
|
||||
width - 6, (height // 2) - 1, 3, add_result,
|
||||
normal_text, highlight_text)
|
||||
curses.curs_set(0)
|
||||
if (key_pressed == ord('e') or key_pressed == ord(
|
||||
'E') or key_pressed == curses.KEY_F4) and row_num != 0:
|
||||
edit_string = ""
|
||||
while edit_string.rstrip() == "":
|
||||
string_textpad = CursesTextpad(screen, 3, width - 8,
|
||||
(height // 2) - 1, 4, "Enter new execution string:",
|
||||
(conf.get(strings[position - 1],
|
||||
"exec_string") if conf.has_option(strings[position - 1],
|
||||
"exec_string") else ""),
|
||||
normal_text, highlight_text)
|
||||
edit_string = string_textpad.edit(CursesTextpadConfirm)
|
||||
SetAliasString(strings[position - 1],
|
||||
edit_string.replace("\n", "").rstrip())
|
||||
strings = conf.sections()
|
||||
groups = []
|
||||
for a in conf.sections():
|
||||
if conf.has_option(a, "group"):
|
||||
groups.append(a)
|
||||
curses.curs_set(1)
|
||||
if strings[position - 1] in groups:
|
||||
while edit_string.rstrip() == "":
|
||||
string_textpad = CursesTextpad(screen, 3, width - 8,
|
||||
(height // 2) - 1, 4, "Enter new aliases for existing group:",
|
||||
(conf.get(strings[position - 1],
|
||||
"group") if conf.has_option(strings[position - 1],
|
||||
"group") else ""),
|
||||
normal_text, highlight_text)
|
||||
edit_string = string_textpad.edit(CursesTextpadConfirm)
|
||||
SetGroupString(strings[position - 1],
|
||||
edit_string.replace("\n", "").rstrip())
|
||||
strings = GetTreeList(False, expanded)
|
||||
stringsfull = GetTreeList(True, expanded)
|
||||
row_num = len(strings)
|
||||
selected_strings.append(" ")
|
||||
pages = int(ceil(row_num / max_row))
|
||||
box.refresh()
|
||||
else:
|
||||
while edit_string.rstrip() == "":
|
||||
string_textpad = CursesTextpad(screen, 3, width - 8,
|
||||
(height // 2) - 1, 4, "Enter new execution string:",
|
||||
(conf.get(strings[position - 1].split()[0].strip(),
|
||||
"exec_string") if conf.has_option(strings[position - 1].split()[0].strip(),
|
||||
"exec_string") else ""),
|
||||
normal_text, highlight_text)
|
||||
edit_string = string_textpad.edit(CursesTextpadConfirm)
|
||||
SetAliasString(strings[position - 1].split()[0].strip(),
|
||||
edit_string.replace("\n", "").rstrip())
|
||||
strings = GetTreeList(False, expanded)
|
||||
stringsfull = GetTreeList(True, expanded)
|
||||
curses.curs_set(0)
|
||||
if (key_pressed == ord('p') or key_pressed == ord(
|
||||
'P') or key_pressed == curses.KEY_F6) and row_num != 0:
|
||||
set_password = ""
|
||||
set_password = CursesPanel(screen, 4, width - 6,
|
||||
(height // 2) - 1, 3,
|
||||
" Enter user password for sshpass and press 'enter':\n>",
|
||||
normal_text, highlight_text, "password")
|
||||
if not set_password == "":
|
||||
SetPassword(strings[position - 1], set_password)
|
||||
groups = []
|
||||
for a in conf.sections():
|
||||
if conf.has_option(a, "group"):
|
||||
groups.append(a)
|
||||
if not strings[position - 1].split()[0].strip() in groups:
|
||||
set_password = ""
|
||||
set_password = CursesPanel(screen, 4, width - 6,
|
||||
(height // 2) - 1, 3,
|
||||
" Enter user password for sshpass and press 'enter':\n>",
|
||||
normal_text, highlight_text, "password")
|
||||
SetPassword(strings[position - 1].split()[0].strip(), set_password)
|
||||
strings = GetTreeList(False, expanded)
|
||||
stringsfull = GetTreeList(True, expanded)
|
||||
if (key_pressed == ord('r') or key_pressed == ord(
|
||||
'R') or key_pressed == curses.KEY_F8 or key_pressed == (
|
||||
curses.KEY_DC)) and row_num != 0:
|
||||
@@ -423,14 +620,15 @@ def CursesMain():
|
||||
str(len(selected)), " selected aliases? (y/N)"]))
|
||||
else:
|
||||
remove_confirm = ("".join(["Are you sure to remove '",
|
||||
strings[position - 1], "' alias? (y/N)"]))
|
||||
selected.append(strings[position - 1])
|
||||
strings[position - 1].split()[0].strip(), "' alias? (y/N)"]))
|
||||
selected.append(strings[position - 1].split()[0].strip())
|
||||
remove_result = CursesPanel(screen, 4, width - 6,
|
||||
(height // 2) - 1, 3, remove_confirm, normal_text,
|
||||
highlight_text, "remove")
|
||||
if remove_result == "confirm":
|
||||
RemoveAliases(selected)
|
||||
strings = conf.sections()
|
||||
strings = GetTreeList(False, expanded)
|
||||
stringsfull = GetTreeList(True, expanded)
|
||||
row_num = len(strings)
|
||||
selected_strings = [" " for i in range(0, row_num + 1)]
|
||||
pages = int(ceil(row_num / max_row))
|
||||
@@ -444,7 +642,8 @@ def CursesMain():
|
||||
if selected_strings[i] == "*":
|
||||
selected.append(strings[i - 1])
|
||||
if not len(selected) > 0:
|
||||
selected.append(strings[position - 1])
|
||||
selected.append(strings[position - 1].split()[0].strip())
|
||||
curses.curs_set(1)
|
||||
command_textpad = CursesTextpad(screen, 3, width - 8,
|
||||
(height // 2) - 1, 4,
|
||||
"".join([
|
||||
@@ -454,19 +653,42 @@ def CursesMain():
|
||||
command_string = command_textpad.edit(CursesTextpadConfirm)
|
||||
CursesConnect(screen, selected,
|
||||
command_string.replace("\n", "").rstrip())
|
||||
curses.curs_set(0)
|
||||
if (key_pressed == ord('k') or key_pressed == ord('K') or
|
||||
key_pressed == (curses.KEY_F7)) and row_num != 0:
|
||||
curses.endwin()
|
||||
HoldConnection(strings[position - 1])
|
||||
groups = []
|
||||
for a in conf.sections():
|
||||
if conf.has_option(a, "group"):
|
||||
groups.append(a)
|
||||
if not strings[position - 1] in groups:
|
||||
curses.endwin()
|
||||
HoldConnection(strings[position - 1].split()[0].strip())
|
||||
if (key_pressed == ord("\n") or key_pressed == (
|
||||
curses.KEY_F9)) and row_num != 0:
|
||||
selected = []
|
||||
for i in range(1, row_num + 1):
|
||||
if selected_strings[i] == "*":
|
||||
selected.append(strings[i - 1])
|
||||
if not len(selected) > 0:
|
||||
selected.append(strings[position - 1])
|
||||
CursesConnect(screen, selected)
|
||||
groups = []
|
||||
for a in conf.sections():
|
||||
if conf.has_option(a, "group"):
|
||||
groups.append(a)
|
||||
if strings[position - 1] in groups:
|
||||
if strings[position - 1] in expanded:
|
||||
expanded.remove(strings[position - 1])
|
||||
else:
|
||||
expanded.append(strings[position - 1])
|
||||
strings = GetTreeList(False, expanded)
|
||||
stringsfull = GetTreeList(True, expanded)
|
||||
row_num = len(strings)
|
||||
selected_strings.append(" ")
|
||||
pages = int(ceil(row_num / max_row))
|
||||
box.refresh()
|
||||
else:
|
||||
selected = []
|
||||
for i in range(1, row_num + 1):
|
||||
if selected_strings[i] == "*":
|
||||
selected.append(strings[i - 1])
|
||||
if not len(selected) > 0:
|
||||
selected.append(strings[position - 1].split()[0].strip())
|
||||
CursesConnect(screen, selected)
|
||||
selected_strings = [" " for i in range(0, row_num + 1)]
|
||||
if (key_pressed == 32 or key_pressed == (
|
||||
curses.KEY_IC)) and row_num != 0:
|
||||
if selected_strings[position] == ' ':
|
||||
@@ -528,6 +750,12 @@ def CursesMain():
|
||||
if page < pages:
|
||||
page = page + 1
|
||||
position = (1 + (max_row * (page - 1)))
|
||||
if key_pressed == curses.KEY_HOME:
|
||||
page = 1
|
||||
position = 1
|
||||
if key_pressed == curses.KEY_END:
|
||||
page = pages
|
||||
position = row_num
|
||||
box.erase()
|
||||
screen.border(0)
|
||||
box.border(0)
|
||||
@@ -537,14 +765,7 @@ def CursesMain():
|
||||
box.addnstr(1, 1, "There aren't any aliases yet. Press 'a' to add new one.",
|
||||
width - 6, highlight_text)
|
||||
else:
|
||||
if conf.has_option(strings[i - 1], "password"):
|
||||
password = " [password]"
|
||||
else:
|
||||
password = ""
|
||||
exec_string = ["[", selected_strings[i], "] ", str(i), " ",
|
||||
strings[i - 1], " (", (conf.get(strings[i - 1],
|
||||
"exec_string") if conf.has_option(strings[i - 1],
|
||||
"exec_string") else ""), ")", password]
|
||||
exec_string = ["[", selected_strings[i], "] ", stringsfull[i - 1]]
|
||||
if (i + (max_row * (page - 1)) == (position + (max_row * (page - 1)))):
|
||||
box.addnstr(i - (max_row * (page - 1)), 2, "".join(
|
||||
exec_string), width - 6, highlight_text)
|
||||
|
||||
Reference in New Issue
Block a user