import gc
import math
import os
import re
import sys
import time
APPLICATION_AUTHORS = ["Tuuuux"]
APPLICATION_DESCRIPTION = ""
APPLICATION_LICENSE = "License WTFPL v2"
APPLICATION_NAME = "glxsh"
APPLICATION_VERSION = "0.2.5"
APPLICATION_WARRANTY = "Copyright (C) 2020-2022 Galaxie Shell Project.\nLicense WTFPL Version 2, December 2004 <http://www.wtfpl.net/about/>.\nThis is free software: you are free to change and redistribute it.\nThere is NO WARRANTY, to the extent permitted by law.\n"
def size_of(size, suffix="B"):
for unit in ["", "K", "M", "G", "T", "P", "E", "Z", "Y"]:
if size < 1024:
return "{size:.2f}{unit}{suffix}".format(size=size, unit=unit, suffix=suffix)
size /= 1024
sep = "/"
def normcase(path):
return path
def normpath(path):
if path == "":
return "."
initial_slashes = path.startswith("/")
if initial_slashes and path.startswith(("/" * 2)) and (not path.startswith(("/" * 3))):
initial_slashes = 2
new_comps = []
for comp in path.split("/"):
if comp in ("", "."):
continue
if (comp != "..") or ((not initial_slashes) and (not new_comps)) or (new_comps and (new_comps[(-1)] == "..")):
new_comps.append(comp)
elif new_comps:
new_comps.pop()
path = "/".join(new_comps)
if initial_slashes:
path = ("/" * initial_slashes) + path
return path or "."
def abspath(path):
if not isabs(path):
return normpath(join(os.getcwd(), path))
else:
return normpath(path)
def join(*args):
is_bytes = isinstance(args[0], bytes)
res = ""
for a in args:
if is_bytes:
a = a.decode()
if (not res) or a.startswith("/"):
res = a
else:
res += "/" + a
res = res.replace("//", "/")
if is_bytes:
return res.encode()
return res
def split(path):
if path == "":
return ("", "")
r = path.rsplit("/", 1)
if len(r) == 1:
return ("", path)
head = r[0]
if not head:
head = "/"
return (head, r[1])
def splitext(path):
r = path.rsplit(".", 1)
if len(r) == 1:
return (path, "")
if not r[0]:
return (path, "")
return (r[0], ("." + r[1]))
def splitdrive(path):
return ("", path)
def dirname(path):
if path and ("/" in path):
if (path == "///") or (path == "//") or (path == "/") or (path == (len(path) * "/")):
path = "/"
else:
if path.endswith("//"):
path = path[:(-2)]
elif path.endswith("/"):
path = path[:(-1)]
if "/" in path:
r = path.rsplit("/", 1)
if len(r) == 1:
head = ""
else:
head = r[0]
if not head:
head = "/"
path = head
if "/" not in path:
path = "."
else:
path = "."
if path.endswith("//") and (path != "//"):
path = path[:(-2)]
elif path.endswith("/") and (path != "/"):
path = path[:(-1)]
return path
def basename(string=None, suffix=None):
step = 1
if step == 1:
if (string is None) or (string == ""):
string = "."
step = 6
else:
step = 2
if step == 2:
if string == "//":
step = "End"
else:
step = 3
if step == 3:
if string == (len(string) * "/"):
string = "/"
step = "End"
else:
step = 4
if step == 4:
string = re.sub("/+", "/", string)
step = 5
if step == 5:
if string.endswith("//"):
string = string[:(-2)]
elif string.endswith("/"):
string = string[:(-1)]
if "/" in string:
string = string.split("/")[(-1)]
step = 6
if step == 6:
if suffix and (string != suffix) and (not suffix.endswith("/")):
string = string.replace(suffix, "")
return string
def exists(path):
return os.access(path, os.F_OK)
def lexists(path):
if os.access(path, os.F_OK) and os.readlink(path):
return True
return False
def isfile(path):
import stat
try:
mode = os.stat(path)[0]
return stat.S_ISREG(mode)
except OSError:
return False
def isdir(path):
import stat
try:
mode = os.stat(path)[0]
return stat.S_ISDIR(mode)
except OSError:
return False
def islink(path):
import stat
try:
mode = os.lstat(path)[0]
return stat.S_ISLNK(mode)
except OSError:
return False
def isabs(path):
return path.startswith("/")
def realpath(filename, *, strict=False):
filename = os.fspath(filename)
(path, ok) = _joinrealpath(filename[:0], filename, strict, {})
return abspath(path)
def _joinrealpath(path, rest, strict, seen):
import stat
if isinstance(path, bytes):
sep = b"/"
curdir = b"."
pardir = b".."
else:
sep = "/"
curdir = "."
pardir = ".."
if isabs(rest):
rest = rest[1:]
path = sep
while rest:
(name, _, rest) = rest.partition(sep)
if (not name) or (name == curdir):
continue
if name == pardir:
if path:
(path, name) = split(path)
if name == pardir:
path = join(path, pardir, pardir)
else:
path = pardir
continue
newpath = join(path, name)
try:
st = os.lstat(newpath)
except OSError:
if strict:
raise
is_link = False
else:
is_link = stat.S_ISLNK(st.st_mode)
if not is_link:
path = newpath
continue
if newpath in seen:
path = seen[newpath]
if path is not None:
continue
if strict:
os.stat(newpath)
else:
return (join(newpath, rest), False)
seen[newpath] = None
(path, ok) = _joinrealpath(path, os.readlink(newpath), strict, seen)
if not ok:
return (join(path, rest), False)
seen[newpath] = path
return (path, True)
def expanduser(s):
if (s == "~") or s.startswith("~/"):
h = os.getenv("HOME")
return h + s[1:]
if s[0] == "~":
return "/home/" + s[1:]
return s
def commonprefix(m):
if not m:
return ""
s1 = min(m)
s2 = max(m)
for (i, c) in enumerate(s1):
if c != s2[i]:
return s1[:i]
return s1
def relpath(path, start=None):
if not path:
raise ValueError("no path specified")
if isinstance(path, bytes):
curdir = b"."
sep = b"/"
pardir = b".."
else:
curdir = "."
sep = "/"
pardir = ".."
if start is None:
start = curdir
start_list = [x for x in abspath(start).split(sep) if x]
path_list = [x for x in abspath(path).split(sep) if x]
i = len(commonprefix([start_list, path_list]))
rel_list = ([pardir] * (len(start_list) - i)) + path_list[i:]
if not rel_list:
return curdir
return join(*rel_list)
def wrap(text, width=70, expand_tabs=True, replace_whitespace=True, tabsize=8, **kwargs):
list_to_return = []
line = ""
if replace_whitespace:
if hasattr(re, "sub"):
text = re.sub(" +", " ", text)
text = text.replace("\n", " ")
if expand_tabs:
text = text.replace("\t", (" " * tabsize))
for word in text.split(" "):
if (len(line) + len(("%s " % word))) <= width:
line += "%s " % word
elif (len(line) + len(("%s " % word))) > width:
list_to_return.append(line.strip(" "))
line = "%s " % word
if line and (line != ""):
list_to_return.append(line.strip(" "))
if list_to_return:
return list_to_return
else:
return [text]
def indent(text, prefix, predicate=None):
if predicate is None:
def predicate(line):
return line.strip()
def prefixed_lines():
for line in text.splitlines(True):
(yield ((prefix + line) if predicate(line) else line))
return "".join(prefixed_lines())
try:
from ucollections import namedtuple
except ImportError:
from collections import namedtuple
class WithCmdArgParser:
def __init__(self, parser):
self.parser = parser
def __call__(self, func):
if not self.parser:
self.parser = func(None, None, None, True)
def wrapped_function(*args, **kwargs):
try:
return func(*args, parsed=self.parser.parse_args(args[1].split()), **kwargs)
except SystemExit:
return
return wrapped_function
class Namespace:
pass
class _ArgError(BaseException):
pass
class _Arg:
def __init__(self, names, dest, action, nargs, const, default, type, help):
self.names = names
self.dest = dest
self.action = action
self.nargs = nargs
self.const = const
self.default = default
self.type = type
self.help = help
def parse(self, optname, eq_arg, args):
if (self.action == "store") or (self.action == "append"):
if self.nargs is None:
if eq_arg is not None:
ret = eq_arg
elif args:
ret = args.pop(0)
else:
raise _ArgError(("expecting value for %s" % optname))
return self.type(ret)
elif self.nargs == "?":
if eq_arg is not None:
ret = eq_arg
elif args:
ret = args.pop(0)
else:
return self.default
return self.type(ret)
else:
ret = []
if self.nargs == "*":
n = -1
elif self.nargs == "+":
if not args:
raise _ArgError(("expecting value for %s" % optname))
n = -1
elif self.nargs == "...":
n = 0
while args:
ret.append(args.pop(0))
else:
n = int(self.nargs)
stop_at_opt = True
while args and (n != 0):
if stop_at_opt and args[0].startswith("-") and (args[0] != "-"):
if args[0] == "--":
stop_at_opt = False
args.pop(0)
else:
break
else:
ret.append(args.pop(0))
n -= 1
if n > 0:
raise _ArgError(("expecting value for %s" % optname))
return ret
elif self.action == "store_const":
return self.const
else:
assert False
def _dest_from_optnames(opt_names):
dest = opt_names[0]
for name in opt_names:
if name.startswith("--"):
dest = name
break
return dest.lstrip("-").replace("-", "_")
class ArgumentParser:
def __init__(self, *, prog=None, description="", short_description="", add_help=None):
self.prog = prog
self.description = description
self.short_description = short_description
self.opt = []
self.pos = []
if add_help:
self.add_argument("-h", "--help", dest="help", action="store_true", help="show this help message and exit")
def add_argument(self, *args, **kwargs):
action = kwargs.get("action", "store")
if action == "store_true":
action = "store_const"
const = True
default = kwargs.get("default", False)
elif action == "store_false":
action = "store_const"
const = False
default = kwargs.get("default", True)
elif action == "append":
const = None
default = kwargs.get("default", [])
else:
const = kwargs.get("const", None)
default = kwargs.get("default", None)
if args and args[0].startswith("-"):
list = self.opt
dest = kwargs.get("dest")
if dest is None:
dest = _dest_from_optnames(args)
else:
list = self.pos
dest = kwargs.get("dest")
if dest is None:
dest = args[0]
if not args:
args = [dest]
list.append(
_Arg(
args,
dest,
action,
kwargs.get("nargs", None),
const,
default,
kwargs.get("type", str),
kwargs.get("help", ""),
)
)
@staticmethod
def error(msg):
sys.stderr.write(("error: %s\n" % msg))
sys.exit(2)
def parse_args(self, args=None, namespace=None):
return self._parse_args_impl(args, namespace, False)
def parse_known_args(self, args=None, namespace=None):
return self._parse_args_impl(args, namespace, True)
def _parse_args_impl(self, args, namespace, return_unknown):
if args is None:
args = sys.argv[1:]
else:
args = args[:]
if namespace is None:
namespace = Namespace()
try:
return self._parse_args(args, namespace, return_unknown)
except _ArgError as e:
self.print_usage()
self.error(str(e))
def _parse_args(self, args, argholder, return_unknown):
for opt in self.opt:
setattr(argholder, opt.dest, opt.default)
unknown = []
def consume_unknown():
while args and (not args[0].startswith("-")):
unknown.append(args.pop(0))
parsed_pos = False
while args or (not parsed_pos):
if args and args[0].startswith("-") and (args[0] != "-") and (args[0] != "--"):
a = args.pop(0)
eq_arg = None
if a.startswith("--") and ("=" in a):
(a, eq_arg) = a.split("=", 1)
found = False
for (i, opt) in enumerate(self.opt):
if a in opt.names:
val = opt.parse(a, eq_arg, args)
if opt.action == "append":
getattr(argholder, opt.dest).append(val)
else:
setattr(argholder, opt.dest, val)
found = True
break
if not found:
if return_unknown:
unknown.append(a)
consume_unknown()
else:
raise _ArgError(("unknown option %s" % a))
else:
if parsed_pos:
if return_unknown:
unknown = unknown + args
break
else:
raise _ArgError(("extra args: %s" % " ".join(args)))
for pos in self.pos:
setattr(argholder, pos.dest, pos.parse(pos.names[0], None, args))
parsed_pos = True
if return_unknown:
consume_unknown()
return (argholder, unknown) if return_unknown else argholder
def format_usage(self):
sys.stdout.write(("Usage: %s" % (self.prog or sys.argv[0])))
def render_arg(arg):
if arg.action == "store":
return " %s" % arg.dest
else:
return ""
for opt in self.opt:
sys.stdout.write((" [%s]" % ", ".join(opt.names)))
for pos in self.pos:
sys.stdout.write(render_arg(pos))
sys.stdout.write("\n")
def format_help(self):
columns = 79
sys.stdout.write("NAME\n")
sys.stdout.write(" ")
if self.prog or sys.argv[0]:
sys.stdout.write(("%s" % (self.prog or sys.argv[0])))
if self.short_description != "":
sys.stdout.write(" - ")
if self.short_description != "":
sys.stdout.write(("%s" % self.short_description))
sys.stdout.write("\n")
sys.stdout.write("\nSYNOPSIS\n")
sys.stdout.write((" %s" % (self.prog or sys.argv[0])))
def render_arg(arg):
if arg.action == "store":
return " %s" % arg.dest
else:
return ""
for opt in self.opt:
sys.stdout.write((" [%s]" % ", ".join(opt.names)))
for pos in self.pos:
sys.stdout.write(render_arg(pos))
sys.stdout.write("\n")
if self.description:
sys.stdout.write("\nDESCRIPTION\n")
for line in wrap(self.description, columns, replace_whitespace=False):
sys.stdout.write(("%s\n" % indent(line, " ")))
if self.pos:
sys.stdout.write("\nOPERANDS\n")
max_size = max((len(x.names[0]) for x in self.pos))
for pos in self.pos:
the_name = pos.names[0]
the_help = wrap(pos.help, ((columns - max_size) - 4))
sys.stdout.write(indent(the_name, " "))
for help_line in the_help:
if help_line == the_help[0]:
sys.stdout.write(indent(help_line, (" " * int(((max_size - len(the_name)) + 2)))))
sys.stdout.write("\n")
else:
sys.stdout.write(indent(help_line, (" " * int((max_size + 4)))))
sys.stdout.write("\n")
if self.opt:
sys.stdout.write("\nOPTIONS\n")
max_size = max((len(", ".join(x.names)) for x in self.opt))
for opt in self.opt:
the_name = ", ".join(opt.names)
the_help = wrap(opt.help, ((columns - max_size) - 4))
sys.stdout.write(indent(the_name, " "))
for help_line in the_help:
if help_line == the_help[0]:
sys.stdout.write(indent(help_line, (" " * int(((max_size - len(the_name)) + 2)))))
sys.stdout.write("\n")
else:
sys.stdout.write(indent(help_line, (" " * int((max_size + 4)))))
sys.stdout.write("\n")
def print_usage(self, file=None):
self.format_usage()
def print_help(self, file=None):
self.format_help()
class FileType(object):
def __init__(self, mode="r", bufsize=(-1), encoding=None, errors=None):
self._mode = mode
self._bufsize = bufsize
self._encoding = encoding
self._errors = errors
def __call__(self, string):
if string == "-":
if "r" in self._mode:
return sys.stdin
elif "w" in self._mode:
return sys.stdout
else:
raise ValueError(('argument "-" with mode %r' % self._mode))
try:
return open(string, self._mode, self._bufsize, self._encoding, self._errors)
except OSError as e:
args = {"filename": string, "error": e}
message = "can't open '%(filename)s': %(error)s"
raise TypeError((message % args))
def __repr__(self):
args = (self._mode, self._bufsize)
kwargs = [("encoding", self._encoding), ("errors", self._errors)]
args_str = ", ".join(
(
[repr(arg) for arg in args if (arg != (-1))]
+ [("%s=%r" % (kw, arg)) for (kw, arg) in kwargs if (arg is not None)]
)
)
return "%s(%s)" % (type(self).__name__, args_str)
parser_man = ArgumentParser(
prog="man", description="The man utility shall write information about each of the name operands.", add_help=True
)
parser_man.add_argument("name", nargs="*", default=[], help="A keyword or the name of a standard utility.")
PROMPT = "(Cmd) "
IDENTCHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"
class Cmd:
prompt = PROMPT
identchars = IDENTCHARS
ruler = "="
lastcmd = ""
intro = None
doc_leader = ""
doc_header = "Documented commands (type man <topic>):"
misc_header = "Miscellaneous help topics:"
undoc_header = "Undocumented commands:"
nohelp = "No manual entry for %s"
use_rawinput = 1
def __init__(self, stdin=None, stdout=None):
if stdin is not None:
self.stdin = stdin
else:
self.stdin = sys.stdin
if stdout is not None:
self.stdout = stdout
else:
self.stdout = sys.stdout
self.cmdqueue = []
self.exit_code = 0
def cmdloop(self, intro=None):
self.preloop()
try:
if intro is not None:
self.intro = intro
if self.intro:
self.stdout.write((str(self.intro) + "\n"))
stop = None
while not stop:
if self.cmdqueue:
line = self.cmdqueue.pop(0)
elif self.use_rawinput:
try:
line = input(self.prompt)
except EOFError:
line = "EOF"
else:
self.stdout.write(self.prompt)
self.stdout.flush()
line = self.stdin.readline()
if not len(line):
line = "EOF"
else:
line = line.rstrip("\r\n")
line = self.precmd(line)
stop = self.onecmd(line)
stop = self.postcmd(stop, line)
self.postloop()
finally:
pass
def precmd(self, line):
return line
def postcmd(self, stop, line):
return stop
def preloop(self):
pass
def postloop(self):
pass
def parseline(self, line):
line = line.strip()
if not line:
return (None, None, line)
elif line[0] == "?":
line = "man " + line[1:]
elif line[0] == "!":
if hasattr(self, "do_shell"):
line = "shell " + line[1:]
else:
return (None, None, line)
(i, n) = (0, len(line))
while (i < n) and (line[i] in self.identchars):
i = i + 1
(cmd, arg) = (line[:i], line[i:].strip())
return (cmd, arg, line)
def onecmd(self, line):
(cmd, arg, line) = self.parseline(line)
if not line:
return self.emptyline()
if cmd is None:
return self.default(line)
self.lastcmd = line
if line == "EOF":
self.lastcmd = ""
if cmd == "":
return self.default(line)
else:
try:
func = getattr(self, ("do_" + cmd))
except AttributeError:
return self.default(line)
return func(arg)
def emptyline(self):
if self.lastcmd:
return self.onecmd(self.lastcmd)
def default(self, line):
self.stdout.write(("*** Unknown syntax: %s\n" % line))
def get_names(self):
return dir(self.__class__)
@staticmethod
def help_man():
parser_man.print_help()
@WithCmdArgParser(parser_man)
def do_man(self, arg, **kwargs):
if kwargs["parsed"].help:
self.help_man()
return
if arg:
try:
func = getattr(self, ("help_" + arg))
except AttributeError:
self.stdout.write(("%s\n" % str((self.nohelp % (arg,)))))
return
func()
else:
names = self.get_names()
cmds_doc = []
cmds_undoc = []
help = {}
for name in names:
if name[:5] == "help_":
help[name[5:]] = 1
names.sort()
prevname = ""
for name in names:
if name[:3] == "do_":
if name == prevname:
continue
prevname = name
cmd = name[3:]
if cmd in help:
cmds_doc.append(cmd)
del help[cmd]
else:
cmds_undoc.append(cmd)
self.stdout.write(("%s\n" % self.doc_leader))
self.print_topics(self.doc_header, cmds_doc, 15, 80)
self.print_topics(self.misc_header, list(help.keys()), 15, 80)
self.print_topics(self.undoc_header, cmds_undoc, 15, 80)
def print_topics(self, header, cmds, cmdlen, maxcol):
if cmds:
self.stdout.write(("%s\n" % header))
if self.ruler:
self.stdout.write(("%s\n" % str((self.ruler * len(header)))))
self.columnize(cmds, (maxcol - 1))
self.stdout.write("\n")
def columnize(self, list, displaywidth=80):
if not list:
self.stdout.write("<empty>\n")
return
nonstrings = [i for i in range(len(list)) if (not isinstance(list[i], str))]
if nonstrings:
raise TypeError(("list[i] not a string for i in %s" % ", ".join(map(str, nonstrings))))
size = len(list)
if size == 1:
self.stdout.write(("%s\n" % str(list[0])))
return
for nrows in range(1, len(list)):
ncols = ((size + nrows) - 1) // nrows
colwidths = []
totwidth = -2
for col in range(ncols):
colwidth = 0
for row in range(nrows):
i = row + (nrows * col)
if i >= size:
break
x = list[i]
colwidth = max(colwidth, len(x))
colwidths.append(colwidth)
totwidth += colwidth + 2
if totwidth > displaywidth:
break
if totwidth <= displaywidth:
break
else:
nrows = len(list)
ncols = 1
colwidths = [0]
for row in range(nrows):
texts = []
for col in range(ncols):
i = row + (nrows * col)
if i >= size:
x = ""
else:
x = list[i]
texts.append(x)
while texts and (not texts[(-1)]):
del texts[(-1)]
for col in range(len(texts)):
texts[col] = "%-*s" % (colwidths[col], texts[col])
self.stdout.write(("%s\n" % str(" ".join(texts))))
def tabulate(tabular_data, headers, tablefmt, colalign):
value_to_return = []
columns_info = {}
if headers:
tabular_data.insert(0, headers)
for line in tabular_data:
for (index_col, cell_value) in enumerate(line):
columns_info[index_col] = {}
columns_info[index_col]["data"] = []
columns_info[index_col]["text"] = []
columns_info[index_col]["size"] = 0
columns_info[index_col]["colalign"] = None
for line in tabular_data:
for (index_col, cell_value) in enumerate(line):
columns_info[index_col]["data"].append(cell_value)
columns_info[index_col]["text"].append(cell_value)
if colalign:
columns_info[index_col]["colalign"] = colalign[index_col]
if len(str(cell_value)) > columns_info[index_col]["size"]:
columns_info[index_col]["size"] = len(str(cell_value))
for (key, value) in columns_info.items():
for (index, item) in enumerate(value["data"]):
value["text"][index] = str(value["text"][index])
if len(str(item)) < value["size"]:
if value["colalign"].lower() == "right":
spacing = " " * int((value["size"] - len(str(item))))
value["text"][index] = "%s%s" % (spacing, value["text"][index])
elif value["colalign"].lower() == "center":
spacing = " " * int((int((value["size"] - len(str(item)))) / 2))
value["text"][index] = "%s%s%s" % (spacing, value["text"][index], spacing)
else:
spacing = " " * int((value["size"] - len(str(item))))
value["text"][index] = "%s%s" % (value["text"][index], spacing)
line_to_append = ""
spacing = " "
for (line, line_value) in enumerate(tabular_data):
for (col, col_value) in enumerate(line_value):
line_to_append += "%s%s" % (columns_info[col]["text"][line], spacing)
value_to_return.append(line_to_append.strip(" "))
line_to_append = ""
return "\n".join(value_to_return)
class EINVAL(Exception):
pass
class ENOMEM(Exception):
pass
class GLXEnviron(object):
def __init__(self):
self.__environ = None
self.environ = None
@property
def environ(self):
return self.__environ
@environ.setter
def environ(self, value):
if value is None:
value = {}
if type(value) != dict:
raise TypeError("'environ' property value must be a dict type or None")
if self.environ != value:
self.__environ = value
def getenv(self, name=None):
if type(name) != str:
raise TypeError("'name' parameter must be a str or None")
if name in self.environ:
return self.environ[name]
else:
return None
def setenv(self, envname=None, envval=None, overwrite=None):
if type(envname) != str:
raise TypeError("'name' parameter must be a str")
if type(envval) != str:
raise TypeError("'value' parameter must be a str")
if (envname == "") or ("=" in envname):
raise EINVAL()
if (envname in self.environ) and (overwrite == 0):
return 0
elif ((envname in self.environ) and (overwrite != 0)) or (envname not in self.environ):
try:
self.environ[envname] = envval
return 0
except MemoryError:
raise ENOMEM()
return -1
def unsetenv(self, name):
if type(name) != str:
raise TypeError("'name' parameter value must be a str type")
if (name == "") or ("=" in name):
raise EINVAL()
if name not in self.environ:
return 0
try:
del self.environ[name]
return 0
except KeyError:
return -1
parser_basename = ArgumentParser(
prog="basename",
description="The string operand shall be treated as a pathname, as defined in XBD Pathname. The string string shall be converted to the filename corresponding to the last pathname component in string and then the suffix string suffix, if present, shall be removed.",
short_description="return non-directory portion of a pathname",
)
parser_basename.add_argument("string", type=str, nargs="?", default=None, help="a string")
parser_basename.add_argument("suffix", nargs="?", default=None, help="a string")
def basename(string=None, suffix=None):
step = 1
if step == 1:
if (string is None) or (string == ""):
string = "."
step = 6
else:
step = 2
if step == 2:
if string == "//":
step = "End"
else:
step = 3
if step == 3:
if string == (len(string) * string[0]):
string = "/"
step = "End"
else:
step = 4
if step == 4:
string = re.sub("/+", "/", string)
step = 5
if step == 5:
if string.endswith("/"):
string = string[:(-1)]
if "/" in string:
string = string.split("/")[(-1)]
step = 6
if step == 6:
if suffix and (string != suffix) and (not suffix.endswith("/")):
string = string.replace(suffix, "")
return string
parser_cat = ArgumentParser(
prog="cat",
description="The cat utility shall read files in sequence and shall write their contents to the standard output in the same sequence.",
short_description="concatenate and print files",
)
parser_cat.add_argument(
"file",
nargs="*",
type=FileType("r"),
default=sys.stdin,
help="with no FILE, or when FILE is -, read standard input.",
)
parser_cat.add_argument(
"-u",
dest="update",
action="store_true",
default=False,
help="Write bytes from the input file to the standard output without delay as each is read.",
)
def cat(files, update):
head(files, (1 << 30))
parser_cd = ArgumentParser(
prog="cd",
short_description="change the working directory",
description="The cd utility shall change the working directory of the current shell execution environment",
)
parser_cd.add_argument(
"directory",
nargs="?",
const=0,
help="An absolute or relative pathname of the directory that shall become the new working directory. The interpretation of a relative pathname by cd depends on the -L option and the CDPATH and PWD environment variables. If directory is an empty string, the results are unspecified.",
)
parser_cd.add_argument(
"-P",
dest="physical",
action="store_true",
default=False,
help="Handle the operand dot-dot physically; symbolic link components shall be resolved before dot-dot components are processed",
)
parser_cd.add_argument(
"-L",
dest="logical",
action="store_true",
default=False,
help="Handle the operand dot-dot logically; symbolic link components shall not be resolved before dot-dot components are processed ",
)
def cd(directory=None, logical=None, physical=None, **kwargs):
shell = kwargs.get("shell") or None
curpath = None
CDPATH = os.getenv("CDPATH")
if os.getenv("CDPATH") is None:
CDPATH = ""
if logical and physical:
physical = False
if (not logical) and (not physical):
logical = True
if directory == "-":
if os.getenv("OLDPWD"):
directory = os.getenv("OLDPWD")
else:
directory = os.getenv("PWD")
elif directory is not None:
directory = expanduser(directory)
step = 1
if step == 1:
print(("Step 1 -> %s" % curpath))
if ((directory is None) and (not os.getenv("HOME"))) or (os.getenv("HOME") == ""):
return
else:
step = 2
if step == 2:
print(("Step 2 -> %s" % curpath))
if (directory is None) and os.getenv("HOME"):
directory = os.getenv("HOME")
step = 3
if step == 3:
print(("Step 3 -> %s" % curpath))
if directory.startswith("/"):
curpath = directory
step = 7
else:
step = 4
if step == 4:
print(("Step 4 -> %s" % curpath))
if (directory == ".") or (directory == ".."):
step = 6
else:
step = 5
if step == 5:
print(("Step 5 -> %s" % curpath))
if CDPATH:
for pathname in CDPATH.split(":"):
if pathname:
if isdir(("%s/%s" % (pathname, directory))):
curpath = "%s/%s" % (pathname, directory)
step = 7
break
elif isdir(("./%s" % directory)):
curpath = "./%s" % directory
step = 7
break
else:
step = 6
if step == 6:
print(("Step 6 -> %s" % curpath))
curpath = directory
step = 7
if step == 7:
print(("Step 7 -> %s" % curpath))
if physical:
step = 10
else:
if not curpath.startswith("/"):
if not os.getenv("PWD").endswith("/"):
curpath = "%s%s%s" % (os.getenv("PWD"), "/", curpath)
step = 8
if step == 8:
print(("Step 8 -> %s" % curpath))
curpath = realpath(curpath)
step = 9
if step == 9:
print(("Step 9 -> %s" % curpath))
step = 10
if step == 10:
print(("Step 10 -> %s" % curpath))
err = None
if not isdir(curpath):
err = "cd: %s: No such file or directory" % curpath
elif not os.access(curpath, os.R_OK):
err = "cd: %s: Permission denied" % curpath
else:
try:
os.chdir(curpath)
except Exception as ex:
err = f"{ex}"
else:
if os.getenv("OLDPWD") != os.getenv("PWD"):
os.putenv("OLDPWD", os.getenv("PWD"))
if os.getenv("PWD") != os.getcwd():
os.putenv("PWD", os.getcwd())
return err
parser_clear = ArgumentParser(prog="clear", description="Clear screen")
def clear():
return "\x1b[2J\x1b[H"
parser_cp = ArgumentParser(
prog="cp",
short_description="copy files",
description="The first synopsis form is denoted by two operands, neither of which are existing files of type directory. The cp utility shall copy the contents of source_file (or, if source_file is a file of type symbolic link, the contents of the file referenced by source_file) to the destination path named by target_file.",
)
parser_cp.add_argument(
"-f",
dest="force",
action="store_true",
default=False,
help="If a file descriptor for a destination file cannot be obtained, as described in step 3.a.ii., attempt to unlink the destination file and proceed.",
)
parser_cp.add_argument(
"-i",
dest="interactive",
action="store_true",
help="Write a prompt to standard error before copying to any existing non-directory destination file.",
)
parser_cp.add_argument(
"source_file",
nargs="?",
const=0,
help="A pathname of a file to be copied. If a source_file operand is '-', it shall refer to a file named -; implementations shall not treat it as meaning standard input. target_file",
)
parser_cp.add_argument(
"target_file",
nargs="?",
const=0,
help="A pathname of an existing or nonexistent file, used for the output when a single file is copied. If a target_file operand is '-', it shall refer to a file named -; implementations shall not treat it as meaning standard output.",
)
def cp(source_file, target_file, interactive=False):
if interactive:
if exists(target_file):
if input(("do you want to overwrite %s file ? (Y/n)" % target_file)).upper().startswith("N"):
return
try:
with open(source_file, "r") as source_file:
with open(target_file, "w") as target_file:
target_file.write(source_file.read())
except Exception as error:
sys.stdout.write(("cp: %s\n" % error))
parser_df = ArgumentParser(
prog="df",
short_description="report free disk space",
description="The df utility shall write the amount of available space and file slots for file systems on which the invoking user has appropriate read access. File systems shall be specified by the file operands; when none are specified, information shall be written for all file systems.The format of the default output from df is unspecified, but all space figures are reported in 512-byte units, unless the -k option is specified. This output shall contain at least the file system names, amount of available space on each of these file systems, and, if no options other than -t are specified, the number of free file slots, or inodes, available; when -t is specified, the output shall contain the total allocated space as well.",
)
parser_df.add_argument(
"-h", dest="human_readable", action="store_true", default=False, help="print sizes in powers of 1024 (e.g., 1023M)"
)
parser_df.add_argument(
"-k",
dest="kilo",
action="store_const",
const=1024,
help="use 1024-byte units, instead of the default 512-byte units, when writing space figures.",
)
parser_df.add_argument("-P", dest="portability", action="store_true", default=True, help="produce a POSIX output")
parser_df.add_argument(
"-t", dest="total", action="store_true", help="include total allocated-space figures in the output. "
)
parser_df.add_argument(
"file",
nargs="?",
const=0,
help="A pathname of a file within the hierarchy of the desired file system. If a file other than a FIFO, a regular file, a directory, or a special file representing the device containing the file system (for example, /dev/dsk/0s1) is specified, the results are unspecified. If the file operand names a file other than a special file containing a file system, df shall write the amount of free space in the file system containing the specified file operand. Otherwise, df shall write the amount of free space in that file system. ",
)
def df(file=None, block_size=None, total=None, human_readable=None):
if block_size is None:
block_size = 512
devices_list = []
if file:
if not exists(file):
return "df: %s: No such file or directory" % file
if (not os.access(file, os.R_OK)) or (not os.access(df_find_mount_point(file), os.R_OK)):
return "df: %s : Permission denied\n" % file
for line in df_get_devices():
if df_find_mount_point(file) == line[1]:
devices_list.append(
df_get_device_information(file_system_name=line[0], file_system_root=line[1], block_size=block_size)
)
else:
for line in df_get_devices():
devices_list.append(
df_get_device_information(file_system_name=line[0], file_system_root=line[1], block_size=block_size)
)
if devices_list:
if total:
(total_space_free, total_space_used, total_total_space) = df_get_totals(devices_list)
devices_list.append(
[
"total",
total_total_space,
total_space_used,
total_space_free,
(
"%d%%"
% int(math.ceil((100 * (float((total_total_space - total_space_free)) / total_total_space))))
),
"-",
]
)
(block_size_text, tabular_data) = df_get_info_to_print(block_size, devices_list, human_readable)
return df_print_final(block_size_text, tabular_data)
def df_get_info_to_print(block_size, devices_list, human_readable):
block_size_text = f"{block_size}-blocks"
if human_readable:
tabular_data = []
block_size_text = "Size"
for line in devices_list:
if (str(line[1]) != "-") and (str(line[2]) != "-") and (str(line[3]) != "-"):
tabular_data.append(
[
line[0],
size_of(size=(int(line[1]) * block_size), suffix=""),
size_of(size=(int(line[2]) * block_size), suffix=""),
size_of(size=(int(line[3]) * block_size), suffix=""),
line[4],
line[5],
]
)
else:
tabular_data.append(line)
else:
tabular_data = devices_list
return (block_size_text, tabular_data)
def df_get_totals(devices_list):
total_total_space = 0
total_space_used = 0
total_space_free = 0
for device in devices_list:
try:
total_total_space += int(device[1])
except ValueError:
pass
try:
total_space_used += int(device[2])
except ValueError:
pass
try:
total_space_free += int(device[3])
except ValueError:
pass
return (total_space_free, total_space_used, total_total_space)
def df_print_final(block_size_text, tabular_data):
return "%s" % tabulate(
tabular_data=tabular_data,
headers=["Filesystem", block_size_text, "Used", "Available", "Capacity", "Mounted on"],
tablefmt="plain",
colalign=("left", "right", "right", "right", "right", "left"),
)
def df_find_mount_point(path):
if not islink(path):
path = abspath(path)
elif islink(path) and lexists(os.readlink(path)):
path = realpath(path)
if hasattr(os, "path") and hasattr(os, path, "ismount"):
while not os.path.ismount(path):
path = dirname(path)
if islink(path) and lexists(os.readlink(path)):
path = realpath(path)
return path
def df_get_device_information(file_system_name=None, file_system_root=None, block_size=None):
try:
statvfs = os.statvfs(file_system_root)
if type(statvfs) == tuple:
# statvfs[0] = f_bsize
# statvfs[1] = f_frsize
# statvfs[2] = f_blocks
# statvfss[3] = f_bfree
# statvfs[4] = f_bavail
# statvfss[5] = f_files
# statvfs[6] = f_ffree
# statvfs[7] = f_favail
# statvfs[8] = f_flags
# statvfss[9] = f_namemax
space_free = statvfs[4] * statvfs[1] / block_size
total_space = statvfs[2] * statvfs[1] / block_size
else:
space_free = statvfs.f_bavail * statvfs.f_frsize / block_size
total_space = statvfs.f_blocks * statvfs.f_frsize / block_size
space_used = total_space - space_free
if total_space == 0:
percentage_used = "-"
else:
percentage_used = "%d%%" % int(math.ceil(100 * (float(total_space - space_free) / total_space)))
return [
("%s" % file_system_name),
("%d" % total_space),
("%d" % space_used),
("%d" % space_free),
("%s" % percentage_used),
("%s" % file_system_root),
]
except Exception:
return [
("%s" % file_system_name),
("%s" % "-"),
("%s" % "-"),
("%s" % "-"),
("%s" % "-"),
("%s" % file_system_root),
]
def df_get_devices(file=None):
if (file is None) and exists("/etc/mtab"):
file = "/etc/mtab"
if (file is None) and exists("/proc/mounts"):
file = "/proc/mounts"
if file is None:
raise SystemError("Impossible to locate /etc/mtab or /proc/mounts file")
file_entries = []
for line in df_get_file_content(file=file).splitlines():
if len(line.split()) < 4:
continue
file_entries.append(line.split())
return file_entries
def df_get_file_content(file=None):
if not exists(file):
raise FileExistsError(f"{file} do not exist")
if not os.access(file, os.R_OK):
raise PermissionError(f"{file} can't be read")
with open(file) as datafile:
return datafile.read().strip()
parser_dirname = ArgumentParser(
prog="dirname",
short_description="return the directory portion of a pathname",
description="The string operand shall be treated as a pathname, as defined in XBD Pathname. The string string shall be converted to the name of the directory containing the filename corresponding to the last pathname component in string.",
)
parser_dirname.add_argument("string", nargs="?", const=0, help="A string")
parser_env = ArgumentParser(
prog="env",
short_description="set the environment for command invocation",
description="The env utility shall obtain the current environment, modify it according to its arguments, then invoke the utility named by the utility operand with the modified environment.",
)
parser_env.add_argument(
"-i",
dest="invoke",
action="store_true",
help="Invoke utility with exactly the environment specified by the arguments; the inherited environment shall be ignored completely.",
)
parser_env.add_argument(
"name",
nargs="*",
dest="name",
default=None,
help="Arguments of the form name= value shall modify the execution environment, and shall be placed into the inherited environment before the utility is invoked.",
)
parser_env.add_argument(
"utility",
nargs="*",
dest="utility",
default=None,
help="The name of the utility to be invoked. If the utility operand names any of the special built-in utilities in Special Built-In Utilities, the results are undefined.",
)
parser_env.add_argument(
"argument",
nargs="*",
dest="argument",
default=None,
help="A string to pass as an argument for the invoked utility.",
)
def env(name, utility, argument, **kwargs):
stdout = kwargs.get("stdout", sys.stdout)
stdin = kwargs.get("stdin", sys.stdin)
stderr = kwargs.get("stdin", sys.stderr)
shell = kwargs.get("shell", None)
if shell and hasattr(shell, "environ"):
if name:
stdout.write(("%s\n" % name))
else:
for (name, value) in shell.environ.items():
stdout.write(("%s=%s\n" % (name, value)))
parser_exit = ArgumentParser(prog="exit", description="exit shell with a given exit code")
parser_exit.add_argument("code", nargs="*", type="int", help="exit code")
parser_head = ArgumentParser(
prog="head",
short_description="copy the first part of",
description="The head utility shall copy its input files to the standard output, ending the output for each file at a designated point. ",
)
parser_head.add_argument(
"file",
nargs="*",
help="A pathname of an input file. If no file operands are specified, the standard input shall be used.",
)
parser_head.add_argument(
"-n",
dest="number",
type=int,
default=10,
help="The first number lines of each input file shall be copied to standard output. ",
)
def head(files, number=10, **kwargs):
stdout = kwargs.get("stdout", sys.stdout)
if (files is None) or (not isinstance(files, list)):
return
if isinstance(number, int) and (number < 1):
return
for file in files:
with open(file) as f:
for i in range(number):
line = f.readline()
if not line:
break
stdout.write(line)
parser_ls = ArgumentParser(
prog="ls",
short_description="list directory contents",
description="For each operand that names a file of a type other than directory or symbolic link to a directory, ls shall write the name of the file as well as any requested, associated information. For each operand that names a file of type directory, ls shall write the names of files contained within the directory as well as any requested, associated information. Filenames beginning with a <period> ( '.' ) and any associated information shall not be written out unless explicitly referenced, the -A or -a option is supplied, or an implementation-defined condition causes them to be written. If one or more of the -d, -F, or -l options are specified, and neither the -H nor the -L option is specified, for each operand that names a file of type symbolic link to a directory, ls shall write the name of the file as well as any requested, associated information. If none of the -d, -F, or -l options are specified, or the -H or -L options are specified, for each operand that names a file of type symbolic link to a directory, ls shall write the names of files contained within the directory as well as any requested, associated information. In each case where the names of files contained within a directory are written, if the directory contains any symbolic links then ls shall evaluate the file information and file type to be those of the symbolic link itself, unless the -L option is specified.\n\nIf no operands are specified, ls shall behave as if a single operand of dot ( '.' ) had been specified. If more than one operand is specified, ls shall write non-directory operands first; it shall sort directory and non-directory operands separately according to the collating sequence in the current locale.\n",
)
def ls(path=None):
if (path is None) or (path == ""):
try:
path = os.getcwd()
except Exception as error:
return "ls: %s" % error
try:
listdir = os.listdir(path)
listdir.sort()
Cmd().columnize(listdir)
except Exception as error:
return "ls: %s" % error
parser_mkdir = ArgumentParser(
prog="mkdir",
short_description="make directories",
description="The mkdir utility shall create the directories specified by the operands",
)
parser_mkdir.add_argument("dir", nargs="*", help="a pathname of a directory to be created.")
parser_mkdir.add_argument(
"-m",
dest="mode",
nargs="?",
const=1,
type=str,
default="755",
help="set the file permission bits of the newly-created directory to the specified mode value.",
)
parser_mkdir.add_argument(
"-p",
dest="parents",
action="store_true",
default=False,
help="create any missing intermediate pathname components.",
)
def mkdir(directories=None, parents=False, mode="755"):
value_to_return = []
for directory in directories:
if parents:
if str(directory).startswith("/"):
directory_to_create = "/"
else:
directory_to_create = ""
for sub_directory in directory.split("/"):
if directory_to_create == "/":
directory_to_create = "%s%s" % (directory_to_create, sub_directory)
elif (directory_to_create != "") and (sub_directory != ""):
directory_to_create = "%s%s%s" % (directory_to_create, "/", sub_directory)
elif sub_directory == "":
continue
elif sub_directory == ".":
directory_to_create = "."
continue
elif sub_directory == "..":
directory_to_create = ".."
continue
else:
directory_to_create = sub_directory
try:
os.mkdir(path=directory_to_create, mode=int(mode))
except TypeError:
os.mkdir(directory_to_create)
except OSError as error:
return "mkdir: %s" % error
else:
try:
os.stat(directory)
value_to_return.append(("mkdir: cannot create directory '%s': File exists" % directory))
except OSError:
try:
try:
os.mkdir(path=directory, mode=int(mode))
except OSError as error:
return "mkdir: %s" % error
except TypeError:
try:
os.mkdir(directory)
except OSError as error:
return "mkdir: %s" % error
if value_to_return:
return "\n".join(value_to_return)
parser_mv = ArgumentParser(
prog="mv",
short_description="move files",
description="The mv utility shall move the file named by the source_file operand to the destination specified by the target_file. This first synopsis form is assumed when the final operand does not name an existing directory and is not a symbolic link referring to an existing directory. In this case, if source_file names a non-directory file and target_file ends with a trailing <slash> character, mv shall treat this as an error and no source_file operands will be processed.",
)
parser_mv.add_argument("source_file", nargs="?", const=0, help="A pathname of a file to be copied.")
parser_mv.add_argument("source_file", nargs="?", const=0, help="A pathname of a file or directory to be moved.")
parser_mv.add_argument("target_file", nargs="?", const=0, help="A new pathname for the file or directory being moved.")
parser_mv.add_argument(
"target_dir", nargs="?", const=0, help="A pathname of an existing directory into which to move the input files."
)
parser_mv.add_argument(
"-f",
dest="force",
action="store_true",
default=False,
help="Do not prompt for confirmation if the destination path exists. Any previous occurrence of the -i option is ignored.",
)
parser_mv.add_argument(
"-i",
dest="interactive",
action="store_true",
default=False,
help="Prompt for confirmation if the destination path exists. Any previous occurrence of the -f option is ignored.",
)
def mv(source_file=None, target_file=None, target_dir=None, force=None, interactive=None):
try:
if os.access(source_file, os.F_OK):
os.rename(source_file, target_file)
except Exception as error:
return "mv: %s\n" % error
pass
parser_pwd = ArgumentParser(
prog="pwd",
short_description="return working directory name",
description="The pwd utility shall write to standard output an absolute pathname of the current working directory, which does not contain the filenames dot or dot-dot.",
)
parser_pwd.add_argument(
"-L",
dest="logical",
action="store_true",
default=False,
help="f the PWD environment variable contains an absolute pathname of the current directory and the pathname does not contain any components that are dot or dot-dot, pwd shall write this pathname to standard output, except that if the PWD environment variable is longer than {PATH_MAX} bytes including the terminating null",
)
parser_pwd.add_argument(
"-P",
dest="physical",
action="store_true",
default=False,
help="The pathname written to standard output shall not contain any components that refer to files of type symbolic link. If there are multiple pathnames that the pwd utility could write to standard output, one beginning with a single <slash> character and one or more beginning with two <slash> characters, then it shall write the pathname beginning with a single <slash> character. The pathname shall not contain any unnecessary <slash> characters after the leading one or two <slash> characters.",
)
def pwd(logical, physical):
if (not logical) and (not physical):
logical = True
if logical:
return normpath(os.getcwd())
else:
return realpath(os.getcwd())
parser_rm = ArgumentParser(
prog="rm",
short_description="remove directory entries",
description="The rm utility shall remove the directory entry specified by each file argument.\n\nIf either of the files dot or dot-dot are specified as the basename portion of an operand (that is, the final pathname component) or if an operand resolves to the root directory, rm shall write a diagnostic message to standard error and do nothing more with such operands.",
)
parser_rm.add_argument(
"-f",
dest="force",
action="store_true",
default=False,
help="Do not prompt for confirmation. Do not write diagnostic messages or modify the exit status in the case of no file operands, or in the case of operands that do not exist. Any previous occurrences of the -i option shall be ignored.",
)
parser_rm.add_argument(
"-i",
dest="interactive",
action="store_true",
default=False,
help="Prompt for confirmation as described previously. Any previous occurrences of the -f option shall be ignored.",
)
parser_rm.add_argument(
"-R",
"-r",
dest="recursive",
action="store_true",
default=False,
help="Remove file hierarchies. See the DESCRIPTION.",
)
parser_rm.add_argument("file", nargs="*", default=[], help="A pathname of a directory entry to be removed.")
def rm(files=None, recursive=None, interactive=None, force=None):
to_return = []
def delete_file(f):
try:
os.remove(f)
except Exception as error:
to_return.append(("rm: %s" % error))
if files:
for file in files:
delete_file(file)
if to_return:
return "\n".join(to_return)
parser_rmdir = ArgumentParser(
prog="rmdir",
short_description="remove directories",
description="The rmdir utility shall remove the directory entry specified by each dir operand.",
)
parser_rmdir.add_argument("dir", nargs="*", default=[], help="A pathname of an empty directory to be removed.")
parser_rmdir.add_argument(
"-p", dest="parents", action="store_true", default=False, help="Remove all directories in a pathname."
)
def rmdir(directories=None, parents=False):
to_return = []
def delete_directory(d):
try:
os.rmdir(path=d)
except OSError as error:
to_return.append(("rmdir: %s" % error))
for directory in directories:
if parents:
for (path, dirs, files) in os.walk(directory, False):
for f in files:
os.unlink(((path + "/") + f))
delete_directory(path)
else:
delete_directory(directory)
if to_return:
return "\n".join(to_return)
parser_sleep = ArgumentParser(
prog="sleep",
short_description="suspend execution for an interval",
description="The sleep utility shall suspend execution for at least the integral number of seconds specified by the time operand. ",
)
parser_sleep.add_argument(
"time",
nargs="?",
default=0,
help="A non-negative decimal integer or float specifying the number of seconds for which to suspend execution.",
)
def sleep(sec):
to_return = []
def string_to_numeric_if_possible(x):
try:
val = float(x)
return int(val) if (val == int(val)) else val
except (TypeError, ValueError):
return x
try:
time.sleep(string_to_numeric_if_possible(sec))
except TypeError as error:
to_return.append(("sleep: %s" % error))
except KeyboardInterrupt:
return
if to_return:
return "\n".join(to_return)
parser_touch = ArgumentParser(
prog="touch",
short_description="change file access and modification times",
description="The touch utility shall change the last data modification timestamps, the last data access timestamps, or both.\n\nThe time used can be specified by the -t time option-argument, the corresponding time fields of the file referenced by the -r ref_file option-argument, or the -d date_time option-argument, as specified in the following sections. If none of these are specified, touch shall use the current time.",
)
parser_touch.add_argument(
"-a",
dest="access_time",
help="Change the access time of file. Do not change the modification time unless -m is also specified.",
)
parser_touch.add_argument(
"-c",
help="Do not create a specified file if it does not exist. Do not write any diagnostic messages concerning this condition.",
)
parser_touch.add_argument(
"-m", help="Change the modification time of file. Do not change the access time unless -a is also specified."
)
parser_touch.add_argument(
"-r", help="Use the corresponding time of the file named by the pathname ref_file instead of the current time."
)
parser_touch.add_argument(
"-t",
help="Use the specified time instead of the current time. The option-argument shall be a decimal number of the form",
)
parser_touch.add_argument(
"file",
help="Use the specified time instead of the current time. The option-argument shall be a decimal number of the form",
)
def touch(file=None):
raise NotImplementedError("Touch is not implemented yet ...")
parser_tty = ArgumentParser(
prog="tty",
short_description="return user's terminal name",
description="The tty utility shall write to the standard output the name of the terminal that is open as standard input.",
)
def tty():
to_return = []
try:
to_return.append(("%s" % os.ttyname(0)))
except OSError:
to_return.append("not a tty")
if to_return:
return "\n".join(to_return)
parser_uname = ArgumentParser(
prog="uname",
short_description="return system name",
description="By default, the uname utility shall write the operating system name to standard output. When options are specified, symbols representing one or more system characteristics shall be written to the standard output. The format and contents of the symbols are implementation-defined. On systems conforming to the System Interfaces volume of POSIX.1-2017, the symbols written shall be those supported by the uname() function as defined in the System Interfaces volume of POSIX.1-2017.",
)
parser_uname.add_argument(
"-a", dest="all", action="store_true", help="Behave as though all of the options -mnrsv were specified."
)
parser_uname.add_argument(
"-s", dest="sysname", action="store_true", help="Write the name of the implementation of the operating system."
)
parser_uname.add_argument(
"-n",
dest="nodename",
action="store_true",
help="Write the name of this node within an implementation-defined communications network.",
)
parser_uname.add_argument(
"-r",
dest="release",
action="store_true",
help="Write the current release level of the operating system implementation.",
)
parser_uname.add_argument(
"-v",
action="store_true",
dest="version",
help="Write the current version level of this release of the operating system implementation.",
)
parser_uname.add_argument(
"-m",
dest="machine",
action="store_true",
help="Write the name of the hardware type on which the system is running to standard output.",
)
def uname(all=False, sysname=False, nodename=False, release=False, version=False, machine=False):
info = os.uname()
def gen_lines():
if all or nodename:
(yield info.nodename)
if all or release:
(yield info.release)
if all or version:
(yield info.version)
if all or machine:
(yield info.machine)
lines = list(gen_lines())
if all or sysname or (not lines):
lines.insert(0, info.sysname)
return " ".join(lines)
class GLXUsh(Cmd, GLXEnviron):
prompt = "> "
if hasattr(sys.implementation, "mpy"):
loader_mpy = "MPY %s" % sys.implementation.mpy
else:
loader_mpy = ""
if hasattr(gc, "mem_free") and hasattr(gc, "mem_alloc"):
gc.collect()
memory_total = "%s MEMORY SYSTEM\n" % size_of((gc.mem_free() + gc.mem_alloc())).upper()
memory_free = "%s FREE\n" % size_of(gc.mem_free()).upper()
elif hasattr(os, "sysconf"):
memory_total = "%s RAM SYSTEM\n" % size_of((os.sysconf("SC_PAGE_SIZE") * os.sysconf("SC_PHYS_PAGES"))).upper()
memory_free = "%s FREE\n" % size_of((os.sysconf("SC_PAGE_SIZE") * os.sysconf("SC_AVPHYS_PAGES"))).upper()
else:
memory_total = ""
memory_free = ""
intro = (
"******************************* %s V%s **********************************\n\n%s\nLOADER %s %s %s\nEXEC PYTHON V%s\n%s%s"
% (
APPLICATION_NAME.upper(),
APPLICATION_VERSION.upper(),
APPLICATION_LICENSE.upper(),
sys.implementation.name.upper(),
".".join((str(item).upper() for item in list(sys.implementation.version))),
loader_mpy,
sys.version.upper(),
memory_total,
memory_free,
)
)
def __init__(self, *args, **kwargs):
super().__init__()
GLXEnviron.__init__(self)
if hasattr(os, "environ"):
self.environ = os.environ.copy()
else:
self.setenv("PATH", os.getcwd(), 1)
self.setenv("HOME", "/", 1)
def postloop(self):
return self.exit_code
def do_EOF(self, line):
self.stdout.write("\n")
return True
def default(self, line):
sys.stderr.write("glxush: %s : unknown command\n")
return
@staticmethod
def help_basename():
parser_basename.print_help()
@WithCmdArgParser(parser_basename)
def do_basename(self, *args, **kwargs):
self.stdout.write(("%s\n" % basename(string=kwargs["parsed"].string, suffix=kwargs["parsed"].suffix)))
@staticmethod
def help_cat():
parser_cat.print_help()
@WithCmdArgParser(parser_cat)
def do_cat(self, *args, **kwargs):
returned = cat(files=kwargs["parsed"].file, update=kwargs["parsed"].update)
if returned:
self.stdout.write(("%s\n" % returned))
@WithCmdArgParser(parser_cd)
def do_cd(self, *args, **kwargs):
returned = cd(
directory=kwargs["parsed"].directory,
logical=kwargs["parsed"].logical,
physical=kwargs["parsed"].physical,
shell=self,
)
if returned:
self.stdout.write(("%s\n" % returned))
@staticmethod
def help_cd():
parser_cd.print_help()
@WithCmdArgParser(parser_clear)
def do_clear(self, *args, **kwargs):
self.stdout.write(("%s" % clear()))
@staticmethod
def help_clear():
parser_clear.print_help()
@WithCmdArgParser(parser_cp)
def do_cp(self, *args, **kwargs):
cp(
source_file=kwargs["parsed"].source_file,
target_file=kwargs["parsed"].target_file,
interactive=kwargs["parsed"].interactive,
)
@staticmethod
def help_cp():
parser_cp.print_help()
@WithCmdArgParser(parser_df)
def do_df(self, *args, **kwargs):
self.stdout.write(
(
"%s\n"
% df(
file=kwargs["parsed"].file,
block_size=kwargs["parsed"].kilo,
total=kwargs["parsed"].total,
human_readable=kwargs["parsed"].human_readable,
)
)
)
@staticmethod
def help_df():
parser_df.print_help()
@WithCmdArgParser(parser_dirname)
def do_dirname(self, *args, **kwargs):
self.stdout.write(("%s\n" % dirname(kwargs["parsed"].string)))
@staticmethod
def help_dirname():
parser_dirname.print_help()
@staticmethod
def help_env():
parser_env.print_help()
@WithCmdArgParser(parser_env)
def do_env(self, *args, **kwargs):
env(
name=kwargs["parsed"].name,
utility=kwargs["parsed"].utility,
argument=kwargs["parsed"].argument,
stdout=self.stdout,
shell=self,
)
@WithCmdArgParser(parser_head)
def do_head(self, *args, **kwargs):
if not kwargs["parsed"].file:
parser_head.print_usage()
return
head(files=kwargs["parsed"].file, number=kwargs["parsed"].number)
@staticmethod
def help_head():
parser_head.print_help()
def emptyline(self):
pass
@WithCmdArgParser(parser_ls)
def do_ls(self, *args, **kwargs):
ls()
@staticmethod
def help_ls():
parser_ls.print_help()
@WithCmdArgParser(parser_exit)
def do_exit(self, *args, **kwargs):
if not kwargs["parsed"].code:
self.exit_code = 0
else:
self.exit_code = kwargs["parsed"].code[0]
return True
@staticmethod
def help_exit():
parser_exit.print_help()
@WithCmdArgParser(parser_mkdir)
def do_mkdir(self, *args, **kwargs):
if not kwargs["parsed"].dir:
parser_mkdir.print_usage()
return
returned = mkdir(directories=kwargs["parsed"].dir, parents=kwargs["parsed"].parents, mode=kwargs["parsed"].mode)
if returned:
self.stdout.write(("%s\n" % returned))
@staticmethod
def help_mkdir():
parser_mkdir.print_help()
@WithCmdArgParser(parser_mv)
def do_mv(self, *args, **kwargs):
returned = mv(
source_file=kwargs["parsed"].source_file,
target_file=kwargs["parsed"].target_file,
target_dir=kwargs["parsed"].target_dir,
force=kwargs["parsed"].force,
interactive=kwargs["parsed"].interactive,
)
if returned:
self.stdout.write(("%s\n" % returned))
@staticmethod
def help_mv():
parser_mv.print_help()
@WithCmdArgParser(parser_pwd)
def do_pwd(self, *args, **kwargs):
try:
sys.stdout.write(("%s\n" % pwd(logical=kwargs["parsed"].logical, physical=kwargs["parsed"].physical)))
except Exception as error:
sys.stderr.write(("pwd: %s\n" % error))
@staticmethod
def help_pwd():
parser_pwd.print_help()
@WithCmdArgParser(parser_rm)
def do_rm(self, *args, **kwargs):
if not kwargs["parsed"].file:
parser_rm.print_usage()
return
returned_value = rm(
files=kwargs["parsed"].file,
recursive=kwargs["parsed"].recursive,
interactive=kwargs["parsed"].interactive,
force=kwargs["parsed"].force,
)
if returned_value:
self.stdout.write(("%s\n" % returned_value))
@staticmethod
def help_rm():
parser_rm.print_help()
@WithCmdArgParser(parser_rmdir)
def do_rmdir(self, *args, **kwargs):
if not kwargs["parsed"].dir:
parser_rmdir.print_usage()
return
returned_value = rmdir(directories=kwargs["parsed"].dir, parents=kwargs["parsed"].parents)
if returned_value:
self.stdout.write(("%s\n" % returned_value))
@staticmethod
def help_rmdir():
parser_rmdir.print_help()
@WithCmdArgParser(parser_sleep)
def do_sleep(self, *args, **kwargs):
if not kwargs["parsed"].time:
parser_sleep.print_usage()
return
returned_value = sleep(sec=kwargs["parsed"].time)
if returned_value:
self.stdout.write(("%s\n" % returned_value))
@staticmethod
def help_tty():
parser_tty.print_help()
@WithCmdArgParser(parser_tty)
def do_tty(self, *args, **kwargs):
returned_value = tty()
if returned_value:
self.stdout.write(("%s\n" % returned_value))
@staticmethod
def help_sleep():
parser_sleep.print_help()
@WithCmdArgParser(parser_uname)
def do_uname(self, *args, **kwargs):
try:
sys.stdout.write(
(
"%s\n"
% uname(
all=kwargs["parsed"].all,
sysname=kwargs["parsed"].sysname,
nodename=kwargs["parsed"].nodename,
release=kwargs["parsed"].release,
version=kwargs["parsed"].version,
machine=kwargs["parsed"].machine,
)
)
)
except AttributeError as e:
sys.stdout.write(("%s\n" % e))
@staticmethod
def help_uname():
parser_uname.print_help()
parser_glxsh = ArgumentParser(prog="glxsh", add_help=True)
parser_glxsh.add_argument(
"command", nargs="?", help="optional commands or file to run, if no commands given, enter an interactive shell"
)
parser_glxsh.add_argument(
"command_args", nargs="...", help="if commands is not a file use optional arguments for commands"
)
def main():
if len(sys.argv) > 1:
args = parser_glxsh.parse_args(sys.argv[1:])
if args.help:
parser_glxsh.print_help()
return
if isfile(args.command):
raise NotImplementedError("Load file script is not implemented yet")
else:
sys.exit(GLXUsh().onecmd(("%s %s" % (args.command, " ".join(args.command_args)))))
else:
sys.exit(GLXUsh().cmdloop())
if __name__ == "__main__":
sys.exit(main())