diff options
| author | _ov4 <ov4@ov4.org> | 2026-08-11 10:25:46 +0000 |
|---|---|---|
| committer | _ov4 <ov4@ov4.org> | 2026-08-11 10:25:46 +0000 |
| commit | 8370ecfb22fcdb3f0a9b76b5fdb0b7000725ebdc (patch) | |
| tree | 09ffb7693cd03ad76059d151471e149fac4ad1e9 /shlab-handout | |
| parent | c13b300279d10e8b0700312b6bff2af872474c46 (diff) | |
1
Diffstat (limited to 'shlab-handout')
| -rw-r--r-- | shlab-handout/Makefile | 100 | ||||
| -rw-r--r-- | shlab-handout/README | 22 | ||||
| -rw-r--r-- | shlab-handout/myint.c | 36 | ||||
| -rw-r--r-- | shlab-handout/myspin.c | 24 | ||||
| -rw-r--r-- | shlab-handout/mysplit.c | 35 | ||||
| -rw-r--r-- | shlab-handout/mystop.c | 36 | ||||
| -rwxr-xr-x | shlab-handout/sdriver.pl | 210 | ||||
| -rw-r--r-- | shlab-handout/trace01.txt | 5 | ||||
| -rw-r--r-- | shlab-handout/trace02.txt | 5 | ||||
| -rw-r--r-- | shlab-handout/trace03.txt | 5 | ||||
| -rw-r--r-- | shlab-handout/trace04.txt | 5 | ||||
| -rw-r--r-- | shlab-handout/trace05.txt | 11 | ||||
| -rw-r--r-- | shlab-handout/trace06.txt | 8 | ||||
| -rw-r--r-- | shlab-handout/trace07.txt | 14 | ||||
| -rw-r--r-- | shlab-handout/trace08.txt | 14 | ||||
| -rw-r--r-- | shlab-handout/trace09.txt | 20 | ||||
| -rw-r--r-- | shlab-handout/trace10.txt | 22 | ||||
| -rw-r--r-- | shlab-handout/trace11.txt | 12 | ||||
| -rw-r--r-- | shlab-handout/trace12.txt | 17 | ||||
| -rw-r--r-- | shlab-handout/trace13.txt | 23 | ||||
| -rw-r--r-- | shlab-handout/trace14.txt | 47 | ||||
| -rw-r--r-- | shlab-handout/trace15.txt | 46 | ||||
| -rw-r--r-- | shlab-handout/trace16.txt | 16 | ||||
| -rw-r--r-- | shlab-handout/tsh.c | 509 | ||||
| -rwxr-xr-x | shlab-handout/tshref | bin | 19278 -> 0 bytes |
25 files changed, 0 insertions, 1242 deletions
diff --git a/shlab-handout/Makefile b/shlab-handout/Makefile deleted file mode 100644 index 5480608..0000000 --- a/shlab-handout/Makefile +++ /dev/null @@ -1,100 +0,0 @@ -# Makefile for the CS:APP Shell Lab - -TEAM = NOBODY -VERSION = 1 -HANDINDIR = /afs/cs/academic/class/15213-f02/L5/handin -DRIVER = ./sdriver.pl -TSH = ./tsh -TSHREF = ./tshref -TSHARGS = "-p" -CC = gcc -CFLAGS = -Wall -O2 -FILES = $(TSH) ./myspin ./mysplit ./mystop ./myint - -all: $(FILES) - -################## -# Handin your work -################## -handin: - cp tsh.c $(HANDINDIR)/$(TEAM)-$(VERSION)-tsh.c - - -################## -# 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) - -# 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) - - -# clean up -clean: - rm -f $(FILES) *.o *~ - - diff --git a/shlab-handout/README b/shlab-handout/README deleted file mode 100644 index a5add38..0000000 --- a/shlab-handout/README +++ /dev/null @@ -1,22 +0,0 @@ -################ -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 <n> and spins for <n> seconds -mysplit.c # Forks a child that spins for <n> seconds -mystop.c # Spins for <n> seconds and sends SIGTSTP to itself -myint.c # Spins for <n> seconds and sends SIGINT to itself - diff --git a/shlab-handout/myint.c b/shlab-handout/myint.c deleted file mode 100644 index ea5bee1..0000000 --- a/shlab-handout/myint.c +++ /dev/null @@ -1,36 +0,0 @@ -/* - * myint.c - Another handy routine for testing your tiny shell - * - * usage: myint <n> - * Sleeps for <n> seconds and sends SIGINT to itself. - * - */ -#include <stdio.h> -#include <unistd.h> -#include <stdlib.h> -#include <sys/types.h> -#include <sys/wait.h> -#include <signal.h> - -int main(int argc, char **argv) -{ - int i, secs; - pid_t pid; - - if (argc != 2) { - fprintf(stderr, "Usage: %s <n>\n", argv[0]); - exit(0); - } - secs = atoi(argv[1]); - - for (i=0; i < secs; i++) - sleep(1); - - pid = getpid(); - - if (kill(pid, SIGINT) < 0) - fprintf(stderr, "kill (int) error"); - - exit(0); - -} diff --git a/shlab-handout/myspin.c b/shlab-handout/myspin.c deleted file mode 100644 index 08c3e0c..0000000 --- a/shlab-handout/myspin.c +++ /dev/null @@ -1,24 +0,0 @@ -/* - * myspin.c - A handy program for testing your tiny shell - * - * usage: myspin <n> - * Sleeps for <n> seconds in 1-second chunks. - * - */ -#include <stdio.h> -#include <unistd.h> -#include <stdlib.h> - -int main(int argc, char **argv) -{ - int i, secs; - - if (argc != 2) { - fprintf(stderr, "Usage: %s <n>\n", argv[0]); - exit(0); - } - secs = atoi(argv[1]); - for (i=0; i < secs; i++) - sleep(1); - exit(0); -} diff --git a/shlab-handout/mysplit.c b/shlab-handout/mysplit.c deleted file mode 100644 index 9ac016e..0000000 --- a/shlab-handout/mysplit.c +++ /dev/null @@ -1,35 +0,0 @@ -/* - * mysplit.c - Another handy routine for testing your tiny shell - * - * usage: mysplit <n> - * Fork a child that spins for <n> seconds in 1-second chunks. - */ -#include <stdio.h> -#include <unistd.h> -#include <stdlib.h> -#include <sys/types.h> -#include <sys/wait.h> -#include <signal.h> - -int main(int argc, char **argv) -{ - int i, secs; - - if (argc != 2) { - fprintf(stderr, "Usage: %s <n>\n", argv[0]); - exit(0); - } - secs = atoi(argv[1]); - - - if (fork() == 0) { /* child */ - for (i=0; i < secs; i++) - sleep(1); - exit(0); - } - - /* parent waits for child to terminate */ - wait(NULL); - - exit(0); -} diff --git a/shlab-handout/mystop.c b/shlab-handout/mystop.c deleted file mode 100644 index 12eee5f..0000000 --- a/shlab-handout/mystop.c +++ /dev/null @@ -1,36 +0,0 @@ -/* - * mystop.c - Another handy routine for testing your tiny shell - * - * usage: mystop <n> - * Sleeps for <n> seconds and sends SIGTSTP to itself. - * - */ -#include <stdio.h> -#include <unistd.h> -#include <stdlib.h> -#include <sys/types.h> -#include <sys/wait.h> -#include <signal.h> - -int main(int argc, char **argv) -{ - int i, secs; - pid_t pid; - - if (argc != 2) { - fprintf(stderr, "Usage: %s <n>\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); - -} diff --git a/shlab-handout/sdriver.pl b/shlab-handout/sdriver.pl deleted file mode 100755 index 852bf3d..0000000 --- a/shlab-handout/sdriver.pl +++ /dev/null @@ -1,210 +0,0 @@ -#!/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 <n> Sleep for <n> seconds -# -###################################################################### - -# -# usage - print help message and terminate -# -sub usage -{ - printf STDERR "$_[0]\n"; - printf STDERR "Usage: $0 [-hv] -t <trace> -s <shellprog> -a <args>\n"; - printf STDERR "Options:\n"; - printf STDERR " -h Print this message\n"; - printf STDERR " -v Be more verbose\n"; - printf STDERR " -t <trace> Trace file\n"; - printf STDERR " -s <shell> Shell program to test\n"; - printf STDERR " -a <args> 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 (<INFILE>) { - $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 = <Reader>) { - print $line; -} -close Reader; - -# Finally, parent reaps child -wait; - -if ($verbose) { - print "$0: Shell terminated\n"; -} - -exit; diff --git a/shlab-handout/trace01.txt b/shlab-handout/trace01.txt deleted file mode 100644 index 9c8561e..0000000 --- a/shlab-handout/trace01.txt +++ /dev/null @@ -1,5 +0,0 @@ -# -# trace01.txt - Properly terminate on EOF. -# -CLOSE -WAIT diff --git a/shlab-handout/trace02.txt b/shlab-handout/trace02.txt deleted file mode 100644 index e97643b..0000000 --- a/shlab-handout/trace02.txt +++ /dev/null @@ -1,5 +0,0 @@ -# -# trace02.txt - Process builtin quit command. -# -quit -WAIT diff --git a/shlab-handout/trace03.txt b/shlab-handout/trace03.txt deleted file mode 100644 index be8869c..0000000 --- a/shlab-handout/trace03.txt +++ /dev/null @@ -1,5 +0,0 @@ -# -# trace03.txt - Run a foreground job. -# -/bin/echo tsh> quit -quit diff --git a/shlab-handout/trace04.txt b/shlab-handout/trace04.txt deleted file mode 100644 index 554df0e..0000000 --- a/shlab-handout/trace04.txt +++ /dev/null @@ -1,5 +0,0 @@ -# -# trace04.txt - Run a background job. -# -/bin/echo -e tsh> ./myspin 1 \046 -./myspin 1 & diff --git a/shlab-handout/trace05.txt b/shlab-handout/trace05.txt deleted file mode 100644 index 03c1876..0000000 --- a/shlab-handout/trace05.txt +++ /dev/null @@ -1,11 +0,0 @@ -# -# trace05.txt - Process jobs builtin command. -# -/bin/echo -e tsh> ./myspin 2 \046 -./myspin 2 & - -/bin/echo -e tsh> ./myspin 3 \046 -./myspin 3 & - -/bin/echo tsh> jobs -jobs diff --git a/shlab-handout/trace06.txt b/shlab-handout/trace06.txt deleted file mode 100644 index bfa3890..0000000 --- a/shlab-handout/trace06.txt +++ /dev/null @@ -1,8 +0,0 @@ -# -# trace06.txt - Forward SIGINT to foreground job. -# -/bin/echo -e tsh> ./myspin 4 -./myspin 4 - -SLEEP 2 -INT diff --git a/shlab-handout/trace07.txt b/shlab-handout/trace07.txt deleted file mode 100644 index 259a285..0000000 --- a/shlab-handout/trace07.txt +++ /dev/null @@ -1,14 +0,0 @@ -# -# trace07.txt - Forward SIGINT only to foreground job. -# -/bin/echo -e tsh> ./myspin 4 \046 -./myspin 4 & - -/bin/echo -e tsh> ./myspin 5 -./myspin 5 - -SLEEP 2 -INT - -/bin/echo tsh> jobs -jobs diff --git a/shlab-handout/trace08.txt b/shlab-handout/trace08.txt deleted file mode 100644 index 49be19f..0000000 --- a/shlab-handout/trace08.txt +++ /dev/null @@ -1,14 +0,0 @@ -# -# trace08.txt - Forward SIGTSTP only to foreground job. -# -/bin/echo -e tsh> ./myspin 4 \046 -./myspin 4 & - -/bin/echo -e tsh> ./myspin 5 -./myspin 5 - -SLEEP 2 -TSTP - -/bin/echo tsh> jobs -jobs diff --git a/shlab-handout/trace09.txt b/shlab-handout/trace09.txt deleted file mode 100644 index 340d998..0000000 --- a/shlab-handout/trace09.txt +++ /dev/null @@ -1,20 +0,0 @@ -# -# trace09.txt - Process bg builtin command -# -/bin/echo -e tsh> ./myspin 4 \046 -./myspin 4 & - -/bin/echo -e tsh> ./myspin 5 -./myspin 5 - -SLEEP 2 -TSTP - -/bin/echo tsh> jobs -jobs - -/bin/echo tsh> bg %2 -bg %2 - -/bin/echo tsh> jobs -jobs diff --git a/shlab-handout/trace10.txt b/shlab-handout/trace10.txt deleted file mode 100644 index e7de996..0000000 --- a/shlab-handout/trace10.txt +++ /dev/null @@ -1,22 +0,0 @@ -# -# trace10.txt - Process fg builtin command. -# -/bin/echo -e tsh> ./myspin 4 \046 -./myspin 4 & - -SLEEP 1 -/bin/echo tsh> fg %1 -fg %1 - -SLEEP 1 -TSTP - -/bin/echo tsh> jobs -jobs - -/bin/echo tsh> fg %1 -fg %1 - -/bin/echo tsh> jobs -jobs - diff --git a/shlab-handout/trace11.txt b/shlab-handout/trace11.txt deleted file mode 100644 index d2f8663..0000000 --- a/shlab-handout/trace11.txt +++ /dev/null @@ -1,12 +0,0 @@ -# -# trace11.txt - Forward SIGINT to every process in foreground process group -# -/bin/echo -e tsh> ./mysplit 4 -./mysplit 4 - -SLEEP 2 -INT - -/bin/echo tsh> /bin/ps a -/bin/ps a - diff --git a/shlab-handout/trace12.txt b/shlab-handout/trace12.txt deleted file mode 100644 index 88455e3..0000000 --- a/shlab-handout/trace12.txt +++ /dev/null @@ -1,17 +0,0 @@ -# -# trace12.txt - Forward SIGTSTP to every process in foreground process group -# -/bin/echo -e tsh> ./mysplit 4 -./mysplit 4 - -SLEEP 2 -TSTP - -/bin/echo tsh> jobs -jobs - -/bin/echo tsh> /bin/ps a -/bin/ps a - - - diff --git a/shlab-handout/trace13.txt b/shlab-handout/trace13.txt deleted file mode 100644 index d734cbc..0000000 --- a/shlab-handout/trace13.txt +++ /dev/null @@ -1,23 +0,0 @@ -# -# trace13.txt - Restart every stopped process in process group -# -/bin/echo -e tsh> ./mysplit 4 -./mysplit 4 - -SLEEP 2 -TSTP - -/bin/echo tsh> jobs -jobs - -/bin/echo tsh> /bin/ps a -/bin/ps a - -/bin/echo tsh> fg %1 -fg %1 - -/bin/echo tsh> /bin/ps a -/bin/ps a - - - diff --git a/shlab-handout/trace14.txt b/shlab-handout/trace14.txt deleted file mode 100644 index 8086580..0000000 --- a/shlab-handout/trace14.txt +++ /dev/null @@ -1,47 +0,0 @@ -# -# trace14.txt - Simple error handling -# -/bin/echo tsh> ./bogus -./bogus - -/bin/echo -e tsh> ./myspin 4 \046 -./myspin 4 & - -/bin/echo tsh> fg -fg - -/bin/echo tsh> bg -bg - -/bin/echo tsh> fg a -fg a - -/bin/echo tsh> bg a -bg a - -/bin/echo tsh> fg 9999999 -fg 9999999 - -/bin/echo tsh> bg 9999999 -bg 9999999 - -/bin/echo tsh> fg %2 -fg %2 - -/bin/echo tsh> fg %1 -fg %1 - -SLEEP 2 -TSTP - -/bin/echo tsh> bg %2 -bg %2 - -/bin/echo tsh> bg %1 -bg %1 - -/bin/echo tsh> jobs -jobs - - - diff --git a/shlab-handout/trace15.txt b/shlab-handout/trace15.txt deleted file mode 100644 index 2cc780e..0000000 --- a/shlab-handout/trace15.txt +++ /dev/null @@ -1,46 +0,0 @@ -# -# trace15.txt - Putting it all together -# - -/bin/echo tsh> ./bogus -./bogus - -/bin/echo tsh> ./myspin 10 -./myspin 10 - -SLEEP 2 -INT - -/bin/echo -e tsh> ./myspin 3 \046 -./myspin 3 & - -/bin/echo -e tsh> ./myspin 4 \046 -./myspin 4 & - -/bin/echo tsh> jobs -jobs - -/bin/echo tsh> fg %1 -fg %1 - -SLEEP 2 -TSTP - -/bin/echo tsh> jobs -jobs - -/bin/echo tsh> bg %3 -bg %3 - -/bin/echo tsh> bg %1 -bg %1 - -/bin/echo tsh> jobs -jobs - -/bin/echo tsh> fg %1 -fg %1 - -/bin/echo tsh> quit -quit - diff --git a/shlab-handout/trace16.txt b/shlab-handout/trace16.txt deleted file mode 100644 index 822ba14..0000000 --- a/shlab-handout/trace16.txt +++ /dev/null @@ -1,16 +0,0 @@ -# -# trace16.txt - Tests whether the shell can handle SIGTSTP and SIGINT -# signals that come from other processes instead of the terminal. -# - -/bin/echo tsh> ./mystop 2 -./mystop 2 - -SLEEP 3 - -/bin/echo tsh> jobs -jobs - -/bin/echo tsh> ./myint 2 -./myint 2 - diff --git a/shlab-handout/tsh.c b/shlab-handout/tsh.c deleted file mode 100644 index 7c2ea8d..0000000 --- a/shlab-handout/tsh.c +++ /dev/null @@ -1,509 +0,0 @@ -/* - * tsh - A tiny shell program with job control - * - * <Put your name and login ID here> - */ -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <string.h> -#include <ctype.h> -#include <signal.h> -#include <sys/types.h> -#include <sys/wait.h> -#include <errno.h> - -/* 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 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 */ - - /* 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 running in - * the foreground, wait for it to terminate and then return. Note: - * each child process must have a unique process group ID so that our - * background children don't receive SIGINT (SIGTSTP) from the kernel - * when we type ctrl-c (ctrl-z) at the keyboard. -*/ -void eval(char *cmdline) -{ - return; -} - -/* - * parseline - Parse the command line and build the argv array. - * - * Characters enclosed in single quotes are treated as a single - * argument. Return true if the user has requested a BG job, false if - * the user has requested a FG job. - */ -int parseline(const char *cmdline, char **argv) -{ - static char array[MAXLINE]; /* holds local copy of command line */ - char *buf = array; /* ptr that traverses command line */ - char *delim; /* points to first space delimiter */ - int argc; /* number of args */ - int bg; /* background job? */ - - strcpy(buf, cmdline); - buf[strlen(buf)-1] = ' '; /* replace trailing '\n' with space */ - while (*buf && (*buf == ' ')) /* ignore leading spaces */ - buf++; - - /* Build the argv list */ - argc = 0; - if (*buf == '\'') { - buf++; - delim = strchr(buf, '\''); - } - else { - delim = strchr(buf, ' '); - } - - while (delim) { - argv[argc++] = buf; - *delim = '\0'; - buf = delim + 1; - while (*buf && (*buf == ' ')) /* ignore spaces */ - buf++; - - if (*buf == '\'') { - buf++; - delim = strchr(buf, '\''); - } - else { - delim = strchr(buf, ' '); - } - } - argv[argc] = NULL; - - if (argc == 0) /* ignore blank line */ - return 1; - - /* should the job run in the background? */ - if ((bg = (*argv[argc-1] == '&')) != 0) { - argv[--argc] = NULL; - } - return bg; -} - -/* - * builtin_cmd - If the user has typed a built-in command then execute - * it immediately. - */ -int builtin_cmd(char **argv) -{ - return 0; /* not a builtin command */ -} - -/* - * do_bgfg - Execute the builtin bg and fg commands - */ -void do_bgfg(char **argv) -{ - return; -} - -/* - * waitfg - Block until process pid is no longer the foreground process - */ -void waitfg(pid_t pid) -{ - return; -} - -/***************** - * Signal handlers - *****************/ - -/* - * sigchld_handler - The kernel sends a SIGCHLD to the shell whenever - * a child job terminates (becomes a zombie), or stops because it - * received a SIGSTOP or SIGTSTP signal. The handler reaps all - * available zombie children, but doesn't wait for any other - * currently running children to terminate. - */ -void sigchld_handler(int sig) -{ - return; -} - -/* - * sigint_handler - The kernel sends a SIGINT to the shell whenver the - * user types ctrl-c at the keyboard. Catch it and send it along - * to the foreground job. - */ -void sigint_handler(int sig) -{ - return; -} - -/* - * sigtstp_handler - The kernel sends a SIGTSTP to the shell whenever - * the user types ctrl-z at the keyboard. Catch it and suspend the - * foreground job by sending it a SIGTSTP. - */ -void sigtstp_handler(int sig) -{ - return; -} - -/********************* - * End signal handlers - *********************/ - -/*********************************************** - * Helper routines that manipulate the job list - **********************************************/ - -/* clearjob - Clear the entries in a job struct */ -void clearjob(struct job_t *job) { - job->pid = 0; - job->jid = 0; - job->state = UNDEF; - job->cmdline[0] = '\0'; -} - -/* initjobs - Initialize the job list */ -void initjobs(struct job_t *jobs) { - int i; - - for (i = 0; i < MAXJOBS; i++) - clearjob(&jobs[i]); -} - -/* maxjid - Returns largest allocated job ID */ -int maxjid(struct job_t *jobs) -{ - int i, max=0; - - for (i = 0; i < MAXJOBS; i++) - if (jobs[i].jid > max) - max = jobs[i].jid; - return max; -} - -/* addjob - Add a job to the job list */ -int addjob(struct job_t *jobs, pid_t pid, int state, char *cmdline) -{ - int i; - - if (pid < 1) - return 0; - - for (i = 0; i < MAXJOBS; i++) { - if (jobs[i].pid == 0) { - jobs[i].pid = pid; - jobs[i].state = state; - jobs[i].jid = nextjid++; - if (nextjid > MAXJOBS) - nextjid = 1; - strcpy(jobs[i].cmdline, cmdline); - if(verbose){ - printf("Added job [%d] %d %s\n", jobs[i].jid, jobs[i].pid, jobs[i].cmdline); - } - return 1; - } - } - printf("Tried to create too many jobs\n"); - return 0; -} - -/* deletejob - Delete a job whose PID=pid from the job list */ -int deletejob(struct job_t *jobs, pid_t pid) -{ - int i; - - if (pid < 1) - return 0; - - for (i = 0; i < MAXJOBS; i++) { - if (jobs[i].pid == pid) { - clearjob(&jobs[i]); - nextjid = maxjid(jobs)+1; - return 1; - } - } - return 0; -} - -/* fgpid - Return PID of current foreground job, 0 if no such job */ -pid_t fgpid(struct job_t *jobs) { - int i; - - for (i = 0; i < MAXJOBS; i++) - if (jobs[i].state == FG) - return jobs[i].pid; - return 0; -} - -/* getjobpid - Find a job (by PID) on the job list */ -struct job_t *getjobpid(struct job_t *jobs, pid_t pid) { - int i; - - if (pid < 1) - return NULL; - for (i = 0; i < MAXJOBS; i++) - if (jobs[i].pid == pid) - return &jobs[i]; - return NULL; -} - -/* getjobjid - Find a job (by JID) on the job list */ -struct job_t *getjobjid(struct job_t *jobs, int jid) -{ - int i; - - if (jid < 1) - return NULL; - for (i = 0; i < MAXJOBS; i++) - if (jobs[i].jid == jid) - return &jobs[i]; - return NULL; -} - -/* pid2jid - Map process ID to job ID */ -int pid2jid(pid_t pid) -{ - int i; - - if (pid < 1) - return 0; - for (i = 0; i < MAXJOBS; i++) - if (jobs[i].pid == pid) { - return jobs[i].jid; - } - return 0; -} - -/* listjobs - Print the job list */ -void listjobs(struct job_t *jobs) -{ - int i; - - for (i = 0; i < MAXJOBS; i++) { - if (jobs[i].pid != 0) { - printf("[%d] (%d) ", jobs[i].jid, jobs[i].pid); - switch (jobs[i].state) { - case BG: - printf("Running "); - break; - case FG: - printf("Foreground "); - break; - case ST: - printf("Stopped "); - break; - default: - printf("listjobs: Internal error: job[%d].state=%d ", - i, jobs[i].state); - } - printf("%s", jobs[i].cmdline); - } - } -} -/****************************** - * end job list helper routines - ******************************/ - - -/*********************** - * Other helper routines - ***********************/ - -/* - * usage - print a help message - */ -void usage(void) -{ - printf("Usage: shell [-hvp]\n"); - printf(" -h print this message\n"); - printf(" -v print additional diagnostic information\n"); - printf(" -p do not emit a command prompt\n"); - exit(1); -} - -/* - * unix_error - unix-style error routine - */ -void unix_error(char *msg) -{ - fprintf(stdout, "%s: %s\n", msg, strerror(errno)); - exit(1); -} - -/* - * app_error - application-style error routine - */ -void app_error(char *msg) -{ - fprintf(stdout, "%s\n", msg); - exit(1); -} - -/* - * Signal - wrapper for the sigaction function - */ -handler_t *Signal(int signum, handler_t *handler) -{ - struct sigaction action, old_action; - - action.sa_handler = handler; - sigemptyset(&action.sa_mask); /* block sigs of type being handled */ - action.sa_flags = SA_RESTART; /* restart syscalls if possible */ - - if (sigaction(signum, &action, &old_action) < 0) - unix_error("Signal error"); - return (old_action.sa_handler); -} - -/* - * sigquit_handler - The driver program can gracefully terminate the - * child shell by sending it a SIGQUIT signal. - */ -void sigquit_handler(int sig) -{ - printf("Terminating after receipt of SIGQUIT signal\n"); - exit(1); -} - - - diff --git a/shlab-handout/tshref b/shlab-handout/tshref Binary files differdeleted file mode 100755 index d7e2108..0000000 --- a/shlab-handout/tshref +++ /dev/null |
