-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathpsh.py
63 lines (53 loc) · 1.83 KB
/
psh.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#!/usr/bin/env python3
"""psh: a simple shell written in Python"""
import os
import subprocess
import shlex
import sys
# https://xiayingp.gitbook.io/build_a_os/os-interfaces/pipes
# TODO(max): Define shell variables and add them to environment variables
# TODO(max): Pass env to Popen
# TODO(max): Read shell/environment variables
def memfd(output: bytes):
fd = os.memfd_create("tmp")
result = open(fd, "w+b")
result.write(output)
result.seek(0)
return result
def main():
while True:
try:
inp = input("psh> ")
except EOFError:
inp = "exit"
pipeline = inp.split("|")
stdin = sys.stdin
stdout = sys.stdout
stderr = sys.stderr
for idx, command in enumerate(pipeline):
# TODO(max): Figure out how to do I/O pipes and stuff for built-in
# commands.
tokens = shlex.split(command)
# TODO(max): Ask students why cd needs to be a builtin
if tokens[0] == "cd":
os.chdir(os.path.abspath(tokens[1]))
continue
# TODO(max): Ask students why it is fine to comment out pwd "builtin"
# if tokens == ["pwd"]:
# print(os.getcwd())
# continue
if tokens[0] == "banana":
stdin = memfd(b"Peel!\n")
continue
if tokens == ["exit"]:
print("Goodbye.")
return
result = subprocess.Popen(
tokens, stdin=stdin, stdout=subprocess.PIPE, stderr=subprocess.PIPE
)
sys.stderr.write(result.stderr.read().decode("utf-8"))
stdin = result.stdout
# Write the last command's stdout to shell stdout
sys.stdout.write(stdin.read().decode("utf-8"))
if "__main__" == __name__:
main()