All work should be done on a machine in the department's Linux cluster. You can refer to ssh for more information on how to log into a remote machine.
Part 1 | 6 points |
Part 2 | 3 points |
Part 3 | 3 points |
TOTAL | 12 points |
We have provided you with a simple shell template that you can choose to work from. You can compile the shell using the following command assuming you've untarred the package and entered the gosh_template subdirectory:
gcc -I./ gosh_template.c -o goshEach step will define a test that you can run and expected behaviour. Please make your shell follow this behaviour.
Step 1: Internal
Commands
Add support for internal shell commands: cd and pwd.
gosh> cd /usr/lib
c1 0: cd
c1 1: /usr/lib
Running Command
---------------
change dir: success
---------------
Command Returned Exit Code 0
Step 2: Environment
Variables
Add support for environment variables.
gosh> MYVAR='All work and no play makes
Jack a dull boy'
c1 0: MYVAR='All work and no play makes Jack a dull boy'
Running Command
---------------
define new variable: success
---------------
Command Returned Exit Code 0
Step 3: Redirection
Add support for redirecting output to the same file using 2>&1 command line syntax.
gosh> redirect.sh > results.log 2>&1
c1 0: ...
Running Command
---------------
dup file handle: success
---------------
Command Returned Exit Code 0
gosh>
Step 4: Signal Handling
Add support for signal handling of SIGCHLD signals. Note you are to use the POSIX sigaction()
signal set API and approach in this lab, rather than the older and
simpler signal() API (see Kerrisk 20.13 ff.). The SIGCHLD signal
is sent to a parent (i.e. your shell) whenever one of its child
processes terminates. Inside the handler, use some form of wait
to reap the terminated child process. Print out to the screen
that a child process has been reaped (and rewrite the prompt
properly). You willl want to think about issues with reentrancy
in all this. Make sure you have read and consumed section 26.3 of
Kerrisk.
Step 5: See Deliverables
Step 1: background
A pair of related processes can use an 'unnamed pipe' to pass information between them. When a pipe is created, the operating system sets up two file descriptors: one that can be read from and one that can be written to. Any data put into the pipe (by writing to the 'write' side of the file descriptor) by one process can be grabbed by another (by reading from the 'read' file descriptor). One common use of this function/structure is to create a pipe and write the stdout from one process to the pipe's write file descriptor and read from the pipe's read file descriptor to another program's stdin. We use this system all of the time:
cat /etc/passwd | grep root
We are 'piping' the stdout from 'cat /etc/passwd' to the stdin of 'grep root'. The program that usually sets up this pipe for you is the user shell. The program flow is as follows:
program has two commands to run
program sets up a pipe using 'pipe()'
program forks
the parent closes the pipe writer file descriptor
the parent runs 'dup2()' to duplicate it's stdin to the pipe's reader
the child closes the pipe reader file descriptor
the child runs 'dup2()' to duplicate it's stdout to the pipe's writer
both parent and child run 'execvp()' or similar to run the commands
Step 2: my_upipe
In this portion of the lab project, you will write a simple program that creates a pipe between two processes given on the command line. The syntax for this program is as follows:
./my_upipe "cat /etc/passwd" "grep root"
You may want to borrow code from your gosh project to handle the tokenizing of the two commands given. We will test the following commands on CS linux boxes:
gawaine:$ ./my_upipe "cat /etc/services" "more"
# /etc/services:
# $Id: services,v 1.4 1997/05/20 19:41:21 tobias Exp $
#
# Network services, Internet style
...
...
--More--
...
...
gawaine:$ ./my_upipe "cat /etc/passwd" "grep root"
root:x:0:0:Super-User:/:/bin/bash
gawaine:$ ./my_upipe "ls -a -l /usr/bin" "wc"
501 4668 32853
There are example programs that use 'pipe' in the BLP. Also, you can look in /home/mark/pub/51081/pipes for some example code.
Step 1: background
A pair of unrelated processes can use a 'named pipe' to pass information between them. Unlike 'unnamed pipes', however, 'named pipes' are accessed as a file on the file system. This allows a situation where two processes started in separate shells can communicate with eachother through a 'named pipe' on the file system. A named pipe, or FIFO, can be created using the 'mkfifo()' function. It can be removed (like any other file on the file system) using the 'unlink()' function. Once a named pipe file exists, programs can open it like they would other files and then use the file descriptor obtained to perform regualar file IO operations on the (read, write, close...).
Step 2: my_npipe
You will write two simple programs 'my_npipe_reader.c' and 'my_npipe_writer.c' that use a named pipe to communicate. The 'my_npipe_reader' program will set up a named pipe using 'mkfifo()', open it read only, and read strings from it until it recieves the string 'exit'. The writer will open the named pipe file, read strings from the user and write them to the named pipe. When the user enters 'exit', the program will write the string to the pipe and then exit. Execution should look something like this (note that you must start the reader first):
reader:
gawaine:$ ./my_npipe_reader
Creating named pipe: /tmp/mypipe
Waiting for input...Got it: 'hello world'
Waiting for input...Got it: 'foober goober'
Waiting for input...Got it: 'exit'
Exiting
writer:
gawaine:$ ./my_npipe_writer
Opening named pipe: /tmp/mypipe
Enter Input: hello world
Writing buffer to pipe...done
Enter Input: foober goober
Writing buffer to pipe...done
Enter Input: exit
Writing buffer to pipe...done
Exiting
Note that the 'my_npipe_reader' and 'my_npipe_writer' need to be executed in separate shells at the same time. The reader stops at 'Waiting for input...' until it recieves data from the pipe (the read completes).
Step 3: Help
Use BLP as a reference, there are many good code examples for named pipe usage. Also, see /home/mark/pub/51081/pipes for example code.
Carefully follow the steps below.
my_upipe
"cat /etc/passwd" "grep root"
To | Nicholas Flees (nickflees@uchicago.edu) |
Attachment | username.lab5.tgz |
Subject | CSPP51081-lab5 |