integ/base/lshell/files/lshell-source-support.patch

107 lines
3.6 KiB
Diff

---
lshell/shellcmd.py | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 64 insertions(+), 1 deletion(-)
--- a/lshell/shellcmd.py
+++ b/lshell/shellcmd.py
@@ -26,6 +26,7 @@ import re
import signal
import readline
import glob
+import subprocess
from utils import get_aliases
@@ -128,6 +129,9 @@ class ShellCmd(cmd.Cmd, object):
# builtin export function
elif self.g_cmd == 'export':
self.export()
+ # builtin source function
+ elif self.g_cmd == 'source':
+ self.source()
# case 'cd' is in an alias e.g. {'toto':'cd /var/tmp'}
elif self.g_line[0:2] == 'cd':
self.g_cmd = self.g_line.split()[0]
@@ -214,6 +218,14 @@ class ShellCmd(cmd.Cmd, object):
os.environ.update({var: value.rstrip()})
+ def source(self):
+ """ implementation of the "source" command
+ """
+ # ensure if command contains at least 1 space
+ if self.g_line.count(' '):
+ source_script = self.g_line
+ self.sourceShell(source_script)
+
def cd(self):
""" implementation of the "cd" command
"""
@@ -515,6 +527,57 @@ class ShellCmd(cmd.Cmd, object):
else:
self.prompt = '%s:%s$ ' % (self.promptbase, path)
+ def sourceShell(self, script):
+ """Source the shell script and call env when done in order to \
+ detect the new environment and then use that to update the \
+ environ of the lshell process.
+ """
+ pipe = subprocess.Popen("%s; env -0" % script,
+ bufsize=1,
+ stdout=subprocess.PIPE,
+ shell=True)
+
+ iterator = iter(pipe.stdout.readline, b'')
+ outputlist = list(iterator)
+ output = ''
+ for i, line in enumerate(outputlist):
+ if i == (len(outputlist) -1):
+ output = line
+ else:
+ sys.stdout.write(line)
+
+ # output may pick up some echos at the end of script and merge
+ # with the first line in env. Test for this and echo those to stdout
+ envList = output.split('\0')
+ firstenv = re.findall('^\S+=\S+$', envList[0], re.MULTILINE)
+ if firstenv:
+ print envList[0].strip(firstenv[0])
+ envList[0] = firstenv[0]
+ newenv = {}
+ for line in envList:
+ env = line.split("=", 1)
+ if len(env) is not 2:
+ continue
+ newenv.update(dict([env]))
+ os.environ.update(newenv)
+
+ def loginCmdParse(self, script):
+ """Parse the login command specified in login_script. \
+ If login_script or a sub script sources a bash config \
+ then call shell_source()
+ """
+ # if multiple commands are chained together, execute
+ # them individually. We will not support conditional
+ # chaining (&& or ||) since that would required the
+ # additional complexity of checking the retcode of
+ # the previous command
+ cmds = script.split(";")
+ for cmd in cmds:
+ if "source" in cmd:
+ self.sourceShell(cmd)
+ else:
+ os.system(cmd)
+
def cmdloop(self, intro=None):
"""Repeatedly issue a prompt, accept input, parse an initial prefix \
off the received input, and dispatch to action methods, passing them \
@@ -541,7 +604,7 @@ class ShellCmd(cmd.Cmd, object):
if self.intro and isinstance(self.intro, str):
self.stdout.write("%s\n" % self.intro)
if self.conf['login_script']:
- os.system(self.conf['login_script'])
+ self.loginCmdParse(self.conf['login_script'])
stop = None
while not stop:
if self.cmdqueue: