The following are implementation requirements and recommendations for your shell program:
(Required) Your program must be modular at the function level. Define small functions, each of which does a single well-defined job.
(Required) Your program must be modular at the source code file level. Define interfaces and implementations, thus splitting your program into multiple files.
(Required) Define stateless modules as appropriate. A stateless module is one that does not have any associated data. For example, your Str
module from Assignment 2 is a stateless module; it consists of a group of related functions, but does not encapsulate any data.
(Required) Define abstract objects and abstract data types as appropriate, thus encapsulating data structures with functions.
(Recommended) Your program may use the DynArray
ADT (from early precepts). The source code is available through the course web pages, and also in the /u/cos217/Assignment7
directory on nobel.
(Required) If the user specified a command-line argument to your program, then your program must interpret the command-line argument as the name of a configuration file. It is not an error for the user to omit the command-line argument. If the user specifies more than one command-line argument, then the program must write an error message and exit.
(Required) If the configuration file exists and is readable, then your program must read and interpret all commands from that file. If the configuration file does not exist or is not readable, then your program must write an error message. In either case, your program then must read and interpret all commands from stdin
.
If your program does not support reading a configuration file, or does not interpret commands from that file, then it will fail all of our tests. In that unfortunate circumstance, the grade would be reduced substantially.
(Required) Your program must write the commands from the configuration file. That is, immediately after your program reads a command from the configuration file, it must write its "% " prompt and that command to stdout
. In that manner your program must generate a transcript that shows each command of the configuration file, followed by the output that results from executing that command.
If your program does not write the commands of the configuration file to stdout
, then it will be difficult to interpret the transcript. In that unfortunate circumstance, the grade would be reduced.
(Required) Your program must not write the commands from stdin
. That is, when your program reads a command from stdin
, it must not write that command to stdout
.
(Required) Your program must make no assumptions about the maximum number of characters in each line read from the configuration file or from stdin, the maximum length of the name of the given command, the maximum length of any of the command-line arguments of the given command, or the maximum number of command-line arguments of the given command.
(Recommended) Your program must define the readLine
function given in the dfa.c
precept example program, and must read each input line by calling that function.
(Required) Your program must not call the system
function.
(Required) A programmer error is one that could not possibly be caused by user input. Your program must detect a programmer error via an if
statement, report the error via a descriptive error message written to stderr
, and then exit with EXIT_FAILURE
as the status code.
(Required) Invalid function parameter is a special-case programmer error. Your program must call the assert
macro to handle that error. Of course the assert
macro will detect the error, report the error by writing a message to stderr
, and exit.
(Required) A user error is one that could be caused by user input. Your program must detect a user error via an if
statement, and report the error via a descriptive error message written to stderr
. Then your program must reject the offending input line and continue execution.
(Required) In general heap exhaustion (that is, a failed call of malloc
, calloc
or realloc
) could be caused by user input, and so must be treated as a user error. However in this particular program (1) there is no reasonable user input that could cause heap exhaustion, and (2) if heap exhaustion does occur, then there is no reasonable way for your program to recover from it and continue execution. So your program must treat heap exhaustion as a programmer error. That is, your program must detect heap exhaustion via an if
statement, report the error via a descriptive error message written to stderr
, and then exit with EXIT_FAILURE
as the status code.
(Required) Your program's error messages must begin with "programName: ", where programName
is your program's argv[0]
. Note that the name of your program is not necessarily "ish"; the user might have renamed the executable binary file to something other than "ish".
(Required) After a failed call of a function that sets the errno
variable, your program must call the perror
or strerror
function to write an appropriate error message to stderr
.
(Recommended) Implement your lexical analyzer as a deterministic finite state automaton.
(Required) Your program must call the isspace
function to identify white-space characters.
(Recommended) Create some temporary code that writes the token list created by your lexical analyzer. Do not proceed to subsequent phases until you test your lexical analyzer thoroughly.
(Recommended) Test your lexical analyzer by making sure that it handles these example input lines properly:
INPUT LINE | TOKEN ARRAY |
one |
one |
123 |
123 |
one123 |
one123 |
123one |
123one |
@#$%^&*() |
@#$%^&*() |
' |
' |
one two |
one two |
one two |
one two |
one two |
one two |
one > |
one > |
one> |
one > |
>one |
> one |
"one" |
one |
">" |
> (an ordinary token) |
"one two" |
one two |
one"two" |
onetwo |
"one"two |
onetwo |
"one |
ERROR |
one"two |
ERROR |
(Recommended) Your program's lexical analyzer must represent tokens so that the difference between quoted and unquoted special characters is adequately captured. For example, these two commands are very different, and that difference must be captured at the lexical analysis phase:
echo one > two echo one ">" two
(Recommended) Your program must do as much validation of the command as possible at the syntactic analysis phase. The more error checking you do during the syntactic analysis phase, the less must be done during the (more complicated) execution phase.
(Recommended) Create some temporary code that writes the command created by your syntactic analyzer. Do not proceed to subsequent phases until you test your syntactic analyzer thoroughly.
(Recommended) Test your syntactic analyzer by making sure that it handles these valid and invalid example input lines properly:
INPUT LINE | VALID/INVALID |
cat |
Valid |
cat file1 |
Valid |
cat < file1 |
Valid |
cat > file1 |
Valid |
cat < file1 > file2 |
Valid |
cat > file1 < file2 |
Valid |
cat file1 > file2 |
Valid |
cat > file2 file1 |
Valid |
< file1 |
Invalid |
cat file1 < |
Invalid |
cat file1 > |
Invalid |
cat file1 > file2 > file3 |
Invalid |
cat < file1 < file2 |
Invalid |
(Required) Your program must call fflush(NULL)
before each call of fork
to clear all I/O buffers.
(Required) Your program must call the setenv
function to implement the setenv
shell built-in command.
(Required) Your program must call the unsetenv
function to implement the unsetenv
shell built-in command.
(Required) Your program must call the chdir
function to implement the cd
shell built-in command.
(Required) Your program must call exit(0)
to implement the exit
shell built-in command. Or, implement the exit
command by returning 0 from the program's main
function.
(Required) Your program must call the signal
function to install signal handlers.
(Required) Your program must call the alarm
function to control handling of SIGQUIT
signals.
(Required) Your program must use the SIG_IGN
and SIG_DFL
arguments to the signal
function, as appropriate.
(Required) Your program must call the sigprocmask
function near the beginning of the main
function to make sure that SIGINT
, SIGQUIT
, and SIGALRM
signals are not blocked.