Homework 6 Due Friday, Apr 5 In assignment hw4, you took a mini-shell in C, and fixed three bugs. In this assignment, you will take the original mini-shell (hw4/hw4.c) and translate it into a Python program, myshell.py. You must also fix Bugs #1 and #2. (You do _not_ need to fix bug #3). (Please note that getword() includes a call to getenv. The Python translation of getenv() is os.getenv() and you must include that in your translation.) You will need to do this assignment in Linux, since we are writing a Linux shell. Recall that Python can also be used interactively. The examples below assume that you have run 'python' with no arguments and are testing interactively. First, note that the instructor's directory has a Python tutorial: python-tutorial.txt You will also find other excellent tutorials on the Webs. Before starting, here are some useful Python functions for strings and arrays: len([3, 4, 'abc']), len("abcdef"), "abcdef\n".strip() "abc def ghi".split(), "abcdef"[0:2], "abcdef"[0:-1], "abcdef"[3:] range(5) help(range) for i in range(5): print i As always, remember to use a debugger. In Python, the debugger command is: python -mpdb myshell.py [ 'help' shows commands, similar to gdb ] Without the debugger, it's: python myshell.py Let's start. First, replace the C functions, getword() and getargs(), by inline Python functions. Some Python functions that will help you are: If x is the line you read from the user, it's very easy: >>> x = "ls -l README" >>> print x.split() And you'll need to print a '(myshell)' prompt, and read from stdin. Call google on: python stdin http://stackoverflow.com/questions/1450393/how-do-you-read-from-stdin-in-python >>> import sys >>> print '(myshell) ' >>> print sys.stdin.readline() >>> myinput = sys.stdin.readline() >>> print myinput.readline() Also, you will need the os module (library) for fork and exec: >>> import os >>> os.execvp("ls", ["ls", "-l"]) >>> # os.fork() == 0 implies 'child' ... if os.fork() == 0: ... os.execvp("ls", ["ls", "-l"]) ... Now fix Bug #1 (respect the comment character, '#'): Call google on: python regular expression It will show you that you need the re module (library): http://docs.python.org/library/re.html >>> import re >>> # In the regular expression '^[^#]*', the first '^' means to start ... # at the beginning of the line. The '[^', ']' means match ... # _anything_ except the characters inside. (Match anything ... # _except_ the character '#' ... matches = re.search('^[^#]*', 'ls -l#This is a comment') >>> print matches.group(0) # get match number 0 >>> print matches.group(0).split() Now fix Bug #2: Call google on: python argv It will show you that you need the sys module (library): http://docs.python.org/library/sys.html >>> import sys >>> shellArgs = sys.argv >>> argc = len(sys.argv) >>> import sys >>> # We cheat to test interactively. You don't need this in your program: ... sys.argv = ['myshell', 'myshell.input''] >>> # Let's also open a file and put text in the file myshell.input: ... # Calling google on 'python file create' produces this technique: ... newfile = open(sys.argv[1], "w") >>> # What methods can you call on newfile? ... help(newfile) >>> newfile.write("ls -l") >>> newfile.close() >>> # Now let's read from the file: ... if len(sys.argv) >= 2: ... mystdin = open(sys.argv[1], "r") ... print mystdin.readline() ... >>> # OR: ... if len(sys.argv) >= 2: ... mystdin = file(sys.argv[1]) ... print mystdin.readline() ... You can then use "mystdin.readline()" with mystdin either as mystdin == file(sys.argv[1]) #batch mode or: mystdin == sys.stdin #interactive shell) Still another option is: >>> if len(sys.argv) >= 2: ... sys.stdin = file(sys.argv[1]) # redirect stdin to come from file ... Note that when you reach the end of a file, myinput.readline() returns the empty string, ''. This is different from reading a blank line, which returns '\n'. Your program will need to test for '' in myinput. Now move your three 'import' statements to the beginning of your file, so that you can use those module functions anywhere: import re import os import sys You'll also want to use functions: def shell(): At the end of your Python script, be sure to call your top-level ("main") function: shell() Next, add to the beginning of your program, myshell.py, the line below. (Note that '#' is the Python comment character. So, this is just instructions to the operating system to call Python.) #!/usr/bin/python Then make sure that your program myshell.py is executable: chmod a+x myshell.py