[SOLVED] C html shell operating system software CS 367 Project 3 Fall 2019: Shell

$25

File Name: C_html_shell_operating_system_software_CS_367_Project_3__Fall_2019:_Shell.zip
File Size: 687.66 KB

5/5 - (1 vote)

CS 367 Project 3Fall 2019: Shell
Due: December 4th, 2019 11:59pm
This is to be an individual effort. No partners.
No late work allowed after 48 hours; each day late automatically uses up one of your tokens.
1. Introduction
For this assignment, you are going to use C to implement a simple shell program called GMSH GMU Shell. Once running, GMSH would be able to acceptexecute commands from user and perform basic job management. This assignment will help you to get familiar with the principles of process management and job control in a Unixlike operating system. Our lectures on processes, signals, and UnixIO as well as Textbook Ch8 in particular 8.4 and 8.5 and 10.3 will provide good references to this project.
2. Project Overview
A typical shell program receives linebyline command input by the user from a terminal. The shell would support a set of builtin commands which will be executed directly by the shell. If the user input is not a builtin command, however, the shell will interpret the input as the name of a program to be executed, along with arguments to be passed to it. In that case, the shell will fork a new child process and execute the program in the context of the child.
A shell program typically also provides job control. Normally, a user command builtin or not is executed as a foreground job, which means the shell will wait for the command to complete before reading the next command. But if the user command ends with an ampersand , the command will be started in the background and the shell will return to the prompt immediately to accept the next command. Some builtin commands are usually provided by the shell for the user to view the list of background jobs or to switch a job between background and foreground.
For this assignment, your shell implementation should be able to perform the following:
Accept a single line of command from user;
Execute a builtin command detailed list of supported commands below;
Load and run the user specified program with the provided arguments;
Perform basic job control;
Support basic file redirection.
We will describe each of them in more details with some examples below.
2.0 Use of the Logging Functions
In order to keep the output format consistent, you must call provided logging functions at the appropriate times to generate the right output from your shell program. The generated output will also be used for grading. The files logging.c and logging.h provide the functions for you to call. Most of the log functions require you to provide a process ID pid and the relevant
1

command line cmd to make the call. We will explain more details and specify how to use them below.
2.1 Parsing User Commands
Once start, the shell would print a prompt and wait for the user to input commands. Each line from the user is considered as a command. Logging Requirements:
You must call logprompt to print out the prompt.
Each command must follow these simplified rules:
Every item in the line must be separated by one or more spaces;
It must start with either a builtin command or a name of the program to be executed with
the full path of that program;
Optionally, it could include any arguments that the user wants to supply;
Optionally, it might specify file redirection options but at most one file for input and at
most one file for output;
Optionally, it might end withto indicate the command should start a background job.
Your shell program needs to be able to parse the input line, identify the command and arguments, check whether any file needs to be prepared, and determine whether this job is a background job. Assumptions: You can assume that all user inputs are valid command lines no need for format checking in your program. You can also assume that the maximum number of characters per command line is 100 and the maximum number of arguments per line is 50.
Remember, fgets will keep the n character in the buffer after reading from the user. If you do not take care of this, you will get command errors with exec. eg. usrbinlsn is not the same as usrbinls when the system tries to find the command.
When parsing the user input, make use of strtok to handle the tokenizing of the inputs for you. All parts of the user input will be separated by a space delimiter. As you are tokenizing the input, think about the order of items that may be present. Your parser will need to handle the options for builtin commands, nonbuiltin commands with and without arguments, and each type of redirection. Remember, a command may use both redirection in and out in the same command!
Examples:
Command Line
Program command
Args
File Redirection
Background Foreground
help
help
NA
NA
Foreground
binsleep 200
binsleep
200
NA
Foreground
binsleep 200
binsleep
200
NA
Background
binls l ..
binls
l ..
NA
Background
binls lls.txt
binls
l
ls.txt for input
Background
binwcls.txtwc.txt
binwc
NA
ls.txt for input
wc.txt for output
Foreground
2

