Homework 5 - homebrew command line interpreter

The command line interpreter, or "shell" in Unix is an incredibly powerful tool in the hands of an experienced user. Its main function is to providing an intuitive and efficient way to combine many small commands to create new functionality.

In this homework, we will create our own shell, supporting many of the basic functions available in bash and other popular shells.

Copy the hw5 template to your turn-in directory thus:

svn export svn://bits.cs.uic.edu/cs361/pub/homeworks/hw5

svn add hw5

You will also need to install the readline developer files:

sudo apt-get install libreadline-dev

PATH support

The template code requires the absolute path of the binary you want it to run. Change it to automatically look for the program in all of the directories indicated by PATH, except for filenames that contain a '/'. Thus, make ls do the same thing as /bin/ls, but also make sure that mydir/mybinary still works correctly.

HINT: getenv() to get the environment variable, then strsep() to split it into multiple path strings. Finally, sprintf() to compose a full path out of its components.

Commands with command-line arguments

Support up to 10 command line arguments. For example echo hello world, should produce hello world.

HINT: you could use strsep() to split the arguments into an array, which you then pass to execve().

Redirection to and from files

Support stdin and stdout redirection to and from files. For example, ls > /tmp/templ should create a file (with correct permissions) containing the output of ls. Similarly wc < /tmp/templ should use the file as input, and wc < /tmp/templ > /tmp/count uses both input and output redirection.

HINT: use open() to open a file, and dup2() to change where stdin(0) or stdout(1) points to.


Support piping of the stdout from one command to stdin to another. For example:

ls -l | sort -n -k 5 | cut -c 27-34 > /tmp/sizes

produces a file containing a sorted list of file sizes.

HINT: this is by far the most challenging part of the homework. Use fork() as in the template code to start up multiple concurrent processes, pipe() to create pipes through which processes communicate, and dup2() to redirect output into and out of pipes. Finally, use waitpid() to wait for child processes to finish.

Variable substitution

The template code already supports interpreted scripts. There are a couple of examples in the template directory, ending with .hw5. Add support for command line arguments to such scripts. For example,

./echo.hw5 hello world
hello world hello

Replace any occurrence of $1,$2,$3 etc with the first, second, third command line argument respectively.

HINT: this one will require some manual string manipulation, but strchr() to find each "$", and strncpy() to copy part or all of strings is a good start.

Wildcard variable substitution

WARNING: this is not yet tested for in the testing script.

Replace any occurrence of * in the command line with a list of files in the local directory. To list files, use readdir() and associated functions.

HINT: you don't need to support anything but the pure * wildcard. However, for extra pound-on-my-hairless-chest geek credit, see if you can figure out how to support things like *.txt, hw *, and *stuff*and*other*stuff. I'm pretty sure fnmatch() will be handy.

Testing your code

Try running ./test.hw5. Below is the expected output. Of course, the results from "ls" and the number of files will vary depending on what's in your directory.

* Echo seems to work
* Now the directory contents:
Makefile   echo.hw5   hw5      hw5.c      hw5.dSYM   hw5.sh~      test.hw5
* Now the number of files:
* Now we should see "Hello World":
Hello World
* And now the contents of /tmp/countfile
* Now a list of file sizes

* And finally "hello world hello world"
hello world hello world

This topic: CS361fall13 > Homework5
Topic revision: r1 - 2013-09-24 - 01:16:58 - Main.jakob
Copyright 2016 The Board of Trustees
of the University of Illinois.webmaster@cs.uic.edu
Helping Women Faculty Advance
Funded by NSF