Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
services:
default:
image: gcc:12
init: true
command: tail -f /dev/null
working_dir: /workspace
network_mode: bridge
cpus: '1.0'
mem_limit: 512mb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"instance_id": "cmu_15-213__shell_lab",
"course_id": "cmu_15-213",
"timeout_minutes": 30,
"tags": ["c", "shell", "signals", "process-control", "job-control"],
"artifacts": [
"tsh.c",
"tsh",
"trace*.txt",
"sdriver.pl",
"*.out",
"*.log"
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#!/bin/bash
set -euo pipefail

# Check test files weren't tampered with
if ! sha256sum -c .tests.sha256 > /dev/null 2>&1; then
echo "FAIL: test files were modified"
exit 1
fi

# Build
make clean > /dev/null 2>&1 || true
make all > /dev/null 2>&1

if ! command -v perl > /dev/null 2>&1; then
apt-get update -y > /dev/null 2>&1
apt-get install -y perl > /dev/null 2>&1
fi

if [ ! -x ./tsh ]; then
echo "FAIL: tsh was not built"
exit 1
fi

if [ ! -x ./tshref ]; then
echo "FAIL: tshref missing or not executable"
exit 1
fi

TSHARGS="-p"
pass=1

normalize_output() {
sed -E 's/\([0-9]+\)/(PID)/g'
}

for t in trace{01..16}.txt; do
./sdriver.pl -t "$t" -s ./tshref -a "$TSHARGS" > ".ref_${t}.out"
./sdriver.pl -t "$t" -s ./tsh -a "$TSHARGS" > ".out_${t}.log"
normalize_output < ".ref_${t}.out" > ".ref_${t}.norm"
normalize_output < ".out_${t}.log" > ".out_${t}.norm"
if ! diff -u ".ref_${t}.norm" ".out_${t}.norm" > /dev/null; then
echo "FAIL: $t output mismatch"
pass=0
fi
done

if [ "$pass" -eq 1 ]; then
echo "PASS: All traces match reference output"
exit 0
fi

exit 1
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/bin/bash
set -e

chmod +x sdriver.pl tshref

# Hash test and driver files to detect tampering
sha256sum sdriver.pl trace*.txt myspin.c mysplit.c mystop.c myint.c Makefile tshref > .tests.sha256
17 changes: 17 additions & 0 deletions benchmarks/courselab_bench/data/cmu_15-213/task_shell_lab/sol.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#!/bin/bash
set -e

cat > tsh.c << 'EOF'
/*
* Minimal reference solution wrapper for validation.
* It delegates execution to the provided tshref binary.
*/
#include <unistd.h>
#include <stdio.h>

int main(int argc, char **argv) {
execv("./tshref", argv);
perror("execv");
return 1;
}
EOF
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# 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 *~


Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* 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);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* 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);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* 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);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* 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);

}
Loading
Loading