2.2 NonBuiltin Commands
If the user command is not a shell builtin command, it must be interpreted as a program to be loaded in and executed by the shell on behalf of the user. It can be either a foreground or background job. When your shell starts a foreground job, it must wait for the job to complete before showing the prompt to user and accepting the next command. When a background job gets started, however, the shell does not need to wait and can immediately accept the next command.
Assumptions: Your shell does NOT need to support a program that need exclusive access to terminal e.g. vi or that reads from terminal e.g. wc without a file input.
NonBuiltIn Commands that will be used in testing with and without arguments, with and without redirection: binsleep, binls, binpwd
NonBuiltIn Commands that will be used in testing only with redirection in from a file!:binwc eg.binwcfile.txt
Logging Requirements:
For background jobs, you must call logstartbgpid, cmd to report the start of the job.
If the program cannot be loaded and executed, you must call logcommanderrorcmd to
report the error.
Implementation Hints:
You can use fork to create a new child process;
You can use either execl or execv to load a program and execute it in a process.
Even though execl or execv do not normally return, they will return with a 1 value if there are any errors, such as the path or command not being found. Use the man pages for the command you wish to use to see what it will output on errors and think about how to handle them.
Example Runs:
GMSH binls .test l
total 8
rwrr. 1 yzhong itefacstaff 32 Nov 17 23:36 temp.txt rwrr. 1 yzhong itefacstaff 2512 Nov 17 23:37 trivial.txt
Foreground Job
GMSH binls
Background Job
GMSH total 8
rwrr. 1 yzhong itefacstaff 32 Nov 17 23:36 temp.txt rwrr. 1 yzhong itefacstaff 2512 Nov 17 23:37 trivial.txt Background Job 17767:binls .test lTerminated Normally
16952:binls .test l Terminated Normally .test l
17767:binls .test lStarted
2.3 Basic Builtin Shell Commands
Your shell program must support the following builtin commands:
help: when called, your shell should print on terminal a short description of the shell
including a list of builtin commands and their usage. Logging Requirements: o Youmustcallloghelptoprintoutthepredefinedinformation.
quit: when called, your shell should terminate. Logging Requirements: o Youmustcalllogquittoprintoutthepredefinedinformation. o You will then need to exit your shell program.
3

fgbgjobskill: These are described in the Job Control section.
Example Runs:
GMSH help
Welcome to GMSH GMU Shell!
Builtin Commands: fg, bg, jobs, kill, quit, help.
kill SIGNAL PID
fg JOBID
bg JOBID
GMSH quit
Thanks for using GMSH! Goodbye! zeus2:
2.4 Job Control and Relevant Builtin Commands
Your shell might have multiple jobs running concurrently: 0 or 1 foreground job; 0 or more background jobs. Your shell needs to maintain the record for the foreground job if there is any and a list of background jobs that are not terminated. Simple job control tasks include:
On start, every background job gets assigned a nonnegative integer job ID: if there is no other nonterminated background job, it gets job ID 1; otherwise, it takes the next integer that is higher than all existing job IDs.
On start, a foreground job gets a dummy job ID 0. If a foreground job is switched to background, it will be assigned a nonnegative job ID, following the same rules as above.
A job can be switched between background and foreground see details below. Regardless of the switching, once assigned a job ID, a job keeps the same job ID until it is terminated.
You will need to update your record if there is any status change process stopped, terminated, continued, etc or if there is any switching between foreground and background jobs.
Some details need to be included in your record for each job, including the assigned job ID, the process ID, the execution status of the job, and the initial command line that starts the job. You can assume that the execution state is either Running or Stopped,
Some additional builtin commands related to job control must be supported.
jobs: When the user inputs jobs command, your shell should print on terminal the list of
background jobs with the job ID, process ID, running state, and initial command line.
Logging Requirements:
o Youmustfirstcalllogjobnumbernumjobstoreporthowmanybackground
jobs are currently alive not terminated.
o For each of the job, you must then call logjobdetailsjobid, pid, state,
cmd to report the job ID, process ID, execution state either Running or Stopped,
and the original command line that triggered this job.
o If there are multiple jobs, they should be printed in the ascending order of their job
IDs.
Implementation Hints:
o A SIGCHLD will be sent to parent process when there is a status change to a child process stopped, terminated, continued. You can use waitpid to specify which situations you want to monitor. You can also check the status of involved child
4

