mirror of
https://github.com/rwinkhart/sshyp.git
synced 2026-08-27 20:36:27 -04:00
Moved settings-related functions (anything that uses curses) to their own library
Former-commit-id: 95a43d9258c716c49e44020ffaec50a4b03eaaa6 Former-commit-id: 734e5249c491f87fb688651954a0ce84cd6f874e
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
#!/bin/sh
|
||||
git add -f extra lib/sshyp.py lib/sshync.py port-jobs share LICENSE README.md package.sh commit.sh .gitignore
|
||||
git add -f extra lib/sshyp.py lib/sshync.py lib/stweak.py port-jobs share LICENSE README.md package.sh commit.sh .gitignore
|
||||
git commit -m "$1"
|
||||
git push
|
||||
|
||||
Executable → Regular
+6
-205
@@ -3,8 +3,8 @@ from os import chmod, environ, listdir, remove, walk
|
||||
from os.path import exists, expanduser, isdir, isfile, realpath
|
||||
from pathlib import Path
|
||||
from random import randint
|
||||
from shutil import get_terminal_size, move, rmtree
|
||||
from sshync import delete as offline_delete, run_profile, make_profile, get_profile
|
||||
from shutil import move, rmtree
|
||||
from sshync import delete as offline_delete, run_profile, get_profile
|
||||
from subprocess import CalledProcessError, DEVNULL, PIPE, run
|
||||
from sys import argv, exit as s_exit
|
||||
# PORT START UNAME-IMPORT
|
||||
@@ -14,8 +14,10 @@ home = expanduser("~")
|
||||
|
||||
|
||||
# UTILITY FUNCTIONS
|
||||
|
||||
# generates and prints full entry list
|
||||
def entry_list_gen(_directory=f"{home}/.local/share/sshyp/"):
|
||||
from shutil import get_terminal_size
|
||||
from textwrap import fill
|
||||
_ran = False
|
||||
print("\nfor a list of usable commands, run 'sshyp help'\n\n\u001b[38;5;0;48;5;15msshyp entries:\u001b[0m\n")
|
||||
@@ -214,206 +216,7 @@ def copy_id_check(_port, _username_ssh, _ip, _client_device_id):
|
||||
return False
|
||||
|
||||
|
||||
# creates a radio selection between the provided options
|
||||
def settings_radio(_stdscr, _options, _pretext):
|
||||
curses.curs_set(0)
|
||||
_selected = 0
|
||||
while True:
|
||||
_stdscr.clear()
|
||||
_stdscr.addstr(0, 0, _pretext, curses.A_BOLD)
|
||||
for _i, _option in enumerate(_options):
|
||||
_y = _i + 2
|
||||
if _i == _selected:
|
||||
_stdscr.addstr(_y, 0, "[*] " + _option, curses.A_REVERSE)
|
||||
else:
|
||||
_stdscr.addstr(_y, 0, "[ ] " + _option)
|
||||
_stdscr.refresh()
|
||||
_key = _stdscr.getch()
|
||||
# update _selected based on user input
|
||||
if _key == curses.KEY_UP:
|
||||
_selected = (_selected - 1) % len(_options)
|
||||
elif _key == curses.KEY_DOWN:
|
||||
_selected = (_selected + 1) % len(_options)
|
||||
elif _key == ord('\n'):
|
||||
break
|
||||
_stdscr.refresh()
|
||||
curses.curs_set(1)
|
||||
return _selected
|
||||
|
||||
|
||||
# creates a text-box input
|
||||
def settings_text(_stdscr, _pretext):
|
||||
_stdscr.clear()
|
||||
_stdscr.addstr(0, 0, _pretext)
|
||||
_term_columns = get_terminal_size()[0]
|
||||
_editwin = curses.newwin(1, _term_columns-2, 3, 1)
|
||||
rectangle(_stdscr, 2, 0, 4, _term_columns-1)
|
||||
_stdscr.refresh()
|
||||
_box = Textbox(_editwin)
|
||||
# let the user edit until ctrl+g/enter is struck
|
||||
_box.edit()
|
||||
# return resulting contents
|
||||
return _box.gather().strip()
|
||||
|
||||
|
||||
# cleanly terminates curses
|
||||
def settings_terminate(_stdscr):
|
||||
curses.nocbreak()
|
||||
_stdscr.keypad(False) # TODO Needed??
|
||||
curses.echo()
|
||||
curses.endwin()
|
||||
|
||||
|
||||
# ARGUMENT-SPECIFIC FUNCTIONS
|
||||
# runs configuration wizard
|
||||
def settings():
|
||||
# set to avoid PEP8 warnings
|
||||
_sshyp_data = None
|
||||
# config directory creation
|
||||
Path(f"{home}/.config/sshyp/devices").mkdir(mode=0o700, parents=True, exist_ok=True)
|
||||
|
||||
# temporary file symlink creation
|
||||
if not exists(f"{home}/.config/sshyp/tmp"):
|
||||
from os import symlink
|
||||
# PORT START UNAME-TMP
|
||||
if uname()[0] in ('Haiku', 'FreeBSD', 'Darwin'):
|
||||
symlink('/tmp', f"{home}/.config/sshyp/tmp")
|
||||
elif exists('/data/data/com.termux'):
|
||||
symlink('/data/data/com.termux/files/usr/tmp', f"{home}/.config/sshyp/tmp")
|
||||
else:
|
||||
symlink('/dev/shm', f"{home}/.config/sshyp/tmp")
|
||||
# PORT END UNAME-TMP
|
||||
|
||||
# curses initialization
|
||||
_stdscr = curses.initscr()
|
||||
curses.noecho()
|
||||
curses.cbreak()
|
||||
_stdscr.keypad(True)
|
||||
|
||||
# curses menu tree
|
||||
try:
|
||||
# device+sync type selection
|
||||
# PORT START TWEAK-DEVTYPE
|
||||
_install_type = settings_radio(_stdscr, ('server', 'client (ssh-synchronized)', 'client (offline)'),
|
||||
'device + sync type configuration')
|
||||
if _install_type == 0:
|
||||
_sshyp_data = ['server']
|
||||
Path(f"{home}/.config/sshyp/deleted").mkdir(mode=0o700, exist_ok=True)
|
||||
Path(f"{home}/.config/sshyp/whitelist").mkdir(mode=0o700, exist_ok=True)
|
||||
settings_terminate(_stdscr)
|
||||
print(f"\nmake sure the ssh service is running and properly configured")
|
||||
else:
|
||||
_offline_mode = False
|
||||
if _install_type == 2:
|
||||
_offline_mode = True
|
||||
_sshyp_data = ['client']
|
||||
Path(f"{home}/.local/share/sshyp").mkdir(mode=0o700, parents=True, exist_ok=True)
|
||||
# PORT END TWEAK-DEVTYPE
|
||||
|
||||
# gpg key selection
|
||||
_uid_list = [_item for _item in run(['gpg', '-k', '--with-colons'],
|
||||
stdout=PIPE, text=True).stdout.splitlines() if _item.startswith('uid')]
|
||||
_clean_uid_list = []
|
||||
for _uid in _uid_list:
|
||||
_clean_uid_list.append(sub(r':+', ':', _uid).split(':')[4])
|
||||
_clean_uid_list.append('auto-generate')
|
||||
_gpg_id_sel = settings_radio(_stdscr, _clean_uid_list, 'gpg key selection')
|
||||
_gpg_id = _clean_uid_list[_gpg_id_sel]
|
||||
if _gpg_id == 'auto-generate':
|
||||
print('\na unique gpg key is being generated for you...')
|
||||
if not isfile(f"{home}/.config/sshyp/gpg-gen"):
|
||||
open(f"{home}/.config/sshyp/gpg-gen", 'w').writelines([
|
||||
'Key-Type: 1\n', 'Key-Length: 4096\n', 'Key-Usage: sign encrypt\n', 'Name-Real: sshyp\n',
|
||||
'Name-Comment: gpg-sshyp\n', 'Name-Email: https://github.com/rwinkhart/sshyp\n',
|
||||
'Expire-Date: 0'])
|
||||
run(['gpg', '--batch', '--generate-key', f"{home}/.config/sshyp/gpg-gen"])
|
||||
remove(f"{home}/.config/sshyp/gpg-gen")
|
||||
_sshyp_data.append(run(['gpg', '-k'], stdout=PIPE, text=True).stdout.splitlines()[-3].strip())
|
||||
else:
|
||||
_sshyp_data.append(_gpg_id)
|
||||
|
||||
# text editor configuration
|
||||
_sshyp_data.append(settings_text(_stdscr, 'enter the name of your preferred text editor:\n\n\n\n\n'
|
||||
'(ctrl+g/enter to confirm)\n\nexample input: vim'))
|
||||
# lock file generation
|
||||
if isfile(f"{home}/.config/sshyp/lock.gpg"):
|
||||
remove(f"{home}/.config/sshyp/lock.gpg")
|
||||
open(f"{home}/.config/sshyp/lock", 'w')
|
||||
run(['gpg', '-qr', str(_sshyp_data[1]), '-e', f"{home}/.config/sshyp/lock"])
|
||||
remove(f"{home}/.config/sshyp/lock")
|
||||
|
||||
# ssh configuration
|
||||
if not _offline_mode:
|
||||
_uiport = settings_text(_stdscr, 'enter the username, ip, and ssh port of your sshyp server:\n\n\n\n\n('
|
||||
'ctrl+g/enter to confirm)\n\nexample inputs:\n\n ipv4: user@10.10.10.'
|
||||
'10:22\n ipv6: user@[2000:2000:2000:2000:2000:2000:2000:2000]:22\n '
|
||||
'domain: user@mydomain.com:22').lstrip('[').replace(']', '')
|
||||
_uiport_split = _uiport.split('@')
|
||||
_username_ssh = _uiport_split[0]
|
||||
_iport = _uiport_split[1].rsplit(':', 1)
|
||||
|
||||
# sshync profile generation
|
||||
make_profile(f"{home}/.config/sshyp/sshyp.sshync",
|
||||
f"{home}/.local/share/sshyp/", f"/home/{_username_ssh}/.local/share/sshyp/",
|
||||
f"{home}/.ssh/sshyp", _iport[0], _iport[1], _username_ssh)
|
||||
|
||||
# device id configuration
|
||||
# remove existing device id
|
||||
for _id in listdir(f"{home}/.config/sshyp/devices"):
|
||||
remove(f"{home}/.config/sshyp/devices/{_id}")
|
||||
_device_id_prefix = settings_text(_stdscr, 'name this device:\n\n\n\n\n(ctrl+g/enter to confirm)\n\n'
|
||||
'important:\u001b[0m this id \u001b[4;1mmust\u001b[0m be '
|
||||
'unique amongst your client devices\n\nthis is used to keep '
|
||||
'track of database syncing and quick-unlock permissions\n')
|
||||
_device_id_suffix = string_gen('f', randint(24, 48))
|
||||
_device_id = _device_id_prefix + '-' + _device_id_suffix
|
||||
open(f"{home}/.config/sshyp/devices/{_device_id}", 'w')
|
||||
|
||||
# quick-unlock configuration
|
||||
_quick_unlock_sel = settings_radio(_stdscr, ('yes', 'no'), 'enable quick-unlock?')
|
||||
if _quick_unlock_sel == 0:
|
||||
_sshyp_data.append('yes')
|
||||
else:
|
||||
_sshyp_data.append('no')
|
||||
|
||||
settings_terminate(_stdscr)
|
||||
|
||||
# test server connection and attempt to register device id
|
||||
copy_id_check(_iport[1], _username_ssh, _iport[0], _device_id)
|
||||
|
||||
else:
|
||||
if isfile(f"{home}/.config/sshyp/sshyp.sshync"):
|
||||
remove(f"{home}/.config/sshyp/sshyp.sshync")
|
||||
settings_terminate(_stdscr)
|
||||
|
||||
# PORT START CLIPTOOL
|
||||
# check for clipboard tool and display warning if missing
|
||||
if uname()[0] in ('Linux', 'FreeBSD'):
|
||||
if 'WAYLAND_DISPLAY' in environ:
|
||||
_display_server, _clipboard_tool, _clipboard_package = 'Wayland', 'wl-copy', 'wl-clipboard'
|
||||
else:
|
||||
_display_server, _clipboard_tool, _clipboard_package = 'X11', 'xclip', 'xclip'
|
||||
from shutil import which
|
||||
if which(_clipboard_tool) is None:
|
||||
print(f'\n\u001b[38;5;9mwarning: you are using {_display_server} and "{_clipboard_tool}" is not '
|
||||
f'present - \ncopying entry fields will not function until '
|
||||
f'"{_clipboard_package}" is installed\u001b[0m')
|
||||
# PORT END CLIPTOOL
|
||||
|
||||
except KeyboardInterrupt:
|
||||
settings_terminate(_stdscr)
|
||||
|
||||
# write main config file (sshyp-data)
|
||||
with open(f"{home}/.config/sshyp/sshyp-data", 'w') as _config_file:
|
||||
_lines = 0
|
||||
for _item in _sshyp_data:
|
||||
_lines += 1
|
||||
_config_file.write(str(_item) + '\n')
|
||||
while _lines < 4:
|
||||
_lines += 1
|
||||
_config_file.write('n')
|
||||
print('\nconfiguration complete\n')
|
||||
|
||||
|
||||
# prints help text based on argument
|
||||
def print_info():
|
||||
@@ -945,10 +748,8 @@ if __name__ == "__main__":
|
||||
print('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n')
|
||||
s_exit(1)
|
||||
else:
|
||||
import curses
|
||||
from curses.textpad import Textbox, rectangle
|
||||
from re import sub
|
||||
settings()
|
||||
import stweak
|
||||
stweak.settings()
|
||||
s_exit()
|
||||
|
||||
# run function based on arguments
|
||||
|
||||
+215
@@ -0,0 +1,215 @@
|
||||
#!/usr/bin/env python3
|
||||
from curses import curs_set, newwin, A_BOLD, A_REVERSE, KEY_UP, KEY_DOWN, noecho, nocbreak, endwin, initscr, cbreak
|
||||
from curses.textpad import rectangle, Textbox
|
||||
from os import environ, listdir, remove, symlink
|
||||
from pathlib import Path
|
||||
from random import randint
|
||||
from re import sub
|
||||
from shutil import get_terminal_size, which
|
||||
from sshync import make_profile
|
||||
from sshyp import copy_id_check, string_gen
|
||||
from subprocess import run, PIPE
|
||||
# PORT START UNAME-IMPORT
|
||||
from os import uname
|
||||
from os.path import exists, expanduser, isfile
|
||||
# PORT END UNAME-IMPORT
|
||||
home = expanduser("~")
|
||||
|
||||
|
||||
# creates a radio selection between the provided options
|
||||
def settings_radio(_stdscr, _options, _pretext):
|
||||
curs_set(0)
|
||||
_selected = 0
|
||||
while True:
|
||||
_stdscr.clear()
|
||||
_stdscr.addstr(0, 0, _pretext, A_BOLD)
|
||||
for _i, _option in enumerate(_options):
|
||||
_y = _i + 2
|
||||
if _i == _selected:
|
||||
_stdscr.addstr(_y, 0, "[*] " + _option, A_REVERSE)
|
||||
else:
|
||||
_stdscr.addstr(_y, 0, "[ ] " + _option)
|
||||
_stdscr.refresh()
|
||||
_key = _stdscr.getch()
|
||||
# update _selected based on user input
|
||||
if _key == KEY_UP:
|
||||
_selected = (_selected - 1) % len(_options)
|
||||
elif _key == KEY_DOWN:
|
||||
_selected = (_selected + 1) % len(_options)
|
||||
elif _key == ord('\n'):
|
||||
break
|
||||
_stdscr.refresh()
|
||||
curs_set(1)
|
||||
return _selected
|
||||
|
||||
|
||||
# creates a text-box input
|
||||
def settings_text(_stdscr, _pretext):
|
||||
_stdscr.clear()
|
||||
_stdscr.addstr(0, 0, _pretext)
|
||||
_term_columns = get_terminal_size()[0]
|
||||
_editwin = newwin(1, _term_columns - 2, 3, 1)
|
||||
rectangle(_stdscr, 2, 0, 4, _term_columns - 1)
|
||||
_stdscr.refresh()
|
||||
_box = Textbox(_editwin)
|
||||
# let the user edit until ctrl+g/enter is struck
|
||||
_box.edit()
|
||||
# return resulting contents
|
||||
return _box.gather().strip()
|
||||
|
||||
|
||||
# cleanly terminates curses
|
||||
def settings_terminate(_stdscr):
|
||||
nocbreak()
|
||||
_stdscr.keypad(False) # TODO Needed??
|
||||
noecho()
|
||||
endwin()
|
||||
|
||||
|
||||
# ARGUMENT-SPECIFIC FUNCTIONS
|
||||
# runs configuration wizard
|
||||
def settings():
|
||||
# set to avoid PEP8 warnings
|
||||
_sshyp_data = None
|
||||
# config directory creation
|
||||
Path(f"{home}/.config/sshyp/devices").mkdir(mode=0o700, parents=True, exist_ok=True)
|
||||
|
||||
# temporary file symlink creation
|
||||
if not exists(f"{home}/.config/sshyp/tmp"):
|
||||
# PORT START UNAME-TMP
|
||||
if uname()[0] in ('Haiku', 'FreeBSD', 'Darwin'):
|
||||
symlink('/tmp', f"{home}/.config/sshyp/tmp")
|
||||
elif exists('/data/data/com.termux'):
|
||||
symlink('/data/data/com.termux/files/usr/tmp', f"{home}/.config/sshyp/tmp")
|
||||
else:
|
||||
symlink('/dev/shm', f"{home}/.config/sshyp/tmp")
|
||||
# PORT END UNAME-TMP
|
||||
|
||||
# curses initialization
|
||||
_stdscr = initscr()
|
||||
noecho()
|
||||
cbreak()
|
||||
_stdscr.keypad(True)
|
||||
|
||||
# curses menu tree
|
||||
try:
|
||||
# device+sync type selection
|
||||
# PORT START TWEAK-DEVTYPE
|
||||
_install_type = settings_radio(_stdscr, ('server', 'client (ssh-synchronized)', 'client (offline)'),
|
||||
'device + sync type configuration')
|
||||
if _install_type == 0:
|
||||
_sshyp_data = ['server']
|
||||
Path(f"{home}/.config/sshyp/deleted").mkdir(mode=0o700, exist_ok=True)
|
||||
Path(f"{home}/.config/sshyp/whitelist").mkdir(mode=0o700, exist_ok=True)
|
||||
settings_terminate(_stdscr)
|
||||
print(f"\nmake sure the ssh service is running and properly configured")
|
||||
else:
|
||||
_offline_mode = False
|
||||
if _install_type == 2:
|
||||
_offline_mode = True
|
||||
_sshyp_data = ['client']
|
||||
Path(f"{home}/.local/share/sshyp").mkdir(mode=0o700, parents=True, exist_ok=True)
|
||||
# PORT END TWEAK-DEVTYPE
|
||||
|
||||
# gpg key selection
|
||||
_uid_list = [_item for _item in run(['gpg', '-k', '--with-colons'],
|
||||
stdout=PIPE, text=True).stdout.splitlines() if _item.startswith('uid')]
|
||||
_clean_uid_list = []
|
||||
for _uid in _uid_list:
|
||||
_clean_uid_list.append(sub(r':+', ':', _uid).split(':')[4])
|
||||
_clean_uid_list.append('auto-generate')
|
||||
_gpg_id_sel = settings_radio(_stdscr, _clean_uid_list, 'gpg key selection')
|
||||
_gpg_id = _clean_uid_list[_gpg_id_sel]
|
||||
if _gpg_id == 'auto-generate':
|
||||
print('\na unique gpg key is being generated for you...')
|
||||
if not isfile(f"{home}/.config/sshyp/gpg-gen"):
|
||||
open(f"{home}/.config/sshyp/gpg-gen", 'w').writelines([
|
||||
'Key-Type: 1\n', 'Key-Length: 4096\n', 'Key-Usage: sign encrypt\n', 'Name-Real: sshyp\n',
|
||||
'Name-Comment: gpg-sshyp\n', 'Name-Email: https://github.com/rwinkhart/sshyp\n',
|
||||
'Expire-Date: 0'])
|
||||
run(['gpg', '--batch', '--generate-key', f"{home}/.config/sshyp/gpg-gen"])
|
||||
remove(f"{home}/.config/sshyp/gpg-gen")
|
||||
_sshyp_data.append(run(['gpg', '-k'], stdout=PIPE, text=True).stdout.splitlines()[-3].strip())
|
||||
else:
|
||||
_sshyp_data.append(_gpg_id)
|
||||
|
||||
# text editor configuration
|
||||
_sshyp_data.append(settings_text(_stdscr, 'enter the name of your preferred text editor:\n\n\n\n\n'
|
||||
'(ctrl+g/enter to confirm)\n\nexample input: vim'))
|
||||
# lock file generation
|
||||
if isfile(f"{home}/.config/sshyp/lock.gpg"):
|
||||
remove(f"{home}/.config/sshyp/lock.gpg")
|
||||
open(f"{home}/.config/sshyp/lock", 'w')
|
||||
run(['gpg', '-qr', str(_sshyp_data[1]), '-e', f"{home}/.config/sshyp/lock"])
|
||||
remove(f"{home}/.config/sshyp/lock")
|
||||
|
||||
# ssh configuration
|
||||
if not _offline_mode:
|
||||
_uiport = settings_text(_stdscr, 'enter the username, ip, and ssh port of your sshyp server:\n\n\n\n\n('
|
||||
'ctrl+g/enter to confirm)\n\nexample inputs:\n\n ipv4: user@10.10.10.'
|
||||
'10:22\n ipv6: user@[2000:2000:2000:2000:2000:2000:2000:2000]:22\n '
|
||||
'domain: user@mydomain.com:22').lstrip('[').replace(']', '')
|
||||
_uiport_split = _uiport.split('@')
|
||||
_username_ssh = _uiport_split[0]
|
||||
_iport = _uiport_split[1].rsplit(':', 1)
|
||||
|
||||
# sshync profile generation
|
||||
make_profile(f"{home}/.config/sshyp/sshyp.sshync",
|
||||
f"{home}/.local/share/sshyp/", f"/home/{_username_ssh}/.local/share/sshyp/",
|
||||
f"{home}/.ssh/sshyp", _iport[0], _iport[1], _username_ssh)
|
||||
|
||||
# device id configuration
|
||||
# remove existing device id
|
||||
for _id in listdir(f"{home}/.config/sshyp/devices"):
|
||||
remove(f"{home}/.config/sshyp/devices/{_id}")
|
||||
_device_id_prefix = settings_text(_stdscr, 'name this device:\n\n\n\n\n(ctrl+g/enter to confirm)\n\n'
|
||||
'important:\u001b[0m this id \u001b[4;1mmust\u001b[0m be '
|
||||
'unique amongst your client devices\n\nthis is used to keep '
|
||||
'track of database syncing and quick-unlock permissions\n')
|
||||
_device_id_suffix = string_gen('f', randint(24, 48))
|
||||
_device_id = _device_id_prefix + '-' + _device_id_suffix
|
||||
open(f"{home}/.config/sshyp/devices/{_device_id}", 'w')
|
||||
|
||||
# quick-unlock configuration
|
||||
_quick_unlock_sel = settings_radio(_stdscr, ('yes', 'no'), 'enable quick-unlock?')
|
||||
if _quick_unlock_sel == 0:
|
||||
_sshyp_data.append('yes')
|
||||
else:
|
||||
_sshyp_data.append('no')
|
||||
|
||||
settings_terminate(_stdscr)
|
||||
|
||||
# test server connection and attempt to register device id
|
||||
copy_id_check(_iport[1], _username_ssh, _iport[0], _device_id)
|
||||
|
||||
else:
|
||||
if isfile(f"{home}/.config/sshyp/sshyp.sshync"):
|
||||
remove(f"{home}/.config/sshyp/sshyp.sshync")
|
||||
settings_terminate(_stdscr)
|
||||
|
||||
# PORT START CLIPTOOL
|
||||
# check for clipboard tool and display warning if missing
|
||||
if uname()[0] in ('Linux', 'FreeBSD'):
|
||||
if 'WAYLAND_DISPLAY' in environ:
|
||||
_display_server, _clipboard_tool, _clipboard_package = 'Wayland', 'wl-copy', 'wl-clipboard'
|
||||
else:
|
||||
_display_server, _clipboard_tool, _clipboard_package = 'X11', 'xclip', 'xclip'
|
||||
if which(_clipboard_tool) is None:
|
||||
print(f'\n\u001b[38;5;9mwarning: you are using {_display_server} and "{_clipboard_tool}" is not '
|
||||
f'present - \ncopying entry fields will not function until '
|
||||
f'"{_clipboard_package}" is installed\u001b[0m')
|
||||
# PORT END CLIPTOOL
|
||||
|
||||
except KeyboardInterrupt:
|
||||
settings_terminate(_stdscr)
|
||||
|
||||
# write main config file (sshyp-data)
|
||||
with open(f"{home}/.config/sshyp/sshyp-data", 'w') as _config_file:
|
||||
_lines = 0
|
||||
for _item in _sshyp_data:
|
||||
_lines += 1
|
||||
_config_file.write(str(_item) + '\n')
|
||||
while _lines < 4:
|
||||
_lines += 1
|
||||
_config_file.write('n')
|
||||
print('\nconfiguration complete\n')
|
||||
Reference in New Issue
Block a user