Permalink
Browse files

implement pipe

  • Loading branch information...
1 parent 947fb04 commit 6862c8a80fef6202655c8b44407babfb09a7f2ee @nonylene committed Dec 31, 2016
Showing with 72 additions and 8 deletions.
  1. +72 −8 nsh
View
@@ -1,29 +1,85 @@
#! /usr/bin/python3
import sys
import os
+import signal
+
+# do not ignore SIGPIPE
+signal.signal(signal.SIGPIPE,signal.SIG_DFL)
def main():
while True:
line = input(os.getcwd() + ' $ ')
- args = parse_line(line)
+ commands = parse_line(line)
+ if [] in commands:
+ print("no command")
+ continue
+ execute_commands(commands)
+
+def execute_commands(commands):
+
+ def wait_child(pid):
+ while True:
+ wpid, status = os.waitpid(pid, os.WUNTRACED)
+ if os.WIFEXITED(status) or os.WIFSIGNALED(status):
+ break
+
+ if len(commands) == 1:
+ args = commands[0]
if args[0] in builtin_functions:
builtin_functions[args[0]](args)
else:
- execute_line(args)
+ pid = os.fork()
+ if pid == 0:
+ os.execvp(args[0], args)
+ elif pid < 0:
+ print("error with fork!")
+ else:
+ wait_child(pid)
+ else:
+ pid = os.fork()
+ if pid == 0:
+ execute_pipe(commands)
+ elif pid < 0:
+ print("error with fork!")
+ else:
+ wait_child(pid)
+
+def execute_args(args, exit_builtin = False):
+ if args[0] in builtin_functions:
+ builtin_functions[args[0]](args)
+ if exit_builtin: exit()
+ else:
+ os.execvp(args[0], args)
-def execute_line(args):
+def execute_pipe(commands):
+ # use as queue
+ current_args = commands.pop(-1)
+ end = len(commands) == 1
+ r, w = os.pipe()
pid = os.fork()
if pid == 0:
- os.execvp(args[0], args)
+ # child
+ os.close(r)
+ os.dup2(w, 1)
+ os.close(w)
+ if len(commands) == 1:
+ # last
+ args = commands[0]
+ execute_args(args, True)
+ else:
+ execute_pipe(commands)
elif pid < 0:
print("error with fork!")
else:
- while True:
- wpid, status = os.waitpid(pid, os.WUNTRACED)
- if os.WIFEXITED(status) or os.WIFSIGNALED(status): break
+ # parent
+ os.close(w)
+ os.dup2(r, 0)
+ os.close(r)
+ execute_args(current_args, True)
# TODO: use AST?
def parse_line(line):
+ commands = []
args = []
current_arg = str()
@@ -70,10 +126,18 @@ def parse_line(line):
append_arg(False)
else:
current_arg += s
+ elif s == "|":
+ if not (single_quote or double_quote or escaping):
+ append_arg(False)
+ commands.append(args)
+ args = []
+ else:
+ current_arg += s
else:
current_arg += s
append_arg(False)
- return args
+ commands.append(args)
+ return commands
def builtin_cd(args):
directory = args[1] if len(args) > 1 else '~'

0 comments on commit 6862c8a

Please sign in to comment.