CS计算机代考程序代写 file system 1

1

1

CSE 2431 LAB 3 SU 21

Due: Sunday, June 27th at 11:30 p.m.

1. Goal: Enhance the shell written for Lab 1.

2. Introduction

This lab assignment is an extension to the Linux/UNIX Shell interface which was built in Lab 1.
You will add a history feature into your Linux/UNIX Shell which will allow users to view and
possibly rerun any one of up to the 5 most recently entered commands. When your program
outputs these commands (when the user utilizes the h or history command feature – see
below) these commands will be numbered starting at 1 (the least recent of the last 5
commands) and will be numbered up to 5 (the most recent of the last 5 commands). If the
user executes the same command twice consecutively, it will appear twice in the history. A
working version of the shell for Lab 1, shellA.c, has been placed on Carmen in the Labs folder
which you can download into a lab3 directory which you create.

We will use a historyBuff array to store the user’s command history (up to the last 5
commands). This historyBuff array should be declared in main, and has a size equal to 5 times
the maximum length of a command, which for this lab we will set to be 50. Therefore, the
historyBuff array will be an array of char of size 250.

Notice that the setup function in the shellA.c source code uses a file system call to read the
command which the user has entered on the command line into the inputBuff array which is
passed to the setup function. You should notice, however, that after setup reads the command
into inputBuff, the command in inputBuff is modified by the setup function, so we cannot use
the inputBuff array to get a copy of the command; we can pass another array to setup, though,
which we will call commandCopy (also declared in main), to store a copy of the command
before it is modified (you have to figure out how to store the copy of the command before
inputBuff gets modified). After the commandCopy array has a copy of the command, and after
the setup function terminates and returns to main, we can use the commandCopy array to
store a copy of the command which the user entered in the historyBuff array (Be sure to pay
close attention to what is said below about the required null byte terminator for strings in C,
which will need to be placed at the end of the command in commandCopy).

One modification to Lab 1: In lab 1, we assumed that the maximum line length for a
command entered by the user would be 40 characters. Here, we increase that to 50 characters.
Therefore, since you need to store the last 5 commands in the history, and each line can be up
to 50 characters (including the null byte termination), you need a historyBuff of 250
characters. You can just declare (in main) an array of char of length 250 called historyBuff, so
the name of this array will be a constant pointer which points to the array. This will allow you

2

2

to access the various sequences of up to 50 characters which correspond to each command in
the history.

IMPORTANT REMINDER: When storing commands, be very sure that there is a null byte at
the end of the command (recall that the null byte is the char ‘\0’)! Recall that C string
operations cannot be depended on to work correctly if a string is not terminated by a null byte
string terminator. You should put this null byte at the end of each command after you copy it
into the commandCopy array in setup; BE SURE TO DO THIS IN THE CODE IN THE setup
FUNCTION; do not try to do it after setup terminates and returns to main! A C string, by
definition, is null byte terminated; C library functions that work on strings ASSUME that any
string has a null byte terminator. Overlooking this important fact will cause your code to
exhibit bugs which are very difficult to find and correct, so make sure you spend the time
necessary to get this right from the beginning, and the lab will be much less stressful!

3. Assignment

A user will be able to list the 5 most recently entered commands when the user types the
command history or its alias/shortcut h. When your shell program outputs the commands in
the list, it should number them from 1) (the least recently executed or oldest command in the
list) to 5) (the most recently executed command in the history list; and the numbers in the list
of commands should be printed as stated above, that is, the number followed by ‘)’ ). Each
command in the list should be printed on a separate line. The h or history command should
not be placed in the history list. With the list of previous commands output with h or
history, the user can run any of those previous 5 commands by entering rnum where ‘num’ is
the number of that command in the history list (and num will always be from 1 to 5, inclusive,
not 0 to 4). So, for example, after entering the command history or h, if the user then, after the
history list is printed, runs the command r3, the 3rd command in the list should be printed out
and run again. Also, the user should be able to run the most recent command again by
entering rr for ‘run most recent,’ which should print out and execute the last command (most
recent command) in the history list. For rnum, you can assume that no spaces will separate
the r and the number and that the number will be followed by ‘\n’ when entered by the user
on the command line. Also, when rr is used to execute the most recent command you may
assume that it is immediately followed by ‘\n’ on the command line. To simplify the code, we
will assume that the user can only enter either rnum or rr immediately after entering history
or h; after entering h/history, the user can execute any number of rr/rnum commands. You
can assume that a user of your shell will comply with these restrictions.

As stated above, any command that is executed in this fashion (that is, using rr or rnum)
should be echoed on the user’s screen and the command should not be placed in the history
buffer again (it is already there). (rnum and rr do not go into the history list; the actual
command that they are used to execute does not go into the history list again either; in
other words, executing a previous command again using rr or rnum does not modify the
history list at all).

3

3

