ish - kind of like a shell


In this problem set, you will implement the shell ish, a command interpreter with a syntax and behavior similar to bash.

Initialization and Termination

When first started, ish normally performs commands from the file ~/.ishrc, provided that it is readable. Typically, the ~/.ishrc file contains commands to specify the terminal type and environment. (Here is an example .ishrc file, which doubles as a test case.) ish terminates when the user types CTRL-D or exit.

Interactive Operation

After startup processing, the shell interactively processes commands from the terminal, prompting with %. The shell repeatedly performs the following actions: a line of command input is read and broken into words; this sequence of words is parsed (as described under USAGE); and the shell executes the commands in the current line.


Lexical Structure

The shell splits input lines into words separated by spaces or tabs, with the following exceptions:

Command Line Parsing

A simple command is a sequence of words, the first of which specifies the command to be executed. A pipeline is a sequence of one or more simple commands separated by '|' . With '|', the standard output of the preceding command is redirected to the standard input of the command that follows.

You may assume that each simple command is of the form
        'command arguments redirection'
and that the syntax
        'command redirection arguments'
is illegal.

I/O Redirection

The following metacharacters indicate that the subsequent word is the name of a file to which the command's standard input or standard output is redirected.

Command Execution

If the command is an ish shell built-in, the shell executes it directly. Otherwise, the shell searches for a file by that name with execute access. If the command-name begins with a '/', the shell takes it as a full pathname, and tries to execute it. If the command-name does not begin with a '/', the shell attempts to resolve it to a pathname, searching each directory in the PATH variable for the command.

When a file is found that has proper execute permissions, the shell forks a new process and passes it, along with its arguments, to the OS using the execv or execl system call. (Do not use the execvp or execlp calls; your shell is responsible for searching the search path.) The OS then attempts to overlay the new process with the desired program. If the file is an executable binary the OS succeeds, and begins executing the new process. If the file does not have execute permissions, or if the pathname matches a directory, a "permission denied" message is displayed. If the pathname cannot be resolved a "command not found" message is displayed. If either of these errors occur with any component of a pipeline the entire pipeline is aborted, although some of the components of the pipeline may have already started running.

A pipeline is completed (i.e., returns to the prompt) only when all the commands that form a part of the pipeline and that are being executed in the foreground are completed.

Environment Variables

Environment variables may be accessed via the export and unset built-in commands. Initially, ish inherits environment variables from its parent. ish then maintains the environment variables internally using the C library routines setenv and unsetenv. The only environment variable that ish needs to interpret is PATH; all other environment variables can be set and unset in ish using the above built-in commands, but are not interpreted.

Background Processes and Job Control

All jobs run in the foreground. You need not support job control. However, you do need to be able to kill, using CTRL-C, the current foreground job.

Built-In Commands

In addition to export and unset (described above), you need to support the following built-in commands. Built-in commands execute as part of the ish process; you need not fork another process. Hence, you need not support built-ins as part of a pipeline.
cd [ dir ] Change the shell's working directory to directory dir. If no argument is given, change to the home directory of the user.
exit Exit ish.


~/.ishrc     Read at beginning of execution by each shell.


Words can be no longer than 1024 characters. Lines can be no longer than 2048 characters.


Submit your program (makefile, all source code, readme file) electronically with the command

/u/cs217/bin/submit 6

Your solution is due by 11:59 p.m., Tuesday, January 15, 2002. This is a hard deadline; no late work will be accepted.


Support a primitive history mechanism that includes the history built-in command, and the ability re-execute a past command by typing !prefix, just as in bash. (You need not support editing of this previous command to get the extra credit.) Note that since it is possible to include the history built-in in a pipeline, you will need to spawn a sub-shell in this case. This will also allow you to run export in a pipeline.