You are to write a C program that provides functionality similar to the shell. Your starting point is the supplied code smsh.c (and associated headers and files implementing some functions).
Compile this first and then run it. You should discover that it basically provides the functionality that allows a user to type in commands (like “ls” “ls –l” “cat filename” etc. – or names of binaries with the complete path specified, possibly with options). You should also see what it doesn’t do
(here is a partial list):
- It doesn’t allow for I/O redirection:
- It doesn’t allow for single command redirect of stdin, stdout or stderr.
- It doesn’t allow for commands to be piped together
- It doesn’t allow for any job control (^Z will stop the program itself, not the last job it started)
- It doesn’t handle builtins. Builtins are not commands exec’d but are commands that the shell handles directly rather than forking and exec’ing. See man builtin.
- It doesn’t do globbing/wildcard expansion (e.g., “cat *” ).
- It doesn’t allow variables to be set, doesn’t have an environment as an object you can manipulate etc
- It doesn’t understand the syntax of shell programs/scripts – no loops, no conditionals, etc etc.
You task is to add to this functionality, incrementally, in the order given:
- Produce a source file smshv1.c that will be compiled to the binary smshv1 that allows cmds to be piped together. In essence, this is assignment2 integrated into this “shell”. Assignment 2 didn’t parse a command line with the “|” symbols in it. You are given, in addition to the files for the starting version of the shell, a file which is a basic solution to assignment2 – this is provided for those people that didn’t manage to get a working solution to assignment2: you are welcome to use this in your code or, of course, you can use your code from assignment2. This introduces the concept of a job. A job is either a single cmd (with or without args) or a combination of commands piped together. To appreciate this try (in the real shell) cat | more (which will of course “just sit there” as cat has no input until you type). Then press ^Z and you see that the combination of cmds is stopped as a single job, which can be resumed.
- Produce a source file smshv2.c that adds functionality to smshv1 to allow for parsing of (and implementation of!) redirection of I/O. This should work for a single command (with or without args) and with redirection of two or three streams, and with this form of indirection in a pipe.
- Produce a source file smshv3.c that adds functionality to smshv2 to allow for limited job control. The functionality is merely that when one types something like “cat myfilename &” that the prompt returns automatically so the user can type in another command without having to wait until that job completes. Note this should work for single commands and for multi-command jobs.
- Produce a source file smshv4.c that builds on the functionality of smshv3 to add a limited number of builtins. The list you must cater for is pwd, cd, pushd, popd. These query or manipulate the current directory – you will need to implement a simple stack. Only “bare bones” versions need be implemented (cd and pushd are the only ones that need to be able to take an argument: you can put a small fixed limit on the stack size). Note: even the starting smsh.c DOES respond intelligently to pwd but it doesn’t for cd, pushd, and popd. (Why?) BTW see man 1 pwd for the pwd your shell should no longer use – it gives you a clue as to how to implement as a builtin without execing a command.
Extra challenge (not for marks for undergraduates but compulsory for postgrads) – how would you implement job control such as is provided by the builtins: fg bg jobs kill. Put in a few paragraphs in your report about what data structures and information would you have to maintain to go about this and how you would implement in terms of high level pseudocode.
Extra challenge (again not for marks for undergrads but compulsory for postgrads) – provide additional functionality to produce smshv5.c that handles ^Z in so far as typing ^Z does not stop you shell but stops any command that is yet to complete running. Some marks will be awarded for only describing, in your report, how this would be implemented but I expect you could at least implement the functionality of avoiding ^Z stop your shell – if not the functionality of stopping the last uncompleted single cmd job (if there is one at the point of typing the ^Z).