--- lshell/shellcmd.py | 77 ++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 71 insertions(+), 6 deletions(-) --- a/lshell/shellcmd.py +++ b/lshell/shellcmd.py @@ -28,6 +28,7 @@ import readline import glob import subprocess +from time import gmtime, strftime from utils import get_aliases @@ -50,6 +51,9 @@ class ShellCmd(cmd.Cmd, object): else: self.stderr = stderr + # create a devnull device + self.devnull = open(os.devnull, 'w') + self.args = args self.conf = userconf self.log = self.conf['logpath'] @@ -145,13 +149,63 @@ class ShellCmd(cmd.Cmd, object): self.g_cmd, self.g_arg, self.g_line = ['', '', ''] return object.__getattribute__(self, attr) + def check_prompt(self, var, value): + """ check if user is attempting to + modify shell prompt and if so then + update the prompt + """ + if 'PS' in var: + if 'PS1' in var: + # update prompt + self.promptbase = self.setprompt( + {'prompt' : value.strip('\n').strip('\r')}) + self.updateprompt(os.getcwd()) + else: + self.log.critical("*** forbidden %s prompt change requested. " + "Only PS1 changes permissible" % var) + + def setprompt(self, conf): """ set prompt used by the shell """ if conf.has_key('prompt'): promptbase = conf['prompt'] - promptbase = promptbase.replace('%u', getuser()) - promptbase = promptbase.replace('%h', os.uname()[1].split('.')[0]) + # Recognize shell name control command + promptbase = re.sub(r'\\s', 'lshell', + promptbase) + # Recognize username control command + promptbase = re.sub(r'\\u|%u', getuser(), + promptbase) + # Recognize hostname control command + promptbase = re.sub(r'\\h|%h', os.uname()[1].split('.')[0], + promptbase) + # Recognize full hostname control command + promptbase = re.sub(r'\\H', os.uname()[1], + promptbase) + # Recognize time control commands + promptbase = re.sub(r'\\t', strftime("%H:%M:%S", gmtime()), + promptbase) + promptbase = re.sub(r'\\T', strftime("%I:%M:%S", gmtime()), + promptbase) + promptbase = re.sub(r'\\A', strftime("%H:%M", gmtime()), + promptbase) + promptbase = re.sub(r'\\@', strftime("%I:%M:%S%p", gmtime()), + promptbase) + promptbase = re.sub(r'\\d', strftime("%a %b %d", gmtime()), + promptbase) + ######################################################## + # The following control commands are not supported: # + # v - the shell version # + # V - the shell release version # + # w - Complete path of current working directory # + # W - the basename of the current working directory # + # ! - the history number of this command # + # # - the command number of this command # + # $? - status of the last command # + # $() - any command executions # + ######################################################## + promptbase = re.sub(r'\\v|\\V|\\w|\\W|\\!|\\#|\\\$\?|\\\$\(.*\)|\\\$', '', + promptbase) else: promptbase = getuser() @@ -199,7 +253,7 @@ class ShellCmd(cmd.Cmd, object): def export(self): """ export environment variables """ # if command contains at least 1 space - if self.g_line.count(' '): + if self.g_line.count(' '): env = self.g_line.split(" ", 1)[1] # if it conatins the equal sign, consider only the first one if env.count('='): @@ -216,6 +270,10 @@ class ShellCmd(cmd.Cmd, object): cin, cout = os.popen2('`which echo` %s' % value) value = cout.readlines()[0] + # check if new exported environment + # is a prompt change command + self.check_prompt(var, value) + os.environ.update({var: value.rstrip()}) def source(self): @@ -485,11 +543,14 @@ class ShellCmd(cmd.Cmd, object): p = subprocess.Popen( "`which echo` %s" % item, shell=True, stdin=subprocess.PIPE, - stdout=subprocess.PIPE ) + stdout=subprocess.PIPE, + stderr = self.devnull ) (cin, cout) = (p.stdin, p.stdout) except ImportError: - cin, cout = os.popen2('`which echo` %s' % item) - item = cout.readlines()[0].split(' ')[0].strip() + cin, cout = os.popen2('`which echo` %s 2>/dev/null' % item) + shellresponse = cout.readlines() + if shellresponse: + item = shellresponse[0].split(' ')[0].strip() item = os.path.expandvars(item) tomatch = os.path.realpath(item) if os.path.isdir(tomatch) and tomatch[-1] != '/': tomatch += '/' @@ -559,6 +620,10 @@ class ShellCmd(cmd.Cmd, object): if len(env) is not 2: continue newenv.update(dict([env])) + # check if the new environment includes + # any Shell prompt change commands + self.check_prompt(env[0], env[1]) + os.environ.update(newenv) def loginCmdParse(self, script):