process using different macros WIFEXITED, WIFSTOPPED, WIFSIGNALED,
WIFCONTINUED, etc.
o You can use sigaction to override the default signal handling and define what
actions to take when a signal arrives. See the Appendix to get more details.
Example Runs:
GMSH binsleep 100
Background Job 1168:binsleep 100Started
GMSH binsleep 10
Background Job 1184:binsleep 10Started
GMSH binsleep 200
Background Job 1189:binsleep 200Started
GMSH jobs
3 Jobs
1: 1168: Running
2: 1184: Running
3: 1189: Running
GMSH Background Job 1184:binsleep 10Terminated Normally GMSH jobs
2 Jobs
1: 1168: Running binsleep 100
3: 1189: Running binsleep 200
GMSH binsleep 400
Background Job 1210:binsleep 400Started
GMSH jobs
3 Jobs
1: 1168: Running
3: 1189: Running
4: 1210: Running
kill SIGNAL PID: when called, your shell should send a signal with number SIGNAL to process with PID.
Logging Requirements:
o Onerror,youmustcalllogkillerrorpid,sigtoreportthefailedattempt.
Implementation Hints:
o Youcanusekilltosendsignalstoaparticularprocess.
Example Runs:
GMSH jobs
1 jobs
1: 30388: Running binsleep 200
GMSH kill 19 30388
GMSH Background Job 30388:binsleep 200Stopped GMSH jobs
1 jobs
1: 30388: Stopped binsleep 200
fg JOBID: when called, your shell should change the specified background job to be foreground and wait until it completes. If no JOBID is specified, switch the background job with the highest job ID to foreground. If the job has been previously stopped, resume its execution. No change should be made if provided JOBID is invalid.
binsleep 100
binsleep 10
binsleep 200
binsleep 100
binsleep 200
binsleep 400
5

Logging Requirements:
o Youmustcalllogjobfgpid,cmdtoreportwhichbackgroundjobhasbeen
switched to be a foreground job.
o If there is no background jobs at all, you must call lognobgerror to report the
issue.
o On failure of locating the specified job ID, you must call
logfgnotfounderrorjobid to report the issue.
o On failure of resuming the specified job, you must call logjobfgfailint pid,
char cmd to report the issue.Implementation Hints:
o Youcanusekilltosendsignalstoaparticularprocess.
Example Runs:
GMSH binsleep 10
Background Job 9746:binsleep 10Started
GMSH jobs
1 Jobs
1: 9746: Running binsleep 10
GMSH fg
Background Job 9746:binsleep 10Moved to Foreground Foreground Job 9746:binsleep 10Terminated Normally GMSH GMSH jobs
0 jobs
GMSH jobs
2 Jobs
1: 10862: Running binsleep 100
2: 11693: Running binsleep 300
GMSH fg 1
Background Job 10862:binsleep 100Moved to Foreground Foreground Job 10862:binsleep 100Terminated Normally GMSH jobs
1 Jobs
2: 11693: Running binsleep 300
bg JOBID: when called, your shell would resume the execution of a background job with the specified JOBID. No change should be made if provided JOBID is invalid or if the specified job is already actively running.
Logging Requirements:
o Youmustcalllogjobbgpid,cmdtoreportcommandbghasbeenappliedto
which background job.
o On failure of locating the specified job ID, you must call
logbgnotfounderrorjobid to report the issue.
o On failure of resuming the specified job, you must call logjobbgfailint pid,
char cmd to report the issue.Implementation Hints:
o Youcanusekilltosendsignalstoaparticularprocess.
6

Example Runs:
GMSH jobs
1 Jobs
1: 20979: Stopped binsleep 200
GMSH bg 1
Command bg applied to 20979:binsleep 200
GMSH Background Job 20979:binsleep 200Continued GMSH jobs
1 Jobs
1: 20979: Running binsleep 200
Assumption: You can assume that builtin commands are always used to specify a foreground job. You can also assume there is no file redirection for builtin shell commands.
2.5 Keyboard Interaction
A number of certain keyboard combinations can trigger signals to be sent to the group of foreground jobs. Note that by default, the signal triggered by those keyboard combinations will be sent to the whole foreground process group, which by default includes both the shell program and its foreground job. Your program must change that default behavior to make sure the signal only affects the foreground job, not the shell program. Implementation Hints:
You can use setpgid to change the group ID of a process. See the Appendix of this
document for more details.
You can use sigaction to change the default response to a particular signal;
Your shell program can use kill to sendforward the received signal to another process.
For this assignment, your only need to support two keyboard combinations:
Ctrlc: A SIGINT2 should be sent to the foreground job to terminate its execution.
Ctrlz: A SIGTSTP20 should be sent to the foreground job to pause its execution and
switch it to be a background job.
Example Runs:
GMSH binsleep 200
CForeground Job 1340:binsleep 200 Terminated by Signal GMSH jobs
0 jobs
GMSH binsleep 200
ZForeground Job 1438:binsleep 200 Stopped
GMSH jobs
1 jobs
1: 1438: Stopped binsleep 200
GMSH
2.6 File Redirection
If the user specifies a file to be used as the input andor output of a program, your shell needs to redirect the standard input andor standard output of that program process to the specified files. Logging Requirements:
On failure of opening the file, you must call logfileopenerrorfilename to report
the issue. Note: If there is a file open error, ignore the file redirection but you should still execute the user command with the normal standard input andor standard output.
7

