In Lab 2, you will create a simple command line interpreter. Command line interpreters are often called shells, particularly on systems that provide more than one and allow users to choose. We will create a shell program named nanosh, which will contain code (much of which you will write) to carry out a very, very small number of user commands but will also spawn processes to run external commands.
• Managing data in an array
• While loops
• Error handling and reporting using errno and perror()
• Calling system functions to retrieve information from the environment and to set the current working directory
• Using fork(), exec() and wait() to run a second program and wait for it to complete
A template .C file is provided for this assignment to suggest a logic flow for the program. Your task is to read input from the keyboard a line at a time, parse that line into commands and arguments, populate an array with each word type and executing commands based on what was typed.
Makefile and nanosh.c are found on icarus in /var/classes/cs3100/lab2/lab2.tar and should be copied to your ~/cs3100/lab2 folder:
scp USER@icarus.cs.weber.edu:/var/classes/cs3100/lab2/lab2.tar . tar xvf lab2.tar
cp template/nanosh.c .
cp template/Makefile .
Edit nanosh.c and see what has already been provided. Do not alter Makefile. When you feel you are ready for grading, upload just nanosh.c to Canvas. Compile using make, which will call gcc with the correct parameters, rather than executing gcc directly. I strongly recommend testing each feature completely as you design and code it before moving on to the next feature. Include error handling and testing as you develop each feature.
nanosh is a program that accepts commands and executes those commands, in a continuous command loop. In this loop, nanosh prints a prompt (nanosh: ), allow the user to type a line of input and hit RETURN, then nanosh should recognize and execute the command entered. nanosh should recognize the following commands:
Page !1 of !5
exits the program (don’t laugh…it is important to have)
displays the current working directory on stdout
changes the current working directory to the path found in environment variable
changes the current working directory to NEWDIR
executes ANYOTHERCOMMAND and passes any commandline parameters.
Waits until ANYOTHERCOMMAND completes.
If no command (or nothing but whitespace) is entered, ignore the command
The so-called “command loop” does the following (in a continuous loop) as a suggested logic flow:
• Prints the prompt
• Reads a line from the keyboard
• Populates an array of strings called myArgv with each element of the array pointing to a word on the commandline. All whitespace (tab, newline or space) is ignored. An integer called myArgc contains a count of the number of strings in myArgv.
• The first word on the line is compared to one of the known internal commands: exit, cd, chdir, pwd
• If the first word is one of the known commands, a function written for that command is called, passing it myArgc and myArgv. The called function checks for parameter errors and executes the requested function, then returns to the loop.
• If the first word is not a known command, call a function that will fork() and exec() a new process. The child process should execvp() the requested program and pass myArgv. The parent process should issue waitpid() and then return.
• returns to the top of the loop
• If exit, pwd or cd are entered with an invalid number of parameters, nanosh should set errno to EINVAL, call perror() with an appropriate message, ignore the command and restart the loop
• If one of the commands fail, call perror() with an appropriate message and restart the loop.
• If ANYOTHERCOMMAND is entered and that command cannot be found on the system (meaning execvp() fails, call perror()with an appropriate message.
• If a command is successful, do not issue any message whatsoever. Simply restart the command loop. Issue messages only when an error occurs.
Here is an example of how your nanosh should behave:
Page !2 of !5
nanosh: cd ..
Special form of the “cd” command
that chdir() to $HOME
nanosh: cd cs3100/lab2
Here I hit RETURN 3 times
nanosh: cd too many parameters
Invalid number of parameters to cd: Invalid argument
execvp() failed: No such file or directory
nanosh: ls -al /etc/vim
I called the external “ls”
root root 12288
nanosh: cd /etc/vim
Invalid number of
failed: Invalid argument
Hints and Suggestions
• When issuing an error message, make sure errno is set properly before calling perror() or perror() will issue the message “Success”. Always call perror() to issue error messages and printf() to issue informational messages.
• Use the man pages for syntax for system calls (we will discuss this in class)
• exit: call exit(0) if no parameters are specified; otherwise, issue an error message, ignore the command and return to loop
• getting parameters: use strtok() to read words from the line typed by the user, add to myArgv and count in myArgc.
• pwd: call getcwd()
• cd: call chdir() and getenv(“HOME”)
• executing external programs: call fork(), execvp() and waitpid() and always check the return code from each to report any errors. If an error occurs in execvp(), exit the process with exit(0) after issuing an error message. If this is mysterious, ask why in class.
• If an error occurs and you need to exit the program, use exit(1). On normal termination, use exit(0).
I often use scripts to help grade programs. Please note the following:
• My scripts use the gcc compiler to compile your programs. If you use a different system to create your programs, please test them on Ubuntu Desktop 14 before submitting them for grading.
• The automated test bed will fail if you do not follow the naming instructions, so please be sure that the programs are named correctly.
• Upload the files you modified for this assignment to Canvas when you are ready for me to grade your work. You should upload only the following, using the Firefox web browser in ubuntu:
• It is not necessary to upload your files to icarus for this assignment.
Page !4 of !Here is how you earn points for this assignment:
Files are named correctly and uploaded to Canvas
Compiles without errors or warnings
Correctly displays the appropriate prompt followed by a single space: nanosh:
exit causes nanosh to exit without any errors, crashes or messages
exit with any parameters issues perror() with errno=EINVAL and is ignored
pwd prints the correct current working directory on a single line followed by a
pwd with any parameters issues perror() with errno=EINVAL and is ignored
cd NEWDIR changes the current working directory to NEWDIR
cd without any parameters changes the working directory to $HOME
cd with more than two parameters issues perror() with errno=EINVAL and is
cd to a nonexistent NEWDIR issues perror() and is ignored
Any unknown command is correctly executed with fork() and execvp()
External programs are serialized with waitpid()
Errors from execvp() are reported with a call to perror()
No messages appear on STDOUT except prompts or output from external
commands and all error messages appear on STDERR
Chid processes terminate and do not cause multiple instances of the command loop
Page !5 of !5