NAME

xssh - simple shell similar to csh

DISCLAIMER

This is the first time we have assigned xssh. Some details may be vague and subject to change; we'll alert you when they do.

SYNOPSIS

xssh [-x] [-d level] [file [arg] ]

DESCRIPTION

A shell is a process that does command-line interpretation.  It reads a command line from standard input and executes the command associated with the line read.  In the simplest case, the shell reads a command, forks a child process to execute the command, and waits on the child to terminate before it reads another command.  A real shell handles features such as foreground processing, background processing, redirection, pipelining, and signals.

In this project we will design, implement, and test a simple shell called xssh that will help us explore the intricacies of process creation, process termination, process identification, and process synchronization.

xssh is a lightweight shell similar to csh or tcsh but lacking many advanced features.

If a file is given it is treated as a script and input is taken from the file instead of stdin. Each additional arg is treated as an argument to script and assigned to the variables $1, $2, etc (positional variables).

OPTIONS

-x

Display the command line after variable substitution but before it is evaluated.

-d level

Set the debugging level to level. A debug level of 0 will not output any debug messages while 1 will output enough information to verify the correctness of the operation.

BUILTINS

When a user enters a command, xssh first attempts to run the builtin command of the same name. If there is no such builtin command then xssh searches for a matching external command and executes that instead.

Searching for external commands is done in two parts: If the command is a path (i.e. contains a slash) then the program given in path used. Otherwise xssh searches the directed listed in the PATH environment variable for a matching command.

The following is a list of builtin commands supported by xssh:

echo [word ]

Display each word separated by a space and a newline at the end.

quit [status]

Quit the shell. If status is not given quit with the exit status of the last executed command.

set [variable [value]]

When run with no arguments, display a list of all variables and their values. Otherwise set variable to value or the empty string if value is not given.

unset [variable ]

Remove the given variables. The value of a unset variable is undefined.

wait pid

Wait for the child process pid to complete. If pid is -1, wait for any child process to complete. If pid is 0, wait for all child processes to complete.

<chdir|cd> [path]

Change the working directory to path. If path is not given change to the directory given in the HOME environment variable. Note: the current directory is available from the PWD environment variable.

VARIABLES

With the exception of $$, $?, and $!, all variables in xssh are environment variables.

xssh preforms variable substitution on each command line before it is executed. Unlike real shells, xssh only expands variables if they appear by themselves. That is, variables embedded in a string such as "hello $world" are not substituted and the string remains "hello $world".

Variables are also only expanded one level. If the variable $X contains the string "$Y" the string "$Y" is used and is not expanded to the value of $Y.

If a command tries to expand an undefined variable, the shell should display a "variable undefined" error message and abort the command.

The following variables have special meaning:

$$

PID of this shell

$?

Exit status of last foreground command

$!

PID of last background command

REDIRECTION

The standard input and standard output of a command can be redirected to and from arbitrary files using the following syntax:

command [<input_file] [>output_file]

Both the input and output files are optional. Unlike a real shell the < or > is required to be the first character of the argument and cannot be separated from the filename by a space.

PIPELINES

Similarly to how redirection works, the standard input and standard output of multiple commands can be joined together using the following syntax.

command [| command]

When ever the left command prints any data to standard output that data is written as input to the command on the right. All commands in a pipeline should execute simultaneously so that large amounts of data can be processed without the need for arbitrarily large buffers.

Note that only the first command in a pipeline can have input redirected from a file and only the last command can have output redirected to a file.

BACKGROUND COMMANDS

When a command (or pipeline) is executed it can be followed with an ampersands (&) which indicates that the given processes should be run in the background as opposed to the foreground. A background a background command is run the shell will prompt the user for the next command even before the current command is done executing. A foreground command will cause the shell to wait until the subprocess exits before issuing another prompt.

MISCELLANEOUS

Each argument is separated by whitespace.

The command prompt is the three character sequence ">> " (>, >, space).

The # character signifies a comment. All characters following and including a # on the same line are ignored.

Blank lines are ignored

Extra features may be implemented at your desire as long as they do not beak compatibility with this document.

DIFFERENCES

There are many differences between xssh and "real" shells. Among the most obvious are the lack of the following:

Control structures such as if, then, while and functions definitions.

Interactive features and command line editing and history. (Note: this is trivial to implement using GNU Readline and may be useful during testing and debugging)

Advanced substitution such as filename expansion (~, *), command substitution, and local variables.

Job control such as moving processes between the foreground and background.

EXAMPLES

Start the shell and execute the commands specified in file passing in two arguments.

$ xssh script foo bar

Start the shell with debugging enabled.

$ xssh -x -d 1

Run the builtin command echo

>> echo Hello, World!

Run pipeline of commands in the background

>> nl <input.txt | nl | grep hello >output.txt &

SEE ALSO

sh(1), csh(1), tcsh(1), fork(2), pipe(2), wait(2)

BUGS

Note them in your README file.