Thursday, March 3, 10pm
The starter code for this assignment is your basic shell from Assignment 5. Take the first few days to improve the basic shell functionality if some tests weren’t passing. Continue developing in your A5 repository.
This is a pair assignment, but you can work alone, if you so choose.
Submit the contents of your repository via Gradescope. See Deliverables below for what to submit. If you are working with a partner, do not forget to include their name with the submission.
In this assignment, we will expand on the basic shell you wrote as part of Assignment 5. The basic shell functionality will form part of this assignment.
You are asked to implement builtin commands, as well as the following 4 operators:
echo one; echo two
sort < foo.txt
sort foo.txt > output.txt
sort foo.txt | uniq
Note that these operators can be combined. Follow the implementation strategy suggested below. This will give you the relative priorities of the operators.
In addition to running programs, shells also usually provide a variety of built-in commands. Let’s implement some.
The shell should support at least the following built-in commands, in
addition to exit
from Assignment
5:
cd
(change
directory)pwd
command (not a built-in).
source
prev
help
;
The behavior of ;
is to execute the command on the
left-hand side of the operator, and once it completes, execute the
command on the right-hand side.
<
A command may be followed by <
and a file name. The
command shall be run with the contents of the file replacing the
standard input.
>
A command may be followed by >
and a file name. The
command shall be run as normal, but the standard output should be
captured in the given file. If the file exists, its original contents
should be deleted (“truncated”) before output is written to it. If it
does not exist, it should be created automatically.
|
The pipe operator |
runs the command on the left hand
side and the command on the right-hand side simultaneously and the
standard output of the LHS command is redirected to the standard input
of the RHS command.
Implement the extensions in shell.c
.
Include any .c
and .h
files your
implementation depends on and commit everything to your repository. Do
not include any executables, .o
files, or other binary,
temporary, or hidden files.
About 25% of the grade for this assignment will be for the functionality of the basic shell from Assignment 5. This means that if you’ve completed that assignment, you get 25% for free on this one. If you didn’t get it quite right, completing it will give you 25% of the grade for this assignment right away. You won’t get a lesser grade for the functionality than you did in the previous assignment.
Here’s a set of “rough and ready” guidelines for tackling the extra shell functionality. Note that each subcommand might contain other operators as well. You might want to implement sequencing or redirection first.
command1; command2
command1
(recursively).command2
(recursively).command1 | command 2
stdout
, close other side.command1
.stdin
, close other side.command2
.command <OP> file
command
(recursively).All this functionality needs to be implemented by you, using system calls. Relying on the default shell does not fulfill the requirements.
man
is your friend. Check out fork
,
open
, close
, read
,
write
, dup
, pipe
,
exec
, …if
-else if
-else
or a multi-case
switch
should
be the only reason to go beyond 40-50 lines per function. Even so, the
body of each branch/case should be at most 3-5 lines long.valgrind
with --leak-check=full
to
check you are managing memory properly.Here are some examples you can use to test the shell functionality.
The line
echo one; echo two
should print
one
two
Running
echo -e "1\n2\n3\n4\n5" > numbers.txt; cat numbers.txt
should print
1
2
3
4
5
and result in a file called numbers.txt
being created in
the current directory.
Running
sort -nr < numbers.txt
after the above, should print
5
4
3
2
1
Running
shuf -i 1-10 | sort -n | tail -5
should print
6
7
8
9
10
You might consider some of the following optional features in your shell to challenge yourself (there is no extra credit for this):
Switching processes between foreground and background
(fg
and bg
commands).
Grouping command expressions. E.g.:
( cat prologue.txt ; ( cat names.txt | sort ) ; cat epilogue.txt ) | nl