Removed submodules

This commit is contained in:
2026-05-31 14:34:00 -04:00
commit 46c36b11da
352 changed files with 14792 additions and 0 deletions
+20
View File
@@ -0,0 +1,20 @@
# Ignore all compiled files regardless of location
**/*.o
# But not the private.o
!tests/private.o
# Ignore executables for this project
ipc
testsuite
# Ignore test outputs
tests/ckstyle
tests/itests.txt
tests/outputs
tests/style.txt
tests/valgrind
tests/utests.txt
**/.nfs*
**/.vscode
+52
View File
@@ -0,0 +1,52 @@
#
# Simple Makefile
# Mike Lam, James Madison University, August 2016
#
# This makefile builds a simple application that contains a main module
# (specified by the EXE variable) and a predefined list of additional modules
# (specified by the MODS variable). If there are any external library
# dependencies (e.g., the math library, "-lm"), list them in the LIBS variable.
# If there are any precompiled object files, list them in the OBJS variable.
#
# By default, this makefile will build the project with debugging symbols and
# without optimization. To change this, edit or remove the "-g" and "-O0"
# options in CFLAGS and LDFLAGS accordingly.
#
# By default, this makefile build the application using the GNU C compiler,
# adhering to the C99 standard with all warnings enabled.
# application-specific settings and run target
EXE=ipc
MODS=pipe.o
OBJS=
LIBS=-lm
default: $(EXE)
test: $(EXE)
make -C tests test
# compiler/linker settings
CC=gcc
#CFLAGS=-g -O0 -Wall -Werror --std=gnu99 -pedantic
CFLAGS=-g -O0 -Wall -Werror --std=gnu99 -pedantic
LDFLAGS=-g -O0 -pthread
# build targets
$(EXE): main.o $(MODS) $(OBJS)
$(CC) $(LDFLAGS) -o $(EXE) $^ $(LIBS)
%.o: %.c
$(CC) -c $(CFLAGS) $<
clean:
rm -f $(EXE) main.o $(MODS)
make -C tests clean
.PHONY: default clean
+1
View File
@@ -0,0 +1 @@
hello
+1
View File
@@ -0,0 +1 @@
goodbye
+1
View File
@@ -0,0 +1 @@
alohomora
Binary file not shown.
+87
View File
@@ -0,0 +1,87 @@
#include <assert.h>
#include <fcntl.h>
#include <getopt.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include "pipe.h"
int cmdline (int, char **, bool *, char **, char **, size_t *);
void
usage (void)
{
printf ("Usage: ipc [options] EXEC ARG\n");
printf (" Send ARG through a pipe to child process that runs EXEC.\n");
printf (" Option is:\n");
printf (" -s Use posix_spawn() instead of fork() and exec().\n");
}
int
main (int argc, char **argv)
{
bool use_spawn = false;
char *exec = NULL;
char *fname = NULL;
size_t lineno = -1;
if (cmdline (argc, argv, &use_spawn, &exec, &fname, &lineno) < 0)
{
usage ();
return EXIT_FAILURE;
}
// Use fork/exec or spawn to run the executable exec
char *sum = NULL;
if (!use_spawn)
sum = get_result (exec, fname);
else
sum = spawn_result (exec, fname);
if (sum == NULL)
return EXIT_FAILURE;
printf ("%s(%s) = '%s'\n", exec, fname, sum);
// If you get an error here, it's because sum is not dynamically
// allocated correctly.
free (sum);
return EXIT_SUCCESS;
}
/* Helper for parsing the command line arguments. Sets spawn,
filename, and lineno as call-by-reference parameters. Return 0
on success, -1 otherwise. */
int
cmdline (int argc, char **argv, bool *spawn, char **exec, char **filename,
size_t *lineno)
{
int option;
while ((option = getopt (argc, argv, "sh")) != -1)
{
switch (option)
{
case 's':
*spawn = true;
break;
case 'h':
return -1;
break;
default:
return -1;
}
}
if (optind + 2 != argc)
return -1;
*exec = argv[optind];
*filename = argv[optind + 1];
return 0;
}
+118
View File
@@ -0,0 +1,118 @@
#include <fcntl.h>
#include <spawn.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <unistd.h>
#include "pipe.h"
/* Creates a child process. If this fails, close the pipe and return -1.
If the child is created, use it to run the executable program on the
filename passed. Send the result back through the pipe. The parent process
should just return the child's PID. Sample call:
int fd[2];
pipe (fd);
pid_t child_pid = create_child (exec, fd, "foo.txt");
*/
pid_t
create_child (char *const exec, int *pipe, char *const filename)
{
char *args[3] = { exec, filename, NULL };
pid_t pid = fork ();
if (pid == 0)
{
close (pipe[0]);
dup2 (pipe[1], STDOUT_FILENO);
close (pipe[1]);
execvp (exec, args);
exit (-1);
}
close (pipe[1]);
return pid;
}
/* Runs the executable program on the input filename. Start by creating a
pipe and calling create_child() to create the child process. If that
fails, return NULL. Otherwise, implement the parent here so that it
reads the result of the process from the pipe and returns the result
without a newline. The returned string must be a dynamically allocated
copy; you can use the constant BUFFER_LENGTH for its size. Be sure to
close the ends of the pipe at appropriate times. Sample call:
char *sum = get_result ("cksum", "data/f1.txt");
// sum is "3015617425 6 data/f1.txt" [without the newline]
*/
char *
get_result (char *const exec, char *const filename)
{
int fd[2];
if (pipe (fd) == -1)
{
return NULL;
}
pid_t pid = create_child (exec, fd, filename);
char *buffer = calloc (BUFFER_LENGTH, sizeof (char));
ssize_t n = read (fd[0], buffer, BUFFER_LENGTH);
buffer[n - 1] = '\0';
close (fd[0]);
waitpid (pid, NULL, 0);
return buffer;
}
/* Re-implementation of the create_child() in pipe.c. Instead of
using the calls to pipe/fork/dup2/exec, combine the latter three
into a call to posix_spawn(). Sample call:
char *sum = spawn_result ("cksum", "data/f1.txt");
// sum is "3015617425 6 data/f1.txt\n" [with the newline]
*/
char *
spawn_result (char *const exec, char *const filename)
{
// Instead of using fork() and exec(), use the posix_spawn functions.
// Note that you will need to create a pipe, initialize a
// posix_spawn_file_actions_t instance, and add close and dup2 actions
// to it so that the child process writes its STDOUT to the pipe.
// After spawning the new process, make sure to call
// posix_spawn_file_actions_destroy() on the actions to prevent
// memory leaks. To avoid looking up the executable in the $PATH,
// you can use posix_spawnp().
// Parent code: read the value back from the pipe into a dynamically
// allocated buffer. Wait for the child to exit, then return the
// buffer. Make sure to close the ends of the pipe in appropriate
// places.
int fd[2];
pipe (fd);
posix_spawn_file_actions_t actions;
posix_spawn_file_actions_init (&actions);
posix_spawn_file_actions_addclose (&actions, fd[0]);
posix_spawn_file_actions_adddup2 (&actions, fd[1], STDOUT_FILENO);
posix_spawn_file_actions_addclose (&actions, fd[1]);
pid_t pid = -1;
char *args[3] = { exec, filename, NULL };
posix_spawnp (&pid, exec, &actions, NULL, args, NULL);
posix_spawn_file_actions_destroy (&actions);
close (fd[1]);
char *buffer = calloc (BUFFER_LENGTH, sizeof (char));
ssize_t n = read (fd[0], buffer, BUFFER_LENGTH);
buffer[n - 1] = '\0';
close (fd[0]);
waitpid (pid, NULL, 0);
return buffer;
}
+12
View File
@@ -0,0 +1,12 @@
#ifndef __pipe_h__
#define __pipe_h__
#include <unistd.h>
#define BUFFER_LENGTH 100
pid_t create_child (char *const, int *, char *const);
char *get_result (char *const, char *const);
char *spawn_result (char *const, char *const);
#endif
+86
View File
@@ -0,0 +1,86 @@
#
# Simple Test Makefile
# Mike Lam, James Madison University, August 2016
#
# This version of the Makefile includes support for building a test suite. The
# recommended framework is Check (http://check.sourceforge.net/). To build and
# run the test suite, execute the "test" target. The test suite must be located
# in a module called "testsuite". The MODS, LIBS, and OBJS variables work as
# they do in the main Makefile.
#
# To change the default build target (which executes when you just type
# "make"), change the right-hand side of the definition of the "default"
# target.
#
# By default, this makefile will build the project with debugging symbols and
# without optimization. To change this, edit or remove the "-g" and "-O0"
# options in CFLAGS and LDFLAGS accordingly.
#
# By default, this makefile build the application using the GNU C compiler,
# adhering to the C99 standard with all warnings enabled.
# application-specific settings and run target
EXE=../ipc
TEST=testsuite
MODS=public.o
OBJS=../pipe.o private.o
LIBS=
UTESTOUT=utests.txt
ITESTOUT=itests.txt
SCHECKOUT=style.txt
default: $(TEST)
$(EXE):
make -C ../
test: utest itest style
@echo "========================================"
utest: $(EXE) $(TEST)
@echo "========================================"
@echo " UNIT TESTS"
@./$(TEST) 2>/dev/null >$(UTESTOUT)
@cat $(UTESTOUT) | sed -n -e '/Checks/,$$p' | sed -e 's/^private.*:[EF]://g'
itest: $(EXE)
@echo "========================================"
@echo " INTEGRATION TESTS"
@./integration.sh | tee $(ITESTOUT)
style: $(EXE)
@echo "========================================"
@echo " CODING STYLE CHECK"
@./style.sh 2>/dev/null >$(SCHECKOUT)
@cat $(SCHECKOUT)
# compiler/linker settings
CC=gcc
CFLAGS=-g -O0 -Wall --std=gnu99 -pedantic
LDFLAGS=-g -O0
CFLAGS=
LIBS+=-lcheck -lm -lpthread
ifeq ($(shell uname -s),Linux)
LIBS+=-lrt -lsubunit
endif
# build targets
$(TEST): $(TEST).o $(MODS) $(OBJS)
$(CC) $(LDFLAGS) -o $(TEST) $^ $(LIBS)
%.o: %.c
$(CC) -c $(CFLAGS) $<
clean:
rm -rf $(TEST) $(TEST).o $(MODS) $(UTESTOUT) $(ITESTOUT) $(SCHECKOUT) outputs valgrind ckstyle
.PHONY: default clean test unittest inttest
+1
View File
@@ -0,0 +1 @@
hello
+1
View File
@@ -0,0 +1 @@
goodbye
+1
View File
@@ -0,0 +1 @@
alohomora
Binary file not shown.
+1
View File
@@ -0,0 +1 @@
85cdeaba8a3d4b24f3471d8c91724de8fc9eb6de
@@ -0,0 +1 @@
e69f8afeb4d967606c11ee01002df44e6c01b910
@@ -0,0 +1 @@
22cdb52c3ef40e84d4213809c7dcd1747efe8ff0
+1
View File
@@ -0,0 +1 @@
3881b07e1676a7fbe53089dfe7b3add8ffed7fb0
@@ -0,0 +1 @@
e69f8afeb4d967606c11ee01002df44e6c01b910
@@ -0,0 +1 @@
e609d97c46fa6bb297cb26adc575edf33978ca5a
+1
View File
@@ -0,0 +1 @@
cksum(../data/f1.txt) = '3015617425 6 ../data/f1.txt'
@@ -0,0 +1 @@
asldkfja(../data/f1.txt) = ''
@@ -0,0 +1 @@
cksum(../data/f4.txt) = ''
+1
View File
@@ -0,0 +1 @@
shasum(../data/f2.txt) = 'e7d9b82b45d5833c9dada13f2379e7b66c823434 ../data/f2.txt'
@@ -0,0 +1 @@
asldkfja(../data/f1.txt) = ''
@@ -0,0 +1 @@
shasum(../data/f5.txt) = ''
+75
View File
@@ -0,0 +1,75 @@
#!/bin/bash
EXE="../ipc"
function run_test {
# parameters
TAG=$1
ARGS=$2
# file paths
OUTPUT=outputs/$TAG.txt
DIFF=outputs/$TAG.diff
EXPECT=expected/$TAG.txt
VALGRND=valgrind/$TAG.txt
# print tag format
PTAG=$(printf '%-30s' "$TAG")
# check for expected text that needs to be fixed
if [ ! -z "$(egrep "<<<<.*>>>>" "$EXPECT")" ] ; then
echo "$PTAG FAIL ($EXPECT not correct)"
return
fi
# compare the file
SHAOUT=$(shasum "$EXPECT" | awk '{print $1}')
SHAEXP=$(cat "expected/.$TAG.sha")
if [ "$SHAOUT" != "$SHAEXP" ] ; then
echo "$PTAG FAIL (expected file is not correct)"
return
fi
# run test and compare output to the expected version
$EXE $ARGS 2>/dev/null >"$OUTPUT"
diff -u "$OUTPUT" "$EXPECT" >"$DIFF"
if [ -s "$DIFF" ]; then
# try alternative solution (if it exists)
EXPECT=expected/$TAG-2.txt
if [ -e "$EXPECT" ]; then
diff -u "$OUTPUT" "$EXPECT" >"$DIFF"
if [ -s "$DIFF" ]; then
echo "$PTAG FAIL (see $DIFF for details)"
else
echo "$PTAG pass"
fi
else
echo "$PTAG FAIL (see $DIFF for details)"
fi
else
echo "$PTAG pass"
fi
# run valgrind
valgrind $EXE $ARGS &>$VALGRND
}
# initialize output folders
mkdir -p outputs
mkdir -p valgrind
rm -f outputs/* valgrind/*
# run individual tests
source itests.include
# check for memory leaks
LEAK=`cat valgrind/*.txt | grep 'definitely lost' | grep -v ' 0 bytes in 0 blocks'`
if [ -z "$LEAK" ]; then
echo "No memory leak found."
else
echo "Memory leak(s) found. See files listed below for details."
grep 'definitely lost' valgrind/*.txt | grep -v ' 0 bytes in 0 blocks' | sed -e 's/:.*$//g' | sed -e 's/^/ - /g'
fi
+11
View File
@@ -0,0 +1,11 @@
# list of integration tests
# format: run_test <TAG> <ARGS>
# <TAG> used as the root for all filenames (i.e., "expected/$TAG.txt")
# <ARGS> command-line arguments to test
run_test INTEG_fork "cksum ../data/f1.txt"
run_test INTEG_fork_no_exec "asldkfja ../data/f1.txt"
run_test INTEG_fork_no_file "cksum ../data/f4.txt"
run_test INTEG_spawn "-s shasum ../data/f2.txt"
run_test INTEG_spawn_no_exec "-s asldkfja ../data/f1.txt"
run_test INTEG_spawn_no_file "-s shasum ../data/f5.txt"
Binary file not shown.
+35
View File
@@ -0,0 +1,35 @@
#include <check.h>
#include <fcntl.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <unistd.h>
#include "../pipe.h"
// Change this to true if you want to inspect the files produced in
// tests/inputs for debugging
#define DEBUG false
START_TEST (UNIT_result)
{
printf ("\n======================================\n");
printf ("UNIT_result\n");
printf ("Gets cksum of data/f1.txt\n");
char *result = get_result ("cksum", "data/f1.txt");
ck_assert_str_eq (result, "3015617425 6 data/f1.txt");
}
END_TEST
void public_tests (Suite *s)
{
TCase *tc_public = tcase_create ("Public");
tcase_add_test (tc_public, UNIT_result);
suite_add_tcase (s, tc_public);
}
+53
View File
@@ -0,0 +1,53 @@
#!/bin/bash
STYLE="gnu"
IGNORE=()
FAIL=0
function comp_file {
SRC=$1
SRC_NAME=$2
# file paths
FORMAT=ckstyle/${SRC_NAME}.$STYLE
DIFF=ckstyle/${SRC_NAME}.diff
# run clang-format and compare results
clang-format --style=$STYLE $source > $FORMAT
diff -u $SRC $FORMAT >$DIFF
PTAG=$(printf '%-30s' "$SRC_NAME")
if [ -s $DIFF ]; then
echo "$PTAG FAIL (see $DIFF for details)"
FAIL=1
else
echo "$PTAG pass"
rm $DIFF
fi
rm $FORMAT
}
mkdir -p ckstyle
rm -f ckstyle/*
for source in $(ls ../*.c ../*.h) ; do
SKIP=0
src=$(basename $source)
for ignore in ${IGNORE[*]} ; do
if [ "$src" = "$ignore" ] ; then
SKIP=1
fi
done
if [ $SKIP = 0 ] ; then
comp_file $source $src
fi
done
if [ $FAIL != 0 ] ; then
echo "Code that does not adhere to GNU standards will not be accepted."
echo "You must fix these files before submission."
else
echo "Code correctly adheres to required style."
fi
+34
View File
@@ -0,0 +1,34 @@
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <assert.h>
#include <time.h>
#include <check.h>
extern void public_tests (Suite *s);
extern void private_tests (Suite *s);
Suite * test_suite (void)
{
Suite *s = suite_create ("Default");
public_tests (s);
private_tests (s);
return s;
}
void run_testsuite ()
{
Suite *s = test_suite ();
SRunner *sr = srunner_create (s);
srunner_run_all (sr, CK_NORMAL);
srunner_free (sr);
}
int main (void)
{
srand((unsigned)time(NULL));
run_testsuite ();
return EXIT_SUCCESS;
}