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 goshThe project is divided into discrete steps that you can follow. Each step will define a test that you can run and expected behaviour. Please make your shell follow this behaviour.
Deliverables: A tar file that contains only the following:
gosh> ls -a -l -d /etc
c1 0: ls
c1 1: -a
c1 2: -l
c1 3: -d
c1 4: /etc
gosh>
gosh>
gosh>
gosh>
gosh>
gosh> exit
hangao@gawaine:~/cspp51081/LAB4$
Step 2: Fork/Exec
Write a simple fork/execvp procedure to execute
command c1 in a
child process. If the command inputted does not exist, the
child should
print an error message and exit. The relevant examples (C
code) from
the book are here: create a child process with fork and
wait for its termination,
replace a process image (details: BLP, chapter 10).
gosh> ls -l /etc/passwd
c1 0: ls
c1 1: -l
c1 2: /etc/passwd
Running Command
---------------
lrwxrwxrwx 1 root root 14 Jul 6 1999 /etc/passwd
-> ./local/passwd
---------------
Command Returned Exit Code 0
gosh>
Step 3: 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 4: 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 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
Step 3: help
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 4: Deliverables
A tar file that contains all code: *.c and *.h (if necessary) and a script file shows how your codes work.
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 receives 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 receives 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.
Step 4: Deliverables
A tarball that contains all code: *.c and *.h (if necessary), makefiles, and a script file shows how your code works.