Implementation Hints:
You can use open to open files;
If a file is created by open, it takes a third argument to set the readingwritingexecuting
permission of that file. To simplify the task, make sure to use 0600 as the third argument of open if needed. It will typically set the file to be readable and writable by the owner of the file only.
You can use dup2 to change the standard inputoutput if the call to open succeeded; o If the open fails eg. File not found, you can skip the dup2 to keep the default.
Example Runs:
GMSH binls .test l
total 12
rwrr. 1 yzhong itefacstaff 1209 Nov 1 19:17 driver.c rwrr. 1 yzhong itefacstaff 5719 Nov 1 11:29 shell.c Foreground Job 2750:binls .test l Terminated Normally GMSH binls .test l ls.txt
Foreground Job 2929:binls .test l ls.txt Terminated Normally GMSH binwc ls.txt
.test is a local folder
3 20128
Foreground Job 3198:binwc ls.txt Terminated Normally
GMSH binwc ls.txt wc.txt
Foreground Job 3728:binwc ls.txt wc.txt Terminated Normally GMSH binwc ls.txt wc.txt
total 12
rwrr. 1 yzhong itefacstaff 1209 Nov 1 19:17 driver.c rwrr. 1 yzhong itefacstaff 5719 Nov 1 11:29 shell.c
3 20128
wc.txt after the first wc command
3 20128 3 20128
There are various signals that you might want to override the default handler and specify what actions to take. You will need to define signal handlers to help implementing the tasks discussed above.
Logging Requirements:
For multiple possible status changes of a child process, you must call the corresponding logging function to report the change. All those logging functions require the process ID pid and the original command line cmd of the involved child process. They are summarized in the table below.
ls.txt
wc.txt after the second wc
command
2.7 Signal Handling
Foreground or Background Job
Status Change
Logging Function to Call
Foreground
RunningTerminated
logjobfgtermpid, cmd
RunningStoppedTerminated by a signal
logjobfgtermsigpid, cmd
RunningStopped also switch to background
logjobfgstoppedpid, cmd
8

Background
RunningTerminated
logjobbgtermpid, cmd
RunningStoppedTerminated by a signal
logjobbgtermsigpid, cmd
RunningStopped
logjobbgstoppedpid, cmd
StoppedRunning
logjobbgcontpid, cmd
Implementation Hints:
Signals that you need to monitor and handle include: SIGCHLD, SIGINT, and SIGTSTP;
You can use sigaction to register those handlers. Note: the textbook introduces the usage of signal, which has been deprecated and replaced by sigaction. Make sure you read
the manual of sigaction and learn how to use it first before coding. Check the Appendix
of this document to get the basic idea and example usage of sigaction.
Its recommended not to use any stdio functions in a signal handler. If you need to print any
debugstatementstothe,usewritewithSTDOUTFILENOdirectly. Youcancheckthe provided logging.c for examples e.g. logjobfgterm.
2.8 Race Conditions
You will start to experience the fun and challenges of concurrent programming in this assignment. In particular, if your design includes a global job list, be alert that race conditions might occur. The typical race is between the shell process updating the list when start or move jobs and signal handler updating the same list when a process changes its status termination, continuation etc. For example, the following sequence is possible if no synchronization is provided:
1. The shellparent starts a new job child process and the newly created child gets to run;
2. Before the parent gets the chance to add the job into the list, the child process terminates
and triggers a SIGCHLD to parent;
3. SIGCHLD handler is executed but does not see the job in list and cannot do anything;
4. After the handler completes, the shell parent resumes normal execution and adds the job
into the list when it is too late!.
One approach that we recommend is to block SIGCHLD signal and other signals that might trigger the updates of the global list before the call to fork and unblock them only after the job has been added into the list. Both blocking and unblocking of signals can be implemented with sigprocmask. Also notice that children inherit the blocked set of their parents, so you must unblock them in the child before calling execl or execve. There might be other similar situations that you need to temporarily block signals to ensure the updates to the global list are well synchronized.
3. Getting Started
First, get the starting code project3handout.tar from the same place you got this document. Once you untar the handout on Zeus using tar xvf project3handout.tar, you will have the following files in the handout directory:
shell.cThis is the only file you will be modifying and submitting. There are stubs in this file for the functions that will be called by the rest of the framework. Feel free to
9

define more functions if you like but put all of your code in this file!
shell.hThis has some basic definitions and includes necessary header files.
logging.cThis has a list of provided logging functions that you need to call at the appropriate times.
logging.hThis has the prototypes of logging functions implemented in logging.c.
sigactionexample.cThis is the example program of sigaction from the Appendix.
Makefileto build the assignment and clean up.
4. SubmittingGrading
Submit this assignment electronically on Blackboard. Note that the only file that gets submitted is shell.c. Make sure to put your name and G as a commented line in the beginning of your program shell.c
You can make multiple submissions; but we will test and grade ONLY the latest version that you submit with the corresponding late penalty, if applicable.
Important: Make sure to submit the correct version of your file on Blackboard! Submitting the correct version late will incur a late penalty; and submitting the correct version 48 hours after the due date will not bring any credit.
Questions about the specification should be directed to the CS 367 Piazza forum. Your grade will be determined as follows:
20 pointscodecomments. Be sure to document your design clearly in your code comments. This score will be based on reading your source code.
80 pointscorrectness. We will be building your code using the shell.c code you submit along with our code.
o If you program does not compile, we cannot grade it.
o If your program compiles but does not run, we cannot grade it.
o We will give partial credit for incomplete programs that compile and run. o We will use a series of programs to test your solution.
10

Appendix: Process Groups
Every process belongs to exactly one process group.
pidt getpgrpvoid; include unistd.h
The getpgrp function shall return the process group ID of the calling process.
When a parent process creates a child process, the child process inherits the same process group from the parent.
int setpgidpidt pid, pidt pgid;include unistd.h
The setpgid function shall set process group ID of the calling process. In particular,
a process can call setpgid0,0 to create a new process group with itself in the group.
References:
http:man7.orglinuxmanpagesman3getpgrp.3p.html
http:man7.orglinuxmanpagesman3setpgid.3p.html
Textbook Section 8.5.2 pp.759
11

Appendix: System call sigaction
The sigaction system call is used to change the action taken by a process on receipt of a specificsignal. Thesigactionfunctionhasthesamebasiceffectassignalbut provides more powerful control. It also has a more reliable behavior across UNIX versions and is recommended to be used to replace signal.
int sigaction int signum, const struct sigaction action, struct sigaction oldactioninclude signal.h
o signum specifies the signal and can be any valid signal except SIGKILL and SIGSTOP
o IfactionisnonNULL,thenewactionforsignalsignumisinstalledfrom action. It could be the name of the signal handler.
o IfoldactionisnonNULL,thepreviousactionissavedinoldaction. Example program:
include stdio.h
include stdlib.h
include unistd.h
include signal.h
void siginthandlerint sigwriteSTDOUTFILENO, SIGINTn, 7; exit0;

int main
struct sigaction new;sigaction struct sigaction old;
new.sahandlersiginthandler; new.saflags0; sigactionSIGINT, new, old;
int i0;
whilei100000
fprintfstderr, dn, i; sleep1; i;

return 0;
References:
https:www.gnu.orgsoftwarelibcmanualhtmlnodeSigactionFunction Example.html
http:man7.orglinuxmanpagesman2sigaction.2.html
signal handler for SIGINT
structures
set the handler
register the handler for SIGINT
this will loop for a while
break loop by Ctrlc to trigger SIGINT
12

Reviews

There are no reviews yet.

Only logged in customers who have purchased this product may leave a review.

Shopping Cart
[SOLVED] C html shell operating system software CS 367 Project 3 Fall 2019: Shell
$25