For a better idea of how a similar (BUT NOTE CAREFULLY, NOT IDENTICAL!!!!!!) history
feature actually works in the Linux CSE Environment, execute a few commands in the terminal
window then type history. To execute a command from the history list type !num (for
example, !3, with no space between the ! and the num). To execute the most recent command
type !!. Depending on whether it is set up in your aliases for commands, h may work as well.
Also note that when you type !num or !!, the full command from the history list is output then
executed. If you type history again you can see the commands that were repeated are now in
the updated history list. Our implementation of history does not use !, but rather r. Also, our
implementation of the history feature is not identical to the Linux feature in all ways, so
please do not assume that it is. Trying this in Linux just gives you a sense of how such a
feature works, but in your shell, it should be implemented as described earlier, and not based
on the way it is implemented in Linux.

How to implement the rr/rnum feature: After the setup function is called, and you store a
copy of the user’s command in commandCopy, you can check to see if the command is rr or
rnum (r1, for example). If you determine that it is rr or rnum, you have a copy of the command
that the user wants to execute in the historyBuff array (and you can use this copy to echo the
command, which is supposed to be done for rr/rnum; you can write a function to echo the
command); however, in order to have the forked child execute the command, you need the
command to be parsed into substrings, and to have an args array of char pointers pointing to
the substrings that you can use to invoke execvp. How can the commandCopy be used to get
an args array? Well, the setup function parses commands and produces an args array, but it
does this after reading the command the user entered using a read file system call. We can use
a boolean variable (int in C), which we call rerun, which we will pass to setup. If rerun is 0,
then setup will read the command the user entered on the command line using a read call, but
if rerun is 1, then instead of doing a read system call, setup will use the command we pass it
with commandCopy (which can be copied into inputBuff before setup parses the command, if
rerun is 1). You will need to put code in the setup function to modify it so that it works this
way.

history/h implementation: I recommend that you write a function to store each command
that the user has entered on the command line, up to the last 5, in the historyBuff array. The
function can be called something such as updateHistoryBuff. You can also write a separate
function to print the commands in the historyBuff, something such as printHistoryBuff. You
will need to decide when to call these functions, but having separate functions to do these
things will make your code more modular, and much easier to debug, and you should put this
code in separate functions (that is, do NOT put this code in main or in a function that does
other work).

As stated before, your source code for Part A should be in a source file named shellA.c, which
should have the code you add to the version of shellA.c which you download from the Lab 3
folder on stdlinux. Also, you are permitted to use string operations in the C standard library,
and indeed, you are strongly encouraged to do so (It is always better not to reinvent the
wheel!). You will not be able to do everything with library string operations, but they will help

4

4

with a lot of what you need to do; you’ll need to write some functions to do string work a well,
but it will be easier to use a library function where possible. Always keep in mind, as
mentioned earlier, that library functions for strings in C ASSUME that any string passed as a
parameter is null byte (‘\0’) terminated; be very sure that any string you pass to a library
function has a null byte termination (Actually, if it does not, it is NOT a “string” in C!).

4. Submission

Please put all code for Part A in “shellA.c” (modify the code which you copy from the project
directory); at the beginning of your source file you need to tell the grader your full name (It
should be in a comment on the very first line of the source file).

Submit this file on Carmen by starting a firefox web browser in the stdlinux environment:

$ firefox https://carmen.osu.edu/#

Submit only the source file specified above, and not an executable, or you will not get
credit. Please DO NOT ZIP your source code files before submitting to Carmen.

All necessary code, and #include directives for necessary .h files from the C standard library,
should be in a single C source code file for the lab. To make things easier for the grader(s), you
should compile your code as follows (your Linux prompt may be different from $, but that
does not matter) for each part:

$ gcc shellA.c -o shellA

To run the code, you should use:

$ shellA

Make very sure that your code compiles with no errors or warnings when using these
compilation commands. If your code does not compile when the grader grades your lab, you
will get no credit for the lab. Also make sure that your executable for each part runs without
errors, and that it performs as described above.

To test your code, you can use the following Linux commands (remember that the shell from
lab 1 could run commands in the background or in the foreground):

ls

pwd

date

ls &

pwd &

https://carmen.osu.edu/
https://carmen.osu.edu/
https://carmen.osu.edu/

5

5

history [history list with above commands, numbered, should be printed]

rr [Command 5, that is, pwd &, should be echoed and executed again)

h [history list with above commands, numbered, should be printed]

r2 [Command 2, that is, pwd, should be echoed to the screen and executed;
try other values besides 2 to make sure they work too]

The code and documentation you write and submit must be your own independent, individual
work. If the files do not compile or have runtime errors (such as segfault), no credit will be
given for this lab.

You should test your lab (of course!), so that you know when the grader runs it, it will
perform as described. Test cases which you use should show the last 5 commands that have
been entered – seen by the command numbers displayed when the user types history. The
test cases should also demonstrate the rr and rnum commands.

A late penalty of 25% will be assessed for any lab not submitted by the due date/time shown at the

top of this document, but submitted within 24 hours of the due date and time.

You are welcome to use Piazza to discuss questions/problems you are having with the lab
with the instructor or with other students. Please be sure, however, that you do not post
code, unless you leave your post private (as it will be by default).