7 #######################################################################
8 # sdriver.pl - Shell driver
10 # Copyright (c) 2002, R. Bryant and D. O'Hallaron, All rights reserved.
11 # May not be used, modified, or copied without permission.
13 # The driver runs a student's shell program as a child, sends
14 # commands and signals to the child as directed by a trace file,
15 # and captures and displays the output produced by the child.
19 # The tracefile consists of text lines that are either blank lines,
20 # comment lines, driver commands, or shell commands. Blank lines are
21 # ignored. Comment lines begin with "#" and are echo'd without change
22 # to stdout. Driver commands are intepreted by the driver and are not
23 # passed to the child shell. All other lines are shell commands and
24 # are passed without modification to the shell, which reads them on
25 # stdin. Output produced by the child on stdout/stderr is read by
26 # the parent and printed on its stdout.
29 # TSTP Send a SIGTSTP signal to the child
30 # INT Send a SIGINT signal to the child
31 # QUIT Send a SIGQUIT signal to the child
32 # KILL Send a SIGKILL signal to the child
33 # CLOSE Close Writer (sends EOF signal to child)
34 # WAIT Wait() for child to terminate
35 # SLEEP <n> Sleep for <n> seconds
37 ######################################################################
40 # usage - print help message and terminate
44 printf STDERR
"$_[0]\n";
45 printf STDERR
"Usage: $0 [-hv] -t <trace> -s <shellprog> -a <args>\n";
46 printf STDERR
"Options:\n";
47 printf STDERR
" -h Print this message\n";
48 printf STDERR
" -v Be more verbose\n";
49 printf STDERR
" -t <trace> Trace file\n";
50 printf STDERR
" -s <shell> Shell program to test\n";
51 printf STDERR
" -a <args> Shell arguments\n";
52 printf STDERR
" -g Generate output for autograder\n";
56 # Parse the command line arguments
62 usage
("Missing required -t argument");
65 usage
("Missing required -s argument");
73 # Make sure the input script exists and is readable
75 or die "$0: ERROR: $infile not found\n";
77 or die "$0: ERROR: $infile is not readable\n";
79 # Make sure the shell program exists and is executable
81 or die "$0: ERROR: $shellprog not found\n";
83 or die "$0: ERROR: $shellprog is not executable\n";
86 # Open the input script
88 or die "$0: ERROR: Couldn't open input file $infile: $!\n";
91 # Fork a child, run the shell in it, and connect the parent
92 # and child with a pair of unidirectional pipes:
93 # parent:Writer -> child:stdin
94 # child:stdout -> parent:Reader
96 $pid = open2
(\
*Reader
, \
*Writer
, "$shellprog $shellargs");
99 # The autograder will want to know the child shell's pid
101 print ("pid=$pid\n");
105 # Parent reads a trace file, sends commands to the child shell.
117 elsif ($line =~ /^\s*$/) {
119 print "$0: Ignoring blank line\n";
123 # Send SIGTSTP (ctrl-z)
124 elsif ($line =~ /TSTP/) {
126 print "$0: Sending SIGTSTP signal to process $pid\n";
131 # Send SIGINT (ctrl-c)
132 elsif ($line =~ /INT/) {
134 print "$0: Sending SIGINT signal to process $pid\n";
139 # Send SIGQUIT (whenever we need graceful termination)
140 elsif ($line =~ /QUIT/) {
142 print "$0: Sending SIGQUIT signal to process $pid\n";
148 elsif ($line =~ /KILL/) {
150 print "$0: Sending SIGKILL signal to process $pid\n";
155 # Close pipe (sends EOF notification to child)
156 elsif ($line =~ /CLOSE/) {
158 print "$0: Closing output end of pipe to child $pid\n";
163 # Wait for child to terminate
164 elsif ($line =~ /WAIT/) {
166 print "$0: Waiting for child $pid\n";
170 print "$0: Child $pid reaped\n";
175 elsif ($line =~ /SLEEP (\d+)/) {
177 print "$0: Sleeping $1 secs\n";
185 print "$0: Sending :$line: to child $pid\n";
187 print Writer
"$line\n";
192 # Parent echoes the output produced by the child.
196 print "$0: Reading data from child $pid\n";
198 while ($line = <Reader
>) {
203 # Finally, parent reaps child
207 print "$0: Shell terminated\n";