3cd12006bb
Signed-off-by: Dean Troyer <dtroyer@gmail.com>
107 lines
3.6 KiB
Diff
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:
|