shlab-handout/trace14.txt # # trace14.txt - Restart every stopped process in process group # ./mysplit 4 SLEEP 2 TSTP jobs /bin/ps -o pid,ppid,ruser,stat,args -C mysplit fg %1 /bin/ps -o...

1 answer below ยป
I need help with this assignment


shlab-handout/trace14.txt # # trace14.txt - Restart every stopped process in process group # ./mysplit 4 SLEEP 2 TSTP jobs /bin/ps -o pid,ppid,ruser,stat,args -C mysplit fg %1 /bin/ps -o pid,ppid,ruser,stat,args -C mysplit shlab-handout/sdriver.pl #!/usr/bin/perl #!/usr/local/bin/perl use Getopt::Std; use FileHandle; use IPC::Open2; ####################################################################### # sdriver.pl - Shell driver # # Copyright (c) 2002, R. Bryant and D. O'Hallaron, All rights reserved. # May not be used, modified, or copied without permission. # # The driver runs a student's shell program as a child, sends # commands and signals to the child as directed by a trace file, # and captures and displays the output produced by the child. # # Tracefile format: # # The tracefile consists of text lines that are either blank lines, # comment lines, driver commands, or shell commands. Blank lines are # ignored. Comment lines begin with "#" and are echo'd without change # to stdout. Driver commands are intepreted by the driver and are not # passed to the child shell. All other lines are shell commands and # are passed without modification to the shell, which reads them on # stdin. Output produced by the child on stdout/stderr is read by # the parent and printed on its stdout. # # Driver commands: # TSTP Send a SIGTSTP signal to the child # INT Send a SIGINT signal to the child # QUIT Send a SIGQUIT signal to the child # KILL Send a SIGKILL signal to the child # CLOSE Close Writer (sends EOF signal to child) # WAIT Wait() for child to terminate # SLEEP Sleep for seconds # ###################################################################### # # usage - print help message and terminate # sub usage { printf STDERR "$_[0]\n"; printf STDERR "Usage: $0 [-hv] -t -s -a \n"; printf STDERR "Options:\n"; printf STDERR " -h Print this message\n"; printf STDERR " -v Be more verbose\n"; printf STDERR " -t Trace file\n"; printf STDERR " -s Shell program to test\n"; printf STDERR " -a Shell arguments\n"; printf STDERR " -g Generate output for autograder\n"; die "\n" ; } # Parse the command line arguments getopts('hgvt:s:a:'); if ($opt_h) { usage(); } if (!$opt_t) { usage("Missing required -t argument"); } if (!$opt_s) { usage("Missing required -s argument"); } $verbose = $opt_v; $infile = $opt_t; $shellprog = $opt_s; $shellargs = $opt_a; $grade = $opt_g; # Make sure the input script exists and is readable -e $infile or die "$0: ERROR: $infile not found\n"; -r $infile or die "$0: ERROR: $infile is not readable\n"; # Make sure the shell program exists and is executable -e $shellprog or die "$0: ERROR: $shellprog not found\n"; -x $shellprog or die "$0: ERROR: $shellprog is not executable\n"; # Open the input script open INFILE, $infile or die "$0: ERROR: Couldn't open input file $infile: $!\n"; # # Fork a child, run the shell in it, and connect the parent # and child with a pair of unidirectional pipes: # parent:Writer -> child:stdin # child:stdout -> parent:Reader # $pid = open2(\*Reader, \*Writer, "$shellprog $shellargs"); Writer->autoflush(); # The autograder will want to know the child shell's pid if ($grade) { print ("pid=$pid\n"); } # # Parent reads a trace file, sends commands to the child shell. # while () { $line = $_; chomp($line); # Comment line if ($line =~ /^#/) { print "$line\n"; } # Blank line elsif ($line =~ /^\s*$/) { if ($verbose) { print "$0: Ignoring blank line\n"; } } # Send SIGTSTP (ctrl-z) elsif ($line =~ /TSTP/) { if ($verbose) { print "$0: Sending SIGTSTP signal to process $pid\n"; } kill 'TSTP', $pid; } # Send SIGINT (ctrl-c) elsif ($line =~ /INT/) { if ($verbose) { print "$0: Sending SIGINT signal to process $pid\n"; } kill 'INT', $pid; } # Send SIGQUIT (whenever we need graceful termination) elsif ($line =~ /QUIT/) { if ($verbose) { print "$0: Sending SIGQUIT signal to process $pid\n"; } kill 'QUIT', $pid; } # Send SIGKILL elsif ($line =~ /KILL/) { if ($verbose) { print "$0: Sending SIGKILL signal to process $pid\n"; } kill 'KILL', $pid; } # Close pipe (sends EOF notification to child) elsif ($line =~ /CLOSE/) { if ($verbose) { print "$0: Closing output end of pipe to child $pid\n"; } close Writer; } # Wait for child to terminate elsif ($line =~ /WAIT/) { if ($verbose) { print "$0: Waiting for child $pid\n"; } wait; if ($verbose) { print "$0: Child $pid reaped\n"; } } # Sleep elsif ($line =~ /SLEEP (\d+)/) { if ($verbose) { print "$0: Sleeping $1 secs\n"; } sleep $1; } # Unknown input else { if ($verbose) { print "$0: Sending :$line: to child $pid\n"; } print Writer "$line\n"; } } # # Parent echoes the output produced by the child. # close Writer; if ($verbose) { print "$0: Reading data from child $pid\n"; } while ($line = ) { print $line; } close Reader; # Finally, parent reaps child wait; if ($verbose) { print "$0: Shell terminated\n"; } exit; shlab-handout/README ################ CS:APP Shell Lab ################ Files: Makefile# Compiles your shell program and runs the tests README# This file tsh.c# The shell program that you will write and hand in tshref# The reference shell binary. # The remaining files are used to test your shell sdriver.pl# The trace-driven shell driver trace*.txt# The 15 trace files that control the shell driver tshref.out # Example output of the reference shell on all 15 traces # Little C programs that are called by the trace files myspin.c# Takes argument and spins for seconds mysplit.c# Forks a child that spins for seconds mystop.c # Spins for seconds and sends SIGTSTP to itself myint.c # Spins for seconds and sends SIGINT to itself shlab-handout/trace10.txt # # trace10.txt - Process bg builtin command # ./myspin 4 & ./myspin 5 SLEEP 2 TSTP jobs bg %2 jobs shlab-handout/myspin.c /* * myspin.c - A handy program for testing your tiny shell * * usage: myspin * Sleeps for seconds in 1-second chunks. * */ #include #include #include int main(int argc, char **argv) { int i, secs; if (argc != 2) { fprintf(stderr, "Usage: %s \n", argv[0]); exit(0); } secs = atoi(argv[1]); for (i=0; i < secs; i++) sleep(1); exit(0); } shlab-handout/makefile # makefile for the cs:app shell lab version = 1 handindir = /home/csci2467/handin/$(user)/lab3 driver = ./sdriver.pl tsh = ./tsh tshref = ./tshref tshargs = "-p" cc = gcc cflags = -wall -o2 -ggdb files = $(tsh) ./myspin ./mysplit ./mystop ./myint ./myread all: $(files) tsh: tsh.c fork.o $(cc) $(cflags) -wl,--wrap,fork -o tsh tsh.c fork.o ################## # regression tests ################## # run tests using the student's shell program test01: $(driver) -t trace01.txt -s $(tsh) -a $(tshargs) test02: $(driver) -t trace02.txt -s $(tsh) -a $(tshargs) test03: $(driver) -t trace03.txt -s $(tsh) -a $(tshargs) test04: $(driver) -t trace04.txt -s $(tsh) -a $(tshargs) test05: $(driver) -t trace05.txt -s $(tsh) -a $(tshargs) test06: $(driver) -t trace06.txt -s $(tsh) -a $(tshargs) test07: $(driver) -t trace07.txt -s $(tsh) -a $(tshargs) test08: $(driver) -t trace08.txt -s $(tsh) -a $(tshargs) test09: $(driver) -t trace09.txt -s $(tsh) -a $(tshargs) test10: $(driver) -t trace10.txt -s $(tsh) -a $(tshargs) test11: $(driver) -t trace11.txt -s $(tsh) -a $(tshargs) test12: $(driver) -t trace12.txt -s $(tsh) -a $(tshargs) test13: $(driver) -t trace13.txt -s $(tsh) -a $(tshargs) test14: $(driver) -t trace14.txt -s $(tsh) -a $(tshargs) test15: $(driver) -t trace15.txt -s $(tsh) -a $(tshargs) test16: $(driver) -t trace16.txt -s $(tsh) -a $(tshargs) test17: $(driver) -t trace17.txt -s $(tsh) -a $(tshargs) test18: $(driver) -t trace18.txt -s ./tsh -a $(tshargs) test19: $(driver) -t trace19.txt -s ./tsh -a $(tshargs) test20: $(driver) -t trace20.txt -s ./tsh -a $(tshargs) # run the tests using the reference shell program rtest01: $(driver) -t trace01.txt -s $(tshref) -a $(tshargs) rtest02: $(driver) -t trace02.txt -s $(tshref) -a $(tshargs) rtest03: $(driver) -t trace03.txt -s $(tshref) -a $(tshargs) rtest04: $(driver) -t trace04.txt -s $(tshref) -a $(tshargs) rtest05: $(driver) -t trace05.txt -s $(tshref) -a $(tshargs) rtest06: $(driver) -t trace06.txt -s $(tshref) -a $(tshargs) rtest07: $(driver) -t trace07.txt -s $(tshref) -a $(tshargs) rtest08: $(driver) -t trace08.txt -s $(tshref) -a $(tshargs) rtest09: $(driver) -t trace09.txt -s $(tshref) -a $(tshargs) rtest10: $(driver) -t trace10.txt -s $(tshref) -a $(tshargs) rtest11: $(driver) -t trace11.txt -s $(tshref) -a $(tshargs) rtest12: $(driver) -t trace12.txt -s $(tshref) -a $(tshargs) rtest13: $(driver) -t trace13.txt -s $(tshref) -a $(tshargs) rtest14: $(driver) -t trace14.txt -s $(tshref) -a $(tshargs) rtest15: $(driver) -t trace15.txt -s $(tshref) -a $(tshargs) rtest16: $(driver) -t trace16.txt -s $(tshref) -a $(tshargs) rtest17: $(driver) -t trace17.txt -s $(tshref) -a $(tshargs) rtest18: $(driver) -t trace18.txt -s $(tshref) -a secs;="" i++)="" sleep(1);="" exit(0);="" }="" shlab-handout/makefile="" #="" makefile="" for="" the="" cs:app="" shell="" lab="" version="1" handindir="/home/CSCI2467/handin/$(USER)/lab3" driver="./sdriver.pl" tsh="./tsh" tshref="./tshref" tshargs="-p" cc="gcc" cflags="-Wall" -o2="" -ggdb="" files="$(TSH)" ./myspin="" ./mysplit="" ./mystop="" ./myint="" ./myread="" all:="" $(files)="" tsh:="" tsh.c="" fork.o="" $(cc)="" $(cflags)="" -wl,--wrap,fork="" -o="" tsh="" tsh.c="" fork.o="" ##################="" #="" regression="" tests="" ##################="" #="" run="" tests="" using="" the="" student's="" shell="" program="" test01:="" $(driver)="" -t="" trace01.txt="" -s="" $(tsh)="" -a="" $(tshargs)="" test02:="" $(driver)="" -t="" trace02.txt="" -s="" $(tsh)="" -a="" $(tshargs)="" test03:="" $(driver)="" -t="" trace03.txt="" -s="" $(tsh)="" -a="" $(tshargs)="" test04:="" $(driver)="" -t="" trace04.txt="" -s="" $(tsh)="" -a="" $(tshargs)="" test05:="" $(driver)="" -t="" trace05.txt="" -s="" $(tsh)="" -a="" $(tshargs)="" test06:="" $(driver)="" -t="" trace06.txt="" -s="" $(tsh)="" -a="" $(tshargs)="" test07:="" $(driver)="" -t="" trace07.txt="" -s="" $(tsh)="" -a="" $(tshargs)="" test08:="" $(driver)="" -t="" trace08.txt="" -s="" $(tsh)="" -a="" $(tshargs)="" test09:="" $(driver)="" -t="" trace09.txt="" -s="" $(tsh)="" -a="" $(tshargs)="" test10:="" $(driver)="" -t="" trace10.txt="" -s="" $(tsh)="" -a="" $(tshargs)="" test11:="" $(driver)="" -t="" trace11.txt="" -s="" $(tsh)="" -a="" $(tshargs)="" test12:="" $(driver)="" -t="" trace12.txt="" -s="" $(tsh)="" -a="" $(tshargs)="" test13:="" $(driver)="" -t="" trace13.txt="" -s="" $(tsh)="" -a="" $(tshargs)="" test14:="" $(driver)="" -t="" trace14.txt="" -s="" $(tsh)="" -a="" $(tshargs)="" test15:="" $(driver)="" -t="" trace15.txt="" -s="" $(tsh)="" -a="" $(tshargs)="" test16:="" $(driver)="" -t="" trace16.txt="" -s="" $(tsh)="" -a="" $(tshargs)="" test17:="" $(driver)="" -t="" trace17.txt="" -s="" $(tsh)="" -a="" $(tshargs)="" test18:="" $(driver)="" -t="" trace18.txt="" -s="" ./tsh="" -a="" $(tshargs)="" test19:="" $(driver)="" -t="" trace19.txt="" -s="" ./tsh="" -a="" $(tshargs)="" test20:="" $(driver)="" -t="" trace20.txt="" -s="" ./tsh="" -a="" $(tshargs)="" #="" run="" the="" tests="" using="" the="" reference="" shell="" program="" rtest01:="" $(driver)="" -t="" trace01.txt="" -s="" $(tshref)="" -a="" $(tshargs)="" rtest02:="" $(driver)="" -t="" trace02.txt="" -s="" $(tshref)="" -a="" $(tshargs)="" rtest03:="" $(driver)="" -t="" trace03.txt="" -s="" $(tshref)="" -a="" $(tshargs)="" rtest04:="" $(driver)="" -t="" trace04.txt="" -s="" $(tshref)="" -a="" $(tshargs)="" rtest05:="" $(driver)="" -t="" trace05.txt="" -s="" $(tshref)="" -a="" $(tshargs)="" rtest06:="" $(driver)="" -t="" trace06.txt="" -s="" $(tshref)="" -a="" $(tshargs)="" rtest07:="" $(driver)="" -t="" trace07.txt="" -s="" $(tshref)="" -a="" $(tshargs)="" rtest08:="" $(driver)="" -t="" trace08.txt="" -s="" $(tshref)="" -a="" $(tshargs)="" rtest09:="" $(driver)="" -t="" trace09.txt="" -s="" $(tshref)="" -a="" $(tshargs)="" rtest10:="" $(driver)="" -t="" trace10.txt="" -s="" $(tshref)="" -a="" $(tshargs)="" rtest11:="" $(driver)="" -t="" trace11.txt="" -s="" $(tshref)="" -a="" $(tshargs)="" rtest12:="" $(driver)="" -t="" trace12.txt="" -s="" $(tshref)="" -a="" $(tshargs)="" rtest13:="" $(driver)="" -t="" trace13.txt="" -s="" $(tshref)="" -a="" $(tshargs)="" rtest14:="" $(driver)="" -t="" trace14.txt="" -s="" $(tshref)="" -a="" $(tshargs)="" rtest15:="" $(driver)="" -t="" trace15.txt="" -s="" $(tshref)="" -a="" $(tshargs)="" rtest16:="" $(driver)="" -t="" trace16.txt="" -s="" $(tshref)="" -a="" $(tshargs)="" rtest17:="" $(driver)="" -t="" trace17.txt="" -s="" $(tshref)="" -a="" $(tshargs)="" rtest18:="" $(driver)="" -t="" trace18.txt="" -s="" $(tshref)="">
Answered 1 days AfterNov 07, 2021

Answer To: shlab-handout/trace14.txt # # trace14.txt - Restart every stopped process in process group #...

Shashi Kant answered on Nov 08 2021
108 Votes
shlab-handout/mystop.c
/*
* mystop.c - Another handy routine for testing your tiny shell
*
* usage: mystop
* Sleeps for seconds and sends SIGTSTP to itself.
*
*/
#include
#include
#include
#include
#include
#include
int main(int argc, char **argv)
{
int i, secs;
pid_t pid;
if (argc != 2) {
    fprintf(stderr, "Usage: %s \n", argv[0]);
    exit(0);
}
secs = atoi(argv[1]);
for (i=0; i < secs; i++)
sleep(1);
    
pid = getpid();
if (kill(-pid, SIGTSTP) < 0)
fprintf(stderr, "kill (tstp) error");
exit(0);
}
shlab-handout/trace01.txt
#
# trace01.txt - Process builtin quit command.
#
quit
WAIT
shlab-handout/trace09.txt
#
# trace09.txt - Forward SIGTSTP only to foreground job.
#
./myspin 4 &
./myspin 5
SLEEP 2
TSTP
jobs
shlab-handout/trace20.txt
#
# trace20.txt - I/O redirection, both input and output
#
./myread 40 < myread.c > /dev/null
shlab-handout/trace15.txt
#
# trace15.txt - Simple error handling
#
./bogus
./myspin 4 &
SLEEP 1
fg
bg
fg a
bg a
fg 9999999
bg
9999999
fg %2
fg %1
SLEEP 1
TSTP
bg %2
bg %1
jobs
shlab-handout/trace02.txt
#
# trace02.txt - Run a foreground job several times.
#
/bin/ls
SLEEP 1
/bin/ls
SLEEP 1
/bin/ls
shlab-handout/trace03.txt
#
# trace03.txt - Run a background job.
#
./myspin 1 &
/bin/ls
shlab-handout/checktsh.py
#!/usr/bin/python3
# Autolab autograder for CSCI 2467 (M. Toups / Fall 2018)
import subprocess # to launch tests
import re # regular expressions please
import difflib # to show differences
import signal # to make sure grading script doesn't get stopped by SIGTSTP
import sys
# list of trace files to test on
tracefiles = ["trace01", "trace02", "trace03",
"trace04", "trace05", "trace06",
"trace07", "trace08", "trace09",
"trace10", "trace11", "trace12",
"trace13", "trace14", "trace15",
"trace16", "trace17", "trace18",
"trace19", "trace20"]
grades = {} # use a dict for results
test_max_time = 25 # maximum number of seconds for each test before timeout
signal.signal(signal.SIGTSTP, signal.SIG_IGN) # ignore SIGTSTP (does not affect children, but helps if their buggy code sends us a SIGTSTP)
for trace in tracefiles:
try:
studentoutput = subprocess.check_output(['./sdriver.pl -t ' + str(trace) + ".txt -s ./tsh -a '-p' "], timeout=test_max_time, shell=True)
refoutput = subprocess.check_output(['./sdriver.pl -t ' + str(trace) + ".txt -s ./tshref -a '-p' "], timeout=test_max_time, shell=True)
sout_mod = re.sub("[\(].*?[\)]", "(PID)", studentoutput.decode("utf-8")) # get rid of PIDS
sout_mod = re.sub(r'\s+$', '', sout_mod, flags=re.M) # remove any trailing whitespace
rout_mod = re.sub("[\(].*?[\)]", "(PID)", refoutput.decode("utf-8")) # get rid of PIDS
rout_mod = re.sub(r'\s+$', '', rout_mod, flags=re.M) # remove any trailing whitespace
if trace == "trace12" or trace == "trace13" or trace == "trace14": # for these tests, remove PIDs from ps output
sout_mod = re.sub("(.\d+\s+\d+)\s+(\w.+\s+\w.\s+.*)", r" PID PID \2 ", sout_mod, flags=re.M) # add a dot in case autograder user gets truncated with a +
rout_mod = re.sub("(.\d+\s+\d+)\s+(\w.+\s+\w.\s+.*)", r" PID PID \2 ", rout_mod, flags=re.M)
if trace == "trace15" or trace == "trace16": # ignore trailing period or trailing space
sout_mod = re.sub("\.*\s*$","",sout_mod,flags=re.M)
rout_mod = re.sub("\.*\s*$","",rout_mod,flags=re.M)
if sout_mod.lower() == rout_mod.lower(): # compare them case-insensitively
print(trace + " outputs matched (2 points)") # SUCCESS
grades[trace] = 2
else:
diffobj = difflib.Differ() # make a nice diff-style output for students to see what didn't match
diff = diffobj.compare(sout_mod.splitlines(keepends=True), rout_mod.splitlines(keepends=True))
grades[trace] = 0
print("------------ ERROR: " + trace + " outputs DIFFER (0 points) ------------------------")
sys.stdout.writelines(list(diff))
print("\n------------ end differences for " + trace + " ------------------------------------")
except subprocess.CalledProcessError as e:
grades[trace] = 0
print('Failed test: ' + str(trace))
print(e.output.decode("utf-8"))
except subprocess.TimeoutExpired:
grades[trace] = 0
print('Failed test: ' + str(trace) + ' (Test timed out)')
print("\n\n==== SHELL LAB SCORE SUMMARY ====\n")
for trace in tracefiles:
if grades[trace] == 2:
print("[*PASSED*] (2) " + trace)
else:
print("[ FAILED ] (0) " + trace)
print("\n\n=== SHELL LAB SCORE: " + str(sum(grades.values())) + " ===\n")
shlab-handout/myread.c
/*
* myread.c - A handy program for testing your tiny shell
*
* usage: myread
* Read a maximum of n bytes from standard input.
*
* (Total bytes read will be either the max value n, or
* the number of bytes of input, whichever is lower.)
*
*/
#include
#include
#include
int main(int argc, char **argv)
{
int i, n;
char c;
if (argc != 2) {
    fprintf(stderr, "Usage: %s \n", argv[0]);
    exit(0);
}
n = atoi(argv[1]);
for (i=0; (c=fgetc(stdin))!=EOF && n>0; i++, n--)
    printf(" character read: %c \n", c);
fprintf(stderr, "Read %d bytes from standard input.\n", i);
exit(0);
}
shlab-handout/trace08.txt
#
# trace08.txt - Forward SIGINT only to foreground job.
#
./myspin 4 &
./myspin 5
SLEEP 2
INT
jobs
shlab-handout/trace04.txt
#
# trace04.txt - Process jobs builtin command.
#
./myspin 2 &
./myspin 3 &
jobs
shlab-handout/fork.o
shlab-handout/trace13.txt
#
# trace13.txt - Forward SIGTSTP to every process in foreground process group
#
./mysplit 4
SLEEP 2
TSTP
jobs
/bin/ps -o pid,ppid,ruser,stat,args -C mysplit
shlab-handout/trace11.txt
#
# trace11.txt - Process fg builtin command.
#
./myspin 4 &
SLEEP 1
fg %1
SLEEP 1
TSTP
jobs
fg %1
jobs
shlab-handout/trace17.txt
#
# trace17.txt - Tests whether the shell can handle SIGTSTP and SIGINT
# signals that come from other processes instead of the terminal.
#
./mystop 2
SLEEP 3
jobs
./myint 2
shlab-handout/trace12.txt
#
# trace12.txt - Forward SIGINT to every process in foreground process group
#
./mysplit 4
SLEEP 2
INT
/bin/ps -o pid,ppid,ruser,stat,args -C mysplit
shlab-handout/tsh.c
/*
* tsh - A tiny shell program with job control
*
*
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
/* Misc manifest constants */
#define MAXLINE 1024 /* max line size */
#define MAXARGS 128 /* max args on a command line */
#define MAXJOBS 16 /* max jobs at any point in time */
#define MAXJID 1<<16 /* max job ID */
/* Job states */
#define UNDEF 0 /* undefined */
#define FG 1 /* running in foreground */
#define BG 2 /* running in background */
#define ST 3 /* stopped */
/*
* Jobs states: FG (foreground), BG (background), ST (stopped)
* Job state transitions and enabling actions:
* FG -> ST : ctrl-z
* ST -> FG : fg command
* ST -> BG : bg command
* BG -> FG : fg command
* At most 1 job can be in the FG state.
*/
/* Global variables */
extern char **environ; /* defined in libc */
char prompt[] = "tsh> "; /* command line prompt (DO NOT CHANGE) */
int verbose = 0; /* if true, print additional output */
int nextjid = 1; /* next job ID to allocate */
char sbuf[MAXLINE]; /* for composing sprintf messages */
struct job_t { /* The job struct */
pid_t pid; /* job PID */
int jid; /* job ID [1, 2, ...] */
int state; /* UNDEF, BG, FG, or ST */
char cmdline[MAXLINE]; /* command line */
};
struct job_t jobs[MAXJOBS]; /* The job list */
/* End global variables */
/* Function prototypes */
/* Here are the functions that you will implement */
void eval(char *cmdline);
int builtin_cmd(char **argv);
void do_bgfg(char **argv);
void do_redirect(char **argv);
void waitfg(pid_t pid);
void sigchld_handler(int sig);
void sigtstp_handler(int sig);
void sigint_handler(int sig);
/* Here are helper routines that we've provided for you */
int parseline(const char *cmdline, char **argv);
void sigquit_handler(int sig);
void clearjob(struct job_t *job);
void initjobs(struct job_t *jobs);
int maxjid(struct job_t *jobs);
int addjob(struct job_t *jobs, pid_t pid, int state, char *cmdline);
int deletejob(struct job_t *jobs, pid_t pid);
pid_t fgpid(struct job_t *jobs);
struct job_t *getjobpid(struct job_t *jobs, pid_t pid);
struct job_t *getjobjid(struct job_t *jobs, int jid);
int pid2jid(pid_t pid);
void listjobs(struct job_t *jobs);
void usage(void);
void unix_error(char *msg);
void app_error(char *msg);
typedef void handler_t(int);
handler_t *Signal(int signum, handler_t *handler);
/*
* main - The shell's main routine
*/
int main(int argc, char **argv)
{
char c;
char cmdline[MAXLINE];
int emit_prompt = 1; /* emit prompt (default) */
/* Redirect stderr to stdout (so that driver will get all output
* on the pipe connected to stdout) */
dup2(1, 2);
/* Parse the command line */
while ((c = getopt(argc, argv, "hvp")) != EOF) {
switch (c) {
case 'h': /* print help message */
usage();
     break;
case 'v': /* emit additional diagnostic info */
verbose = 1;
     break;
case 'p': /* don't print a prompt */
emit_prompt = 0; /* handy for automatic testing */
     break;
    default:
usage();
    }
}
/* Install the signal handlers */
/* These are the ones you will need to implement */
Signal(SIGINT, sigint_handler); /* ctrl-c */
Signal(SIGTSTP, sigtstp_handler); /* ctrl-z */
Signal(SIGCHLD, sigchld_handler); /* Terminated or stopped child */
/* Ignoring these signals simplifies reading from stdin/stdout */
Signal(SIGTTIN, SIG_IGN); /* ignore SIGTTIN */
Signal(SIGTTOU, SIG_IGN); /* ignore SIGTTOU */
/* This one provides a clean way to kill the shell */
Signal(SIGQUIT, sigquit_handler);
/* Initialize the job list */
initjobs(jobs);
/* Execute the shell's read/eval loop */
while (1) {
    /* Read command line */
    if (emit_prompt) {
     printf("%s", prompt);
     fflush(stdout);
    }
    if ((fgets(cmdline, MAXLINE, stdin) == NULL) && ferror(stdin))
     app_error("fgets error");
    if (feof(stdin)) { /* End of file (ctrl-d) */
     fflush(stdout);
     exit(0);
    }
    /* Evaluate the command line */
    eval(cmdline);
    fflush(stdout);
    fflush(stdout);
}
exit(0); /* control never reaches here */
}
/*
* eval - Evaluate the command line that the user has just typed in
*
* If the user has requested a built-in command (quit, jobs, bg or fg)
* then execute it immediately. Otherwise, fork a child process and
* run the job in the context of the child. If the job is...
SOLUTION.PDF

Answer To This Question Is Available To Download

Related Questions & Answers

More Questions ยป

Submit New Assignment

Copy and Paste Your Assignment Here