summaryrefslogtreecommitdiffstats
path: root/src/examples
diff options
context:
space:
mode:
Diffstat (limited to 'src/examples')
-rw-r--r--src/examples/.cvsignore29
-rw-r--r--src/examples/Makefile50
-rw-r--r--src/examples/bubsort.c38
-rw-r--r--src/examples/cat.c34
-rw-r--r--src/examples/child.c22
-rw-r--r--src/examples/cmp.c68
-rw-r--r--src/examples/cp.c55
-rw-r--r--src/examples/create-bad.c32
-rw-r--r--src/examples/dummy.c12
-rw-r--r--src/examples/echo.c14
-rw-r--r--src/examples/halt.c14
-rw-r--r--src/examples/hex-dump.c35
-rw-r--r--src/examples/insult.c369
-rw-r--r--src/examples/lab1test.c107
-rw-r--r--src/examples/lab1test2.c208
-rw-r--r--src/examples/lab2test.c107
-rw-r--r--src/examples/lab2test_beta.c112
-rw-r--r--src/examples/lib/.cvsignore1
-rw-r--r--src/examples/lib/user/.cvsignore1
-rw-r--r--src/examples/lib/user/.dummy0
-rw-r--r--src/examples/lineup.c46
-rw-r--r--src/examples/longrun.c86
-rw-r--r--src/examples/ls.c90
-rw-r--r--src/examples/matmult.c57
-rw-r--r--src/examples/mcat.c45
-rw-r--r--src/examples/mcp.c68
-rw-r--r--src/examples/mkdir.c24
-rw-r--r--src/examples/parent.c41
-rw-r--r--src/examples/pfs.c22
-rw-r--r--src/examples/pfs.h2
-rw-r--r--src/examples/pfs_reader.c48
-rw-r--r--src/examples/pfs_writer.c47
-rw-r--r--src/examples/pwd.c152
-rw-r--r--src/examples/recursor.c34
-rw-r--r--src/examples/rm.c21
-rw-r--r--src/examples/shell.c104
-rw-r--r--src/examples/sumargv.c26
37 files changed, 2221 insertions, 0 deletions
diff --git a/src/examples/.cvsignore b/src/examples/.cvsignore
new file mode 100644
index 0000000..b05754c
--- /dev/null
+++ b/src/examples/.cvsignore
@@ -0,0 +1,29 @@
+cat
+cmp
+cp
+echo
+halt
+hex-dump
+ls
+mcat
+mcp
+mkdir
+pwd
+rm
+shell
+bubsort
+insult
+lineup
+matmult
+recursor
+lab2test
+pfs_writer
+pfs
+sumargv
+longrun
+pfs_reader
+child
+parent
+dummy
+create-bad
+*.d
diff --git a/src/examples/Makefile b/src/examples/Makefile
new file mode 100644
index 0000000..92d9038
--- /dev/null
+++ b/src/examples/Makefile
@@ -0,0 +1,50 @@
+SRCDIR = ..
+
+# Test programs to compile, and a list of sources for each.
+# To add a new test, put its name on the PROGS list
+# and then add a name_SRC line that lists its source files.
+PROGS = cat cmp cp echo halt hex-dump ls mcat mcp mkdir pwd rm shell \
+ bubsort insult lineup matmult recursor \
+ sumargv lab2test lab1test lab1test2 pfs pfs_reader pfs_writer dummy longrun \
+ child parent create-bad
+
+# Added test programs
+sumargv_SRC = sumargv.c
+lab2test_SRC = lab2test.c
+lab1test_SRC = lab1test.c
+lab1test2_SRC = lab1test2.c
+pfs_SRC = pfs.c
+pfs_reader_SRC = pfs_reader.c
+pfs_writer_SRC = pfs_writer.c
+longrun_SRC = longrun.c
+dummy_SRC = dummy.c
+child_SRC = child.c
+parent_SRC = parent.c
+create-bad_SRC = create-bad.c
+
+# Should work from project 2 onward.
+cat_SRC = cat.c
+cmp_SRC = cmp.c
+cp_SRC = cp.c
+echo_SRC = echo.c
+halt_SRC = halt.c
+hex-dump_SRC = hex-dump.c
+insult_SRC = insult.c
+lineup_SRC = lineup.c
+ls_SRC = ls.c
+recursor_SRC = recursor.c
+rm_SRC = rm.c
+
+# Should work in project 3; also in project 4 if VM is included.
+bubsort_SRC = bubsort.c
+matmult_SRC = matmult.c
+mcat_SRC = mcat.c
+mcp_SRC = mcp.c
+
+# Should work in project 4.
+mkdir_SRC = mkdir.c
+pwd_SRC = pwd.c
+shell_SRC = shell.c
+
+include $(SRCDIR)/Make.config
+include $(SRCDIR)/Makefile.userprog
diff --git a/src/examples/bubsort.c b/src/examples/bubsort.c
new file mode 100644
index 0000000..343219e
--- /dev/null
+++ b/src/examples/bubsort.c
@@ -0,0 +1,38 @@
+/* sort.c
+
+ Test program to sort a large number of integers.
+
+ Intention is to stress virtual memory system.
+
+ Ideally, we could read the unsorted array off of the file
+ system, and store the result back to the file system! */
+#include <stdio.h>
+
+/* Size of array to sort. */
+#define SORT_SIZE 128
+
+int
+main (void)
+{
+ /* Array to sort. Static to reduce stack usage. */
+ static int array[SORT_SIZE];
+
+ int i, j, tmp;
+
+ /* First initialize the array in descending order. */
+ for (i = 0; i < SORT_SIZE; i++)
+ array[i] = SORT_SIZE - i - 1;
+
+ /* Then sort in ascending order. */
+ for (i = 0; i < SORT_SIZE - 1; i++)
+ for (j = 0; j < SORT_SIZE - 1 - i; j++)
+ if (array[j] > array[j + 1])
+ {
+ tmp = array[j];
+ array[j] = array[j + 1];
+ array[j + 1] = tmp;
+ }
+
+ printf ("sort exiting with code %d\n", array[0]);
+ return array[0];
+}
diff --git a/src/examples/cat.c b/src/examples/cat.c
new file mode 100644
index 0000000..c8d229d
--- /dev/null
+++ b/src/examples/cat.c
@@ -0,0 +1,34 @@
+/* cat.c
+
+ Prints files specified on command line to the console. */
+
+#include <stdio.h>
+#include <syscall.h>
+
+int
+main (int argc, char *argv[])
+{
+ bool success = true;
+ int i;
+
+ for (i = 1; i < argc; i++)
+ {
+ int fd = open (argv[i]);
+ if (fd < 0)
+ {
+ printf ("%s: open failed\n", argv[i]);
+ success = false;
+ continue;
+ }
+ for (;;)
+ {
+ char buffer[1024];
+ int bytes_read = read (fd, buffer, sizeof buffer);
+ if (bytes_read == 0)
+ break;
+ write (STDOUT_FILENO, buffer, bytes_read);
+ }
+ close (fd);
+ }
+ return success ? EXIT_SUCCESS : EXIT_FAILURE;
+}
diff --git a/src/examples/child.c b/src/examples/child.c
new file mode 100644
index 0000000..0c1648d
--- /dev/null
+++ b/src/examples/child.c
@@ -0,0 +1,22 @@
+/* child.c
+ * See parent.c */
+#include <syscall.h>
+#include <stdio.h>
+
+int main (int argc, char* argv[])
+{
+ int i;
+
+ if (argc != 2)
+ return 0;
+
+ for(i = 0; i < 20000; i++)
+ {
+ int a = (i * i) + (i * i);
+ int b = i;
+ i = a; a = b; i = b;
+ }
+ printf("PASS Lab %s ON Time.\n", argv[1]);
+
+ return 0;
+}
diff --git a/src/examples/cmp.c b/src/examples/cmp.c
new file mode 100644
index 0000000..94b406d
--- /dev/null
+++ b/src/examples/cmp.c
@@ -0,0 +1,68 @@
+/* cat.c
+
+ Compares two files. */
+
+#include <stdio.h>
+#include <syscall.h>
+
+int
+main (int argc, char *argv[])
+{
+ int fd[2];
+
+ if (argc != 3)
+ {
+ printf ("usage: cmp A B\n");
+ return EXIT_FAILURE;
+ }
+
+ /* Open files. */
+ fd[0] = open (argv[1]);
+ if (fd[0] < 0)
+ {
+ printf ("%s: open failed\n", argv[1]);
+ return EXIT_FAILURE;
+ }
+ fd[1] = open (argv[2]);
+ if (fd[1] < 0)
+ {
+ printf ("%s: open failed\n", argv[1]);
+ return EXIT_FAILURE;
+ }
+
+ /* Compare data. */
+ for (;;)
+ {
+ int pos;
+ char buffer[2][1024];
+ int bytes_read[2];
+ int min_read;
+ int i;
+
+ pos = tell (fd[0]);
+ bytes_read[0] = read (fd[0], buffer[0], sizeof buffer[0]);
+ bytes_read[1] = read (fd[1], buffer[1], sizeof buffer[1]);
+ min_read = bytes_read[0] < bytes_read[1] ? bytes_read[0] : bytes_read[1];
+ if (min_read == 0)
+ break;
+
+ for (i = 0; i < min_read; i++)
+ if (buffer[0][i] != buffer[1][i])
+ {
+ printf ("Byte %d is %02hhx ('%c') in %s but %02hhx ('%c') in %s\n",
+ pos + i,
+ buffer[0][i], buffer[0][i], argv[1],
+ buffer[1][i], buffer[1][i], argv[2]);
+ return EXIT_FAILURE;
+ }
+
+ if (min_read < bytes_read[1])
+ printf ("%s is shorter than %s\n", argv[1], argv[2]);
+ else if (min_read < bytes_read[0])
+ printf ("%s is shorter than %s\n", argv[2], argv[1]);
+ }
+
+ printf ("%s and %s are identical\n", argv[1], argv[2]);
+
+ return EXIT_SUCCESS;
+}
diff --git a/src/examples/cp.c b/src/examples/cp.c
new file mode 100644
index 0000000..86a5cd7
--- /dev/null
+++ b/src/examples/cp.c
@@ -0,0 +1,55 @@
+/* cat.c
+
+Copies one file to another. */
+
+#include <stdio.h>
+#include <syscall.h>
+
+int
+main (int argc, char *argv[])
+{
+ int in_fd, out_fd;
+
+ if (argc != 3)
+ {
+ printf ("usage: cp OLD NEW\n");
+ return EXIT_FAILURE;
+ }
+
+ /* Open input file. */
+ in_fd = open (argv[1]);
+ if (in_fd < 0)
+ {
+ printf ("%s: open failed\n", argv[1]);
+ return EXIT_FAILURE;
+ }
+
+ /* Create and open output file. */
+ if (!create (argv[2], filesize (in_fd)))
+ {
+ printf ("%s: create failed\n", argv[2]);
+ return EXIT_FAILURE;
+ }
+ out_fd = open (argv[2]);
+ if (out_fd < 0)
+ {
+ printf ("%s: open failed\n", argv[2]);
+ return EXIT_FAILURE;
+ }
+
+ /* Copy data. */
+ for (;;)
+ {
+ char buffer[1024];
+ int bytes_read = read (in_fd, buffer, sizeof buffer);
+ if (bytes_read == 0)
+ break;
+ if (write (out_fd, buffer, bytes_read) != bytes_read)
+ {
+ printf ("%s: write failed\n", argv[2]);
+ return EXIT_FAILURE;
+ }
+ }
+
+ return EXIT_SUCCESS;
+}
diff --git a/src/examples/create-bad.c b/src/examples/create-bad.c
new file mode 100644
index 0000000..4a9688a
--- /dev/null
+++ b/src/examples/create-bad.c
@@ -0,0 +1,32 @@
+/* The following program should be killed by the kernel because the
+ string sent with create starts at one page (the BSS page) and ends
+ outside of it in a page that is not allocated.
+
+ If user memory accesses are not handled correctly by the kernel,
+ then pintos will crash with a page fault exception.
+
+ Author: Mattias Eriksson
+*/
+
+#include <syscall.h>
+#include <stdio.h>
+#include <string.h>
+
+#define PGS 4096 /* page size */
+#define PMASK 0xfffff000
+
+static char inbss;
+
+int
+main (void)
+{
+ char * bss_page = (char*) ((int)(&inbss) & PMASK);
+ printf("inbss and bss_page: %p, %p\n", &inbss, bss_page);
+ printf("This program should be killed by the kernel.\n");
+
+ memset ( bss_page, 'a', PGS );
+ create (bss_page+PGS-5, 1024);
+ printf("ERROR: this point should not be reached\n");
+
+ exit(0);
+}
diff --git a/src/examples/dummy.c b/src/examples/dummy.c
new file mode 100644
index 0000000..deeca27
--- /dev/null
+++ b/src/examples/dummy.c
@@ -0,0 +1,12 @@
+/* A small dummy process that just uses up a process slot in the long
+ * runtime test */
+
+#include <stdlib.h>
+
+int main(int argc, char* argv[])
+{
+ if (argc != 2)
+ return 0;
+
+ return atoi(argv[1]);
+}
diff --git a/src/examples/echo.c b/src/examples/echo.c
new file mode 100644
index 0000000..1b136f2
--- /dev/null
+++ b/src/examples/echo.c
@@ -0,0 +1,14 @@
+#include <stdio.h>
+#include <syscall.h>
+
+int
+main (int argc, char **argv)
+{
+ int i;
+
+ for (i = 0; i < argc; i++)
+ printf ("%s ", argv[i]);
+ printf ("\n");
+
+ return EXIT_SUCCESS;
+}
diff --git a/src/examples/halt.c b/src/examples/halt.c
new file mode 100644
index 0000000..bad7250
--- /dev/null
+++ b/src/examples/halt.c
@@ -0,0 +1,14 @@
+/* halt.c
+
+ Simple program to test whether running a user program works.
+
+ Just invokes a system call that shuts down the OS. */
+
+#include <syscall.h>
+
+int
+main (void)
+{
+ halt ();
+ /* not reached */
+}
diff --git a/src/examples/hex-dump.c b/src/examples/hex-dump.c
new file mode 100644
index 0000000..ee313f2
--- /dev/null
+++ b/src/examples/hex-dump.c
@@ -0,0 +1,35 @@
+/* hex-dump.c
+
+ Prints files specified on command line to the console in hex. */
+
+#include <stdio.h>
+#include <syscall.h>
+
+int
+main (int argc, char *argv[])
+{
+ bool success = true;
+ int i;
+
+ for (i = 1; i < argc; i++)
+ {
+ int fd = open (argv[i]);
+ if (fd < 0)
+ {
+ printf ("%s: open failed\n", argv[i]);
+ success = false;
+ continue;
+ }
+ for (;;)
+ {
+ char buffer[1024];
+ int pos = tell (fd);
+ int bytes_read = read (fd, buffer, sizeof buffer);
+ if (bytes_read == 0)
+ break;
+ hex_dump (pos, buffer, bytes_read, true);
+ }
+ close (fd);
+ }
+ return success ? EXIT_SUCCESS : EXIT_FAILURE;
+}
diff --git a/src/examples/insult.c b/src/examples/insult.c
new file mode 100644
index 0000000..98c4e6a
--- /dev/null
+++ b/src/examples/insult.c
@@ -0,0 +1,369 @@
+/* Insult.c
+
+ This is a version of the famous CS 107 random sentence
+ generator. I wrote a program that reads a grammar definition
+ file and writes a C file containing that grammar as hard code
+ static C strings. Thus the majority of the code below in
+ machine generated and totally unreadable. The arrays created
+ are specially designed to make generating the sentences as
+ easy as possible.
+
+ Originally by Greg Hutchins, March 1998.
+ Modified by Ben Pfaff for Pintos, Sept 2004. */
+char *start[] =
+ { "You", "1", "5", ".", "May", "13", ".", "With", "the", "19", "of", "18",
+",", "may", "13", "."
+};
+char startLoc[] = { 3, 0, 4, 7, 16 };
+char *adj[] = { "3", "4", "2", ",", "1" };
+char adjLoc[] = { 3, 0, 1, 2, 5 };
+char *adj3[] = { "3", "4" };
+char adj3Loc[] = { 2, 0, 1, 2 };
+char *adj1[] =
+ { "lame", "dried", "up", "par-broiled", "bloated", "half-baked", "spiteful",
+"egotistical", "ungrateful", "stupid", "moronic", "fat", "ugly", "puny", "pitiful",
+"insignificant", "blithering", "repulsive", "worthless", "blundering", "retarded",
+"useless", "obnoxious", "low-budget", "assinine", "neurotic", "subhuman", "crochety",
+"indescribable", "contemptible", "unspeakable", "sick", "lazy", "good-for-nothing",
+"slutty", "mentally-deficient", "creepy", "sloppy", "dismal", "pompous", "pathetic",
+"friendless", "revolting", "slovenly", "cantankerous", "uncultured", "insufferable",
+"gross", "unkempt", "defective", "crumby"
+};
+char adj1Loc[] =
+ { 50, 0, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
+21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42,
+43, 44, 45, 46, 47, 48, 49, 50, 51 };
+char *adj2[] =
+ { "putrefied", "festering", "funky", "moldy", "leprous", "curdled", "fetid",
+"slimy", "crusty", "sweaty", "damp", "deranged", "smelly", "stenchy", "malignant",
+"noxious", "grimy", "reeky", "nasty", "mutilated", "sloppy", "gruesome", "grisly",
+"sloshy", "wormy", "mealy", "spoiled", "contaminated", "rancid", "musty",
+"fly-covered", "moth-eaten", "decaying", "decomposed", "freeze-dried", "defective",
+"petrified", "rotting", "scabrous", "hirsute"
+};
+char adj2Loc[] =
+ { 40, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 };
+char *name[] =
+ { "10", ",", "bad", "excuse", "for", "6", ",", "6", "for", "brains", ",",
+"4", "11", "8", "for", "brains", "offspring", "of", "a", "motherless", "10", "7", "6",
+"7", "4", "11", "8"
+};
+char nameLoc[] = { 7, 0, 1, 6, 10, 16, 21, 23, 27 };
+char *stuff[] =
+ { "shit", "toe", "jam", "filth", "puss", "earwax", "leaf", "clippings",
+"bat", "guano", "mucus", "fungus", "mung", "refuse", "earwax", "spittoon", "spittle",
+"phlegm"
+};
+char stuffLoc[] = { 14, 0, 1, 3, 4, 5, 6, 8, 10, 11, 12, 13, 14, 15, 17, 18 };
+char *noun_and_prep[] =
+ { "bit", "of", "piece", "of", "vat", "of", "lump", "of", "crock", "of",
+"ball", "of", "tub", "of", "load", "of", "bucket", "of", "mound", "of", "glob", "of", "bag",
+"of", "heap", "of", "mountain", "of", "load", "of", "barrel", "of", "sack", "of", "blob", "of",
+"pile", "of", "truckload", "of", "vat", "of"
+};
+char noun_and_prepLoc[] =
+ { 21, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36,
+38, 40, 42 };
+char *organics[] =
+ { "droppings", "mung", "zits", "puckies", "tumors", "cysts", "tumors",
+"livers", "froth", "parts", "scabs", "guts", "entrails", "blubber", "carcuses", "gizards",
+"9"
+};
+char organicsLoc[] =
+ { 17, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17 };
+char *body_parts[] =
+ { "kidneys", "genitals", "buttocks", "earlobes", "innards", "feet"
+};
+char body_partsLoc[] = { 6, 0, 1, 2, 3, 4, 5, 6 };
+char *noun[] =
+ { "pop", "tart", "warthog", "twinkie", "barnacle", "fondue", "pot",
+"cretin", "fuckwad", "moron", "ass", "neanderthal", "nincompoop", "simpleton", "11"
+};
+char nounLoc[] = { 13, 0, 2, 3, 4, 5, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
+char *animal[] =
+ { "donkey", "llama", "dingo", "lizard", "gekko", "lemur", "moose", "camel",
+"goat", "eel"
+};
+char animalLoc[] = { 10, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
+char *good_verb[] =
+ { "love", "cuddle", "fondle", "adore", "smooch", "hug", "caress", "worship",
+"look", "at", "touch"
+};
+char good_verbLoc[] = { 10, 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11 };
+char *curse[] =
+ { "14", "20", "23", "14", "17", "20", "23", "14", "find", "your", "9",
+"suddenly", "delectable", "14", "and", "14", "seek", "a", "battleground", "23"
+};
+char curseLoc[] = { 4, 0, 3, 7, 13, 20 };
+char *afflictors[] =
+ { "15", "21", "15", "21", "15", "21", "15", "21", "a", "22", "Rush",
+"Limbaugh", "the", "hosts", "of", "Hades"
+};
+char afflictorsLoc[] = { 6, 0, 2, 4, 6, 8, 12, 16 };
+char *quantity[] =
+ { "a", "4", "hoard", "of", "a", "4", "pack", "of", "a", "truckload", "of",
+"a", "swarm", "of", "many", "an", "army", "of", "a", "4", "heard", "of", "a", "4",
+"platoon", "of", "a", "4", "and", "4", "group", "of", "16"
+};
+char quantityLoc[] = { 10, 0, 4, 8, 11, 14, 15, 18, 22, 26, 32, 33 };
+char *numbers[] =
+ { "a", "thousand", "three", "million", "ninty-nine", "nine-hundred,",
+"ninty-nine", "forty-two", "a", "gazillion", "sixty-eight", "times", "thirty-three"
+};
+char numbersLoc[] = { 7, 0, 2, 4, 5, 7, 8, 10, 13 };
+char *adv[] =
+ { "viciously", "manicly", "merrily", "happily", ",", "with", "the", "19",
+"of", "18", ",", "gleefully", ",", "with", "much", "ritualistic", "celebration", ",",
+"franticly"
+};
+char advLoc[] = { 8, 0, 1, 2, 3, 4, 11, 12, 18, 19 };
+char *metaphor[] =
+ { "an", "irate", "manticore", "Thor's", "belch", "Alah's", "fist", "16",
+"titans", "a", "particularly", "vicious", "she-bear", "in", "the", "midst", "of", "her",
+"menstrual", "cycle", "a", "pissed-off", "Jabberwock"
+};
+char metaphorLoc[] = { 6, 0, 3, 5, 7, 9, 20, 23 };
+char *force[] = { "force", "fury", "power", "rage" };
+char forceLoc[] = { 4, 0, 1, 2, 3, 4 };
+char *bad_action[] =
+ { "spit", "shimmy", "slobber", "find", "refuge", "find", "shelter", "dance",
+"retch", "vomit", "defecate", "erect", "a", "strip", "mall", "build", "a", "26", "have", "a",
+"religious", "experience", "discharge", "bodily", "waste", "fart", "dance", "drool",
+"lambada", "spill", "16", "rusty", "tacks", "bite", "you", "sneeze", "sing", "16",
+"campfire", "songs", "smite", "you", "16", "times", "construct", "a", "new", "home", "throw",
+"a", "party", "procreate"
+};
+char bad_actionLoc[] =
+ { 25, 0, 1, 2, 3, 5, 7, 8, 9, 10, 11, 15, 18, 22, 25, 26, 27, 28, 29, 33,
+35, 36, 40, 44, 48, 51, 52 };
+char *beasties[] =
+ { "yaks", "22", "maggots", "22", "cockroaches", "stinging", "scorpions",
+"fleas", "22", "weasels", "22", "gnats", "South", "American", "killer", "bees", "spiders",
+"4", "monkeys", "22", "wiener-dogs", "22", "rats", "22", "wolverines", "4", ",", "22",
+"pit-fiends"
+};
+char beastiesLoc[] =
+ { 14, 0, 1, 3, 5, 7, 8, 10, 12, 16, 17, 19, 21, 23, 25, 29 };
+char *condition[] =
+ { "frothing", "manic", "crazed", "plague-ridden", "disease-carrying",
+"biting", "rabid", "blood-thirsty", "ravaging", "slavering"
+};
+char conditionLoc[] = { 10, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
+char *place[] =
+ { "in", "24", "25", "upon", "your", "mother's", "grave", "on", "24", "best",
+"rug", "in", "the", "26", "you", "call", "home", "upon", "your", "heinie"
+};
+char placeLoc[] = { 5, 0, 3, 7, 11, 17, 20 };
+char *relation[] =
+ { "your", "your", "your", "your", "father's", "your", "mother's", "your",
+"grandma's"
+};
+char relationLoc[] = { 6, 0, 1, 2, 3, 5, 7, 9 };
+char *in_something[] =
+ { "entrails", "anal", "cavity", "shoes", "house", "pantry", "general",
+"direction", "pants", "bed"
+};
+char in_somethingLoc[] = { 8, 0, 1, 3, 4, 5, 6, 8, 9, 10 };
+char *bad_place[] =
+ { "rat", "hole", "sewer", "toxic", "dump", "oil", "refinery", "landfill",
+"porto-pottie"
+};
+char bad_placeLoc[] = { 6, 0, 2, 3, 5, 7, 8, 9 };
+char **daGrammar[27];
+char *daGLoc[27];
+
+static void
+init_grammar (void)
+{
+ daGrammar[0] = start;
+ daGLoc[0] = startLoc;
+ daGrammar[1] = adj;
+ daGLoc[1] = adjLoc;
+ daGrammar[2] = adj3;
+ daGLoc[2] = adj3Loc;
+ daGrammar[3] = adj1;
+ daGLoc[3] = adj1Loc;
+ daGrammar[4] = adj2;
+ daGLoc[4] = adj2Loc;
+ daGrammar[5] = name;
+ daGLoc[5] = nameLoc;
+ daGrammar[6] = stuff;
+ daGLoc[6] = stuffLoc;
+ daGrammar[7] = noun_and_prep;
+ daGLoc[7] = noun_and_prepLoc;
+ daGrammar[8] = organics;
+ daGLoc[8] = organicsLoc;
+ daGrammar[9] = body_parts;
+ daGLoc[9] = body_partsLoc;
+ daGrammar[10] = noun;
+ daGLoc[10] = nounLoc;
+ daGrammar[11] = animal;
+ daGLoc[11] = animalLoc;
+ daGrammar[12] = good_verb;
+ daGLoc[12] = good_verbLoc;
+ daGrammar[13] = curse;
+ daGLoc[13] = curseLoc;
+ daGrammar[14] = afflictors;
+ daGLoc[14] = afflictorsLoc;
+ daGrammar[15] = quantity;
+ daGLoc[15] = quantityLoc;
+ daGrammar[16] = numbers;
+ daGLoc[16] = numbersLoc;
+ daGrammar[17] = adv;
+ daGLoc[17] = advLoc;
+ daGrammar[18] = metaphor;
+ daGLoc[18] = metaphorLoc;
+ daGrammar[19] = force;
+ daGLoc[19] = forceLoc;
+ daGrammar[20] = bad_action;
+ daGLoc[20] = bad_actionLoc;
+ daGrammar[21] = beasties;
+ daGLoc[21] = beastiesLoc;
+ daGrammar[22] = condition;
+ daGLoc[22] = conditionLoc;
+ daGrammar[23] = place;
+ daGLoc[23] = placeLoc;
+ daGrammar[24] = relation;
+ daGLoc[24] = relationLoc;
+ daGrammar[25] = in_something;
+ daGLoc[25] = in_somethingLoc;
+ daGrammar[26] = bad_place;
+ daGLoc[26] = bad_placeLoc;
+}
+
+#include <ctype.h>
+#include <debug.h>
+#include <random.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syscall.h>
+
+void expand (int num, char **grammar[], char *location[], int handle);
+
+static void
+usage (int ret_code, const char *message, ...) PRINTF_FORMAT (2, 3);
+
+static void
+usage (int ret_code, const char *message, ...)
+{
+ va_list args;
+
+ if (message != NULL)
+ {
+ va_start (args, message);
+ vprintf (message, args);
+ va_end (args);
+ }
+
+ printf ("\n"
+ "Usage: insult [OPTION]...\n"
+ "Prints random insults to screen.\n\n"
+ " -h: this help message\n"
+ " -s <integer>: set the random seed (default 4951)\n"
+ " -n <integer>: choose number of insults (default 4)\n"
+ " -f <file>: redirect output to <file>\n");
+
+ exit (ret_code);
+}
+
+int
+main (int argc, char *argv[])
+{
+ int sentence_cnt, new_seed, i, file_flag, sent_flag, seed_flag;
+ int handle;
+
+ new_seed = 4951;
+ sentence_cnt = 4;
+ file_flag = 0;
+ seed_flag = 0;
+ sent_flag = 0;
+ handle = STDOUT_FILENO;
+
+ for (i = 1; i < argc; i++)
+ {
+ if (strcmp (argv[1], "-h") == 0)
+ usage (0, NULL);
+ else if (strcmp (argv[i], "-s") == 0)
+ {
+ if (seed_flag++)
+ usage (-1, "Can't have more than one seed");
+ if (++i >= argc)
+ usage (-1, "Missing value for -s");
+ new_seed = atoi (argv[i]);
+ }
+ else if (strcmp (argv[i], "-n") == 0)
+ {
+ if (sent_flag++)
+ usage (-1, "Can't have more than one sentence option");
+ if (++i >= argc)
+ usage (-1, "Missing value for -n");
+ sentence_cnt = atoi (argv[i]);
+ if (sentence_cnt < 1)
+ usage (-1, "Must have at least one sentence");
+ }
+ else if (strcmp (argv[i], "-f") == 0)
+ {
+ if (file_flag++)
+ usage (-1, "Can't have more than one output file");
+ if (++i >= argc)
+ usage (-1, "Missing value for -f");
+
+ /* Because files have fixed length in the basic Pintos
+ file system, the 0 argument means that this option
+ will not be useful until project 4 is
+ implemented. */
+ create (argv[i], 0);
+ handle = open (argv[i]);
+ if (handle < 0)
+ {
+ printf ("%s: open failed\n", argv[i]);
+ return EXIT_FAILURE;
+ }
+ }
+ else
+ usage (-1, "Unrecognized flag");
+ }
+
+ init_grammar ();
+
+ random_init (new_seed);
+ hprintf (handle, "\n");
+
+ for (i = 0; i < sentence_cnt; i++)
+ {
+ hprintf (handle, "\n");
+ expand (0, daGrammar, daGLoc, handle);
+ hprintf (handle, "\n\n");
+ }
+
+ if (file_flag)
+ close (handle);
+
+ return EXIT_SUCCESS;
+}
+
+void
+expand (int num, char **grammar[], char *location[], int handle)
+{
+ char *word;
+ int i, which, listStart, listEnd;
+
+ which = random_ulong () % location[num][0] + 1;
+ listStart = location[num][which];
+ listEnd = location[num][which + 1];
+ for (i = listStart; i < listEnd; i++)
+ {
+ word = grammar[num][i];
+ if (!isdigit (*word))
+ {
+ if (!ispunct (*word))
+ hprintf (handle, " ");
+ hprintf (handle, "%s", word);
+ }
+ else
+ expand (atoi (word), grammar, location, handle);
+ }
+
+}
diff --git a/src/examples/lab1test.c b/src/examples/lab1test.c
new file mode 100644
index 0000000..1b5aa2b
--- /dev/null
+++ b/src/examples/lab1test.c
@@ -0,0 +1,107 @@
+/* I cleaned this file up a bit, but it is still not pretty. -- ME */
+#include <stdio.h>
+#include <string.h>
+#include <syscall.h>
+#include <stdarg.h>
+
+int main(void)
+{
+ char *descr = "This is test program v0.1 that tests your implementation basic system calls\n";
+ char *test1 = "The first test is to create three files.\n";
+ char *test2 = "Now lets write some data to the files. Write some binary data to some files.\n";
+ char *test3 = "Test string that is written to a file.\n";
+ char *test4 = "Test to read back data from files.\n";
+ char *test5 = "Test to read from and write to bad file handles.\n";
+ char *test6 = "Get data from console. Please, write something (10 characters).\n";
+ char *test7 = "Test to open a file that does not exist.\n";
+ char binarydata[10];
+ char sbuf[50];
+ int file[3];
+ int num_bytes_read, i;
+
+ binarydata[0] = 1;
+ binarydata[1] = 2;
+ binarydata[2] = 3;
+ binarydata[3] = 4;
+ binarydata[4] = 5;
+ binarydata[5] = 0;
+ binarydata[6] = 1;
+ binarydata[7] = 2;
+ binarydata[8] = 3;
+ binarydata[9] = 4;
+
+ write(STDOUT_FILENO, descr, strlen(descr));
+ write(STDOUT_FILENO, test1, strlen(test1));
+ if (!create("test0", strlen(test3))) {
+ printf("Could not create test0\n");
+ halt();
+ }
+ if (!create("test1", 1024)){
+ printf("Could not create test1\n");
+ halt();
+ }
+ if (!create("test2", 1024)){
+ printf("Could not create test1\n");
+ halt();
+ }
+
+ for(i = 0; i < 2; i++){
+ snprintf(sbuf, 50, "test%d", i);
+ file[i] = open(sbuf);
+ if(file[i] > 1){
+ }
+ else{
+ printf("Could not open %s\n", sbuf);
+ halt();
+ }
+ }
+
+ write(STDOUT_FILENO, test6, strlen(test6));
+ num_bytes_read = read(STDIN_FILENO, sbuf, 10);
+ if(num_bytes_read != 10){
+ printf("Did not read 10 characters from the console.\n");
+ halt();
+ }
+
+ write(STDOUT_FILENO, test2, strlen(test2));
+ write(file[0], test3, strlen(test3));
+ write(file[1], binarydata, 10);
+
+ write(STDOUT_FILENO, test4, strlen(test4));
+ close(file[0]);
+ file[0] = open("test0");
+ num_bytes_read = read(file[0], sbuf, 50);
+ if(num_bytes_read != (int)strlen(test3)){
+ printf("Could not read back from test0 (%u), %u characters read instead!\n", (unsigned int)strlen(test3), num_bytes_read);
+ halt();
+ }
+
+ num_bytes_read = read(file[1], sbuf, 10);
+ if(num_bytes_read != 10){
+ printf("Could not read back binary data from test1\n");
+ halt();
+ }
+ if(!memcmp(sbuf, binarydata, 10)) {
+ printf("Data read back from test1 does not match what was written\n");
+ halt();
+ }
+ close(file[1]);
+
+ write(STDOUT_FILENO, test5, strlen(test5));
+ write(87, "hej", 3);
+ num_bytes_read = read(1006, sbuf, 3);
+ if(num_bytes_read != -1){
+ printf("You should catch that I tried to read from file 1006\n");
+ }
+
+ write(STDOUT_FILENO, test7, strlen(test7));
+ file[2] = open("fdsfa");
+ if(file[2] > 1){
+ printf(sbuf, "Got file handle when opening non-existing file\n");
+ write(STDOUT_FILENO, sbuf, strlen(sbuf));
+ halt();
+ }
+
+ printf("Test passed\n");
+ halt();
+}
diff --git a/src/examples/lab1test2.c b/src/examples/lab1test2.c
new file mode 100644
index 0000000..4438025
--- /dev/null
+++ b/src/examples/lab1test2.c
@@ -0,0 +1,208 @@
+/*
+ Complete test suite for most system calls implemented in lab 1.
+
+ This program tests the minimum file limit and verifies all
+ returned data.
+
+ Tested requirements:
+ - write must return number of bytes written
+ - create must return whether the file was created
+ - a user program must be able to have 128 files open
+ at the same time
+ - opening a file must return a valid file descriptor
+ - opening a file mulitiple times must return unique
+ file descriptors
+ - reading from a closed file must fail
+ - reading from an invalid file descriptor must fail
+ - attempting to open missing files must fail
+ - read must return number of bytes read
+ - read after write must return written data
+ - reading from console be implemented
+ - exit must terminate the user program
+
+ Untested requirements:
+ - halt must shut down the system
+ - file descriptors must be closed on process exit
+*/
+#include <stdio.h>
+#include <string.h>
+#include <syscall.h>
+#include <stdarg.h>
+
+#define FD_TEST_COUNT 128
+#define READ_SIZE 50
+#define READ_CONSOLE_COUNT 10
+
+#define RED "\x1B[31m"
+#define GRN "\x1B[32m"
+#define YEL "\x1B[33m"
+#define BLU "\x1B[34m"
+#define MAG "\x1B[35m"
+#define CYN "\x1B[36m"
+#define WHT "\x1B[37m"
+#define RESET "\x1B[0m"
+
+#define TITLE(x) printf(WHT x RESET)
+#define ERROR(x, ...) printf(RED "ERR: " x RESET, ##__VA_ARGS__); halt()
+#define SUCCESS(x) printf(GRN x RESET)
+
+int main(void)
+{
+ char *dummyprint = "Hello, world!\n";
+ char *testdata = "sample file content";
+ bool created;
+ int fd;
+ int bytes_written;
+ int bytes_read;
+ char sbuf[READ_SIZE];
+
+
+
+ TITLE("TEST 1: Printing text\n");
+ bytes_written = write(STDOUT_FILENO, dummyprint, strlen(dummyprint));
+ if (bytes_written < 0 || (size_t)bytes_written != strlen(dummyprint))
+ {
+ ERROR("Incorrect number of written bytes returned from SYS_WRITE.\n");
+ }
+ else
+ {
+ SUCCESS("TEST 1: Passed\n");
+ }
+
+
+
+ TITLE("TEST 2: Creating file\n");
+ created = create("test0", strlen(testdata));
+ if (!created)
+ {
+ ERROR("Could not create file \"test0\", does it already exist?\n");
+ }
+
+ created = create("test0", strlen(testdata));
+ if (created)
+ {
+ ERROR("Succeeded in creating already existing file.\n");
+ }
+
+ SUCCESS("TEST 2: Passed\n");
+
+
+
+ TITLE("TEST 3: Opening files\n");
+ int file_descriptors[FD_TEST_COUNT];
+ int i;
+
+ printf("Opening %d files", FD_TEST_COUNT);
+ for (i = 0; i < FD_TEST_COUNT; ++i)
+ {
+ fd = open("test0");
+ if (fd == -1)
+ {
+ printf("\n");
+ ERROR("Failed to open file, iteration %d.\n", i + 1);
+ }
+
+ if (fd == STDIN_FILENO || fd == STDOUT_FILENO)
+ {
+ printf("\n");
+ ERROR("Opened file with invalid file descriptor.\n");
+ }
+
+ int j;
+ for (j = 0; j < i; ++j)
+ {
+ if (file_descriptors[j] == fd)
+ {
+ printf("\n");
+ ERROR("Opened file with reoccuring file descriptor.\n");
+ }
+ }
+
+ file_descriptors[i] = fd;
+ printf(".");
+ }
+
+ printf("\nDone!\n");
+ printf("Closing files");
+
+ for (i = 0; i < FD_TEST_COUNT; ++i)
+ {
+ close(file_descriptors[i]);
+ bytes_read = read(file_descriptors[i], sbuf, READ_SIZE);
+ if (bytes_read != -1)
+ {
+ printf("\n");
+ ERROR("Successfully read from closed file.\n");
+ }
+
+ printf(".");
+ }
+
+ printf("\nDone!\n");
+
+ bytes_read = read(STDOUT_FILENO, sbuf, READ_SIZE);
+ if (bytes_read != -1)
+ {
+ ERROR("Successfully read from missing file descriptor.\n");
+ }
+
+ fd = open("foobar");
+ if (fd != -1)
+ {
+ ERROR("Successfully opened missing file.\n");
+ }
+
+ SUCCESS("TEST 3: Passed\n");
+
+
+
+ TITLE("TEST 4: Writing to file\n");
+ fd = open("test0");
+ bytes_written = write(fd, testdata, strlen(testdata));
+ if (bytes_written < 0 || (size_t)bytes_written != strlen(testdata))
+ {
+ ERROR("Failed to write %d bytes to file, wrote %d.\n", strlen(testdata), bytes_written);
+ }
+ close(fd);
+
+ SUCCESS("TEST 4: Passed\n");
+
+
+
+ TITLE("TEST 5: Reading from file\n");
+ fd = open("test0");
+ bytes_read = read(fd, sbuf, READ_SIZE);
+ if (bytes_read < 0 || (size_t)bytes_read != strlen(testdata))
+ {
+ ERROR("Failed to read %d bytes from file, read %d.\n", strlen(testdata), bytes_read);
+ }
+
+ if (memcmp(sbuf, testdata, strlen(testdata)) != 0)
+ {
+ ERROR("Read content does not match what was written to file.\n");
+ }
+ close(fd);
+
+ SUCCESS("TEST 5: Passed\n");
+
+
+
+ TITLE("TEST 6: Reading from console\n");
+ printf("Type 10 characters: ");
+ bytes_read = read(STDIN_FILENO, sbuf, READ_CONSOLE_COUNT);
+ printf("\n");
+ if (bytes_read != READ_CONSOLE_COUNT)
+ {
+ ERROR("Failed to read %d characters from console, read %d.\n", READ_CONSOLE_COUNT, bytes_read);
+ }
+
+ SUCCESS("TEST 6: Passed\n");
+
+
+
+ TITLE("The test suite should now exit. Since SYS_WAIT is not implemented yet, the program should hang. ");
+ TITLE("If it does, it means that all tests were successful.\n");
+ exit(0);
+
+ ERROR("ERR: Thread did not exit.\n");
+}
diff --git a/src/examples/lab2test.c b/src/examples/lab2test.c
new file mode 100644
index 0000000..1b5aa2b
--- /dev/null
+++ b/src/examples/lab2test.c
@@ -0,0 +1,107 @@
+/* I cleaned this file up a bit, but it is still not pretty. -- ME */
+#include <stdio.h>
+#include <string.h>
+#include <syscall.h>
+#include <stdarg.h>
+
+int main(void)
+{
+ char *descr = "This is test program v0.1 that tests your implementation basic system calls\n";
+ char *test1 = "The first test is to create three files.\n";
+ char *test2 = "Now lets write some data to the files. Write some binary data to some files.\n";
+ char *test3 = "Test string that is written to a file.\n";
+ char *test4 = "Test to read back data from files.\n";
+ char *test5 = "Test to read from and write to bad file handles.\n";
+ char *test6 = "Get data from console. Please, write something (10 characters).\n";
+ char *test7 = "Test to open a file that does not exist.\n";
+ char binarydata[10];
+ char sbuf[50];
+ int file[3];
+ int num_bytes_read, i;
+
+ binarydata[0] = 1;
+ binarydata[1] = 2;
+ binarydata[2] = 3;
+ binarydata[3] = 4;
+ binarydata[4] = 5;
+ binarydata[5] = 0;
+ binarydata[6] = 1;
+ binarydata[7] = 2;
+ binarydata[8] = 3;
+ binarydata[9] = 4;
+
+ write(STDOUT_FILENO, descr, strlen(descr));
+ write(STDOUT_FILENO, test1, strlen(test1));
+ if (!create("test0", strlen(test3))) {
+ printf("Could not create test0\n");
+ halt();
+ }
+ if (!create("test1", 1024)){
+ printf("Could not create test1\n");
+ halt();
+ }
+ if (!create("test2", 1024)){
+ printf("Could not create test1\n");
+ halt();
+ }
+
+ for(i = 0; i < 2; i++){
+ snprintf(sbuf, 50, "test%d", i);
+ file[i] = open(sbuf);
+ if(file[i] > 1){
+ }
+ else{
+ printf("Could not open %s\n", sbuf);
+ halt();
+ }
+ }
+
+ write(STDOUT_FILENO, test6, strlen(test6));
+ num_bytes_read = read(STDIN_FILENO, sbuf, 10);
+ if(num_bytes_read != 10){
+ printf("Did not read 10 characters from the console.\n");
+ halt();
+ }
+
+ write(STDOUT_FILENO, test2, strlen(test2));
+ write(file[0], test3, strlen(test3));
+ write(file[1], binarydata, 10);
+
+ write(STDOUT_FILENO, test4, strlen(test4));
+ close(file[0]);
+ file[0] = open("test0");
+ num_bytes_read = read(file[0], sbuf, 50);
+ if(num_bytes_read != (int)strlen(test3)){
+ printf("Could not read back from test0 (%u), %u characters read instead!\n", (unsigned int)strlen(test3), num_bytes_read);
+ halt();
+ }
+
+ num_bytes_read = read(file[1], sbuf, 10);
+ if(num_bytes_read != 10){
+ printf("Could not read back binary data from test1\n");
+ halt();
+ }
+ if(!memcmp(sbuf, binarydata, 10)) {
+ printf("Data read back from test1 does not match what was written\n");
+ halt();
+ }
+ close(file[1]);
+
+ write(STDOUT_FILENO, test5, strlen(test5));
+ write(87, "hej", 3);
+ num_bytes_read = read(1006, sbuf, 3);
+ if(num_bytes_read != -1){
+ printf("You should catch that I tried to read from file 1006\n");
+ }
+
+ write(STDOUT_FILENO, test7, strlen(test7));
+ file[2] = open("fdsfa");
+ if(file[2] > 1){
+ printf(sbuf, "Got file handle when opening non-existing file\n");
+ write(STDOUT_FILENO, sbuf, strlen(sbuf));
+ halt();
+ }
+
+ printf("Test passed\n");
+ halt();
+}
diff --git a/src/examples/lab2test_beta.c b/src/examples/lab2test_beta.c
new file mode 100644
index 0000000..c786de8
--- /dev/null
+++ b/src/examples/lab2test_beta.c
@@ -0,0 +1,112 @@
+#include <stdio.h>
+#include <string.h>
+#include <syscall.h>
+#include <stdarg.h>
+#include "debug.h"
+
+void fail(void);
+
+int main(int argc UNUSED, char ** argv UNUSED)
+{
+ char *test_string = "This is a string that is written to a file.\n";
+ char byte_array[10] = {0,1,2,3,4,0,1,2,3,4};
+ char sbuf[50];
+ int file[3];
+ int num_bytes_read, num_bytes_written;
+
+ printf("\n");
+ printf("*****************************************************************\n");
+ printf("* This program tests your implementation of basic system calls. *\n");
+ printf("*****************************************************************\n\n");
+
+ printf("The first test is to create three files.\n");
+ printf("(Make sure that you have deleted any test files from previous test runs.)\n");
+ if (!create("test0", (int)strlen(test_string)) || !create("test1", 256) || !create("test2", 256)) {
+ printf("Could not create the testfiles.\n");
+ fail();
+ }
+
+ file[0] = open("test0");
+ file[1] = open("test1");
+ file[2] = open("test2");
+
+ printf("Got file descriptors: %d, %d and %d\n", file[0], file[1], file[2]);
+
+ if (file[0] < 0 || file[1] < 0 || file[2] < 0) {
+ printf("Could not open the test files.\n");
+ fail();
+ }
+
+ printf("\nTesting to read from console. Type 10 characters, please.\n");
+ num_bytes_read = read(STDIN_FILENO, sbuf, 10);
+ if (num_bytes_read != 10) {
+ printf("Did not read 10 characters from the console.\n");
+ fail();
+ }
+ printf("This is what you wrote: \"%s\"\n", sbuf);
+
+ printf("\nTesting to write data to files.\n");
+ write(file[0], test_string, strlen(test_string));
+ write(file[1], byte_array, 10);
+
+ printf("\nTesting to read data back from files.\n");
+ /* Reopening to reset seek position. */
+ close(file[0]);
+ file[0] = open("test0");
+ num_bytes_read = read(file[0], sbuf, 50);
+ if (num_bytes_read != (int)strlen(test_string)) {
+ printf("Could not read back from test0 (%d), %d characters read instead!\n", (int)strlen(test_string), num_bytes_read);
+ fail();
+ }
+
+ close(file[1]);
+ file[1] = open("test1");
+ num_bytes_read = read(file[1], sbuf, 10);
+ if (num_bytes_read != 10) {
+ printf("Could not read back binary data from test1\n");
+ fail();
+ }
+ if (memcmp(sbuf, byte_array, 10) != 0) { /* memcmp returns 0 if the data are identical */
+ printf("Data read back from test1 does not match what was written.\n");
+ fail();
+ }
+ close(file[1]);
+
+ printf("\nTesting write with a bad file descriptor.\n");
+ num_bytes_written = write(file[1], "FOO", 3);
+ if (num_bytes_written != -1) {
+ printf("Writing to a closed file should not be possible.\n");
+ fail();
+ }
+
+ printf("\nTesting read with a bad file descriptor.\n");
+ /* Assuming here that 424242 is a bad file descriptor. */
+ num_bytes_read = read(424242, sbuf, 3);
+ if (num_bytes_read != -1) {
+ printf("Writing to a bad fd should not work.\n");
+ fail();
+ }
+
+ printf("\nTesting to open a non-existing file.\n");
+ file[2] = open("this.file.does.not.exist!");
+ if (file[2] > 1) {
+ printf("Got file handle when opening non-existing file.\n");
+ fail();
+ }
+
+ printf("\n");
+ printf("*****************************************************************\n");
+ printf("* Tests passed; halting machine. *\n");
+ printf("*****************************************************************\n\n");
+ halt();
+ return -1;
+}
+
+void fail(void)
+{
+ printf("\n");
+ printf("*****************************************************************\n");
+ printf("* TEST FAILED *\n");
+ printf("*****************************************************************\n\n");
+ halt();
+}
diff --git a/src/examples/lib/.cvsignore b/src/examples/lib/.cvsignore
new file mode 100644
index 0000000..a438335
--- /dev/null
+++ b/src/examples/lib/.cvsignore
@@ -0,0 +1 @@
+*.d
diff --git a/src/examples/lib/user/.cvsignore b/src/examples/lib/user/.cvsignore
new file mode 100644
index 0000000..a438335
--- /dev/null
+++ b/src/examples/lib/user/.cvsignore
@@ -0,0 +1 @@
+*.d
diff --git a/src/examples/lib/user/.dummy b/src/examples/lib/user/.dummy
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/examples/lib/user/.dummy
diff --git a/src/examples/lineup.c b/src/examples/lineup.c
new file mode 100644
index 0000000..60402d0
--- /dev/null
+++ b/src/examples/lineup.c
@@ -0,0 +1,46 @@
+/* lineup.c
+
+ Converts a file to uppercase in-place.
+
+ Incidentally, another way to do this while avoiding the seeks
+ would be to open the input file, then remove() it and reopen
+ it under another handle. Because of Unix deletion semantics
+ this works fine. */
+
+#include <ctype.h>
+#include <stdio.h>
+#include <syscall.h>
+
+int
+main (int argc, char *argv[])
+{
+ char buf[1024];
+ int handle;
+
+ if (argc != 2)
+ exit (1);
+
+ handle = open (argv[1]);
+ if (handle < 0)
+ exit (2);
+
+ for (;;)
+ {
+ int n, i;
+
+ n = read (handle, buf, sizeof buf);
+ if (n <= 0)
+ break;
+
+ for (i = 0; i < n; i++)
+ buf[i] = toupper ((unsigned char) buf[i]);
+
+ seek (handle, tell (handle) - n);
+ if (write (handle, buf, n) != n)
+ printf ("write failed\n");
+ }
+
+ close (handle);
+
+ return EXIT_SUCCESS;
+}
diff --git a/src/examples/longrun.c b/src/examples/longrun.c
new file mode 100644
index 0000000..e3399f0
--- /dev/null
+++ b/src/examples/longrun.c
@@ -0,0 +1,86 @@
+/* Start a lot of processes and let them finish to test if we
+ * eventually run out of process slots.
+ * To run the test effectively, if you have a limit on number of
+ * processes, lower the limit to 5 processes and run this test like
+ *
+ * 'longrun 5 400'
+ *
+ * It will fill (and if it works empty) your process table 400 times
+ * :-)
+ *
+ * Note that some pintos tests requires at least 16 simultaneous
+ * processes to work, so be sure to increase the limit before running
+ * pintos tests.
+ */
+
+#include <syscall.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#define MAX_SIMULTANEOUS 50
+#define MAX_REPEAT 1000
+
+int main(int argc, char* argv[])
+{
+ char cmd[15];
+ int pid[MAX_SIMULTANEOUS];
+ unsigned i = 0;
+ unsigned j = 0;
+ unsigned simul = 0;
+ unsigned repeat = 0;
+
+ if (argc != 3)
+ {
+ printf("Usage: %s simultaneous repeat\n"
+ "Where 'simultaneous' is the number of simultaneous processes to \n"
+ "start and wait for, and 'repeat' how many times this should be \n"
+ "repeated.\n", argv[0]
+ );
+ return -1;
+ }
+
+ simul = atoi(argv[1]);
+ repeat = atoi(argv[2]);
+
+ if (simul > MAX_SIMULTANEOUS)
+ {
+ printf("This test program is compiled with a limitation to max %d \n"
+ "simultaneos processes.\n", MAX_SIMULTANEOUS);
+ return -1;
+ }
+
+ if (repeat > MAX_REPEAT)
+ {
+ printf("This test program is compiled with a limitation to max %d \n"
+ "repetitions.\n", MAX_REPEAT);
+ return -1;
+ }
+
+ printf("Will try to start a total of %d processes in groups of %d\n",
+ simul * repeat, simul);
+
+ for (j = 0; j < repeat; ++j)
+ {
+ for (i = 0; i < simul; ++i)
+ {
+ snprintf(cmd, 15, "dummy %i", j * simul + i);
+ pid[i] = exec(cmd);
+ }
+
+ /* There will never be more than 'simul' processes running
+ * simultaneously, but in total there will be a lot of processes
+ * (repeat * simul). Just as you can expect in a real system.
+ */
+ for (i = 0; i < simul; ++i)
+ {
+ /* probably nothing left to wait for */
+ if (pid[i] == -1)
+ {
+ printf("ERROR: Aborting test. Some execution(s) failed\n");
+ return j+1;
+ }
+ wait(pid[i]);
+ }
+ }
+ return 0;
+}
diff --git a/src/examples/ls.c b/src/examples/ls.c
new file mode 100644
index 0000000..fbe27a1
--- /dev/null
+++ b/src/examples/ls.c
@@ -0,0 +1,90 @@
+/* ls.c
+
+ Lists the contents of the directory or directories named on
+ the command line, or of the current directory if none are
+ named.
+
+ By default, only the name of each file is printed. If "-l" is
+ given as the first argument, the type, size, and inumber of
+ each file is also printed. This won't work until project 4. */
+
+#include <syscall.h>
+#include <stdio.h>
+#include <string.h>
+
+static bool
+list_dir (const char *dir, bool verbose)
+{
+ int dir_fd = open (dir);
+ if (dir_fd == -1)
+ {
+ printf ("%s: not found\n", dir);
+ return false;
+ }
+
+ if (isdir (dir_fd))
+ {
+ char name[READDIR_MAX_LEN];
+
+ printf ("%s", dir);
+ if (verbose)
+ printf (" (inumber %d)", inumber (dir_fd));
+ printf (":\n");
+
+ while (readdir (dir_fd, name))
+ {
+ printf ("%s", name);
+ if (verbose)
+ {
+ char full_name[128];
+ int entry_fd;
+
+ snprintf (full_name, sizeof full_name, "%s/%s", dir, name);
+ entry_fd = open (full_name);
+
+ printf (": ");
+ if (entry_fd != -1)
+ {
+ if (isdir (entry_fd))
+ printf ("directory");
+ else
+ printf ("%d-byte file", filesize (entry_fd));
+ printf (", inumber %d", inumber (entry_fd));
+ }
+ else
+ printf ("open failed");
+ close (entry_fd);
+ }
+ printf ("\n");
+ }
+ }
+ else
+ printf ("%s: not a directory\n", dir);
+ close (dir_fd);
+ return true;
+}
+
+int
+main (int argc, char *argv[])
+{
+ bool success = true;
+ bool verbose = false;
+
+ if (argc > 1 && !strcmp (argv[1], "-l"))
+ {
+ verbose = true;
+ argv++;
+ argc--;
+ }
+
+ if (argc <= 1)
+ success = list_dir (".", verbose);
+ else
+ {
+ int i;
+ for (i = 1; i < argc; i++)
+ if (!list_dir (argv[i], verbose))
+ success = false;
+ }
+ return success ? EXIT_SUCCESS : EXIT_FAILURE;
+}
diff --git a/src/examples/matmult.c b/src/examples/matmult.c
new file mode 100644
index 0000000..4f0615f
--- /dev/null
+++ b/src/examples/matmult.c
@@ -0,0 +1,57 @@
+/* matmult.c
+
+ Test program to do matrix multiplication on large arrays.
+
+ Intended to stress virtual memory system.
+
+ Ideally, we could read the matrices off of the file system,
+ and store the result back to the file system!
+ */
+
+#include <stdio.h>
+#include <syscall.h>
+
+/* You should define DIM to be large enough that the arrays
+ don't fit in physical memory.
+
+ Dim Memory
+ ------ --------
+ 16 3 kB
+ 64 48 kB
+ 128 192 kB
+ 256 768 kB
+ 512 3,072 kB
+ 1,024 12,288 kB
+ 2,048 49,152 kB
+ 4,096 196,608 kB
+ 8,192 786,432 kB
+ 16,384 3,145,728 kB */
+#define DIM 128
+
+int A[DIM][DIM];
+int B[DIM][DIM];
+int C[DIM][DIM];
+
+int
+main (void)
+{
+ int i, j, k;
+
+ /* Initialize the matrices. */
+ for (i = 0; i < DIM; i++)
+ for (j = 0; j < DIM; j++)
+ {
+ A[i][j] = i;
+ B[i][j] = j;
+ C[i][j] = 0;
+ }
+
+ /* Multiply matrices. */
+ for (i = 0; i < DIM; i++)
+ for (j = 0; j < DIM; j++)
+ for (k = 0; k < DIM; k++)
+ C[i][j] += A[i][k] * B[k][j];
+
+ /* Done. */
+ exit (C[DIM - 1][DIM - 1]);
+}
diff --git a/src/examples/mcat.c b/src/examples/mcat.c
new file mode 100644
index 0000000..7b39760
--- /dev/null
+++ b/src/examples/mcat.c
@@ -0,0 +1,45 @@
+/* mcat.c
+
+ Prints files specified on command line to the console, using
+ mmap. */
+
+#include <stdio.h>
+#include <syscall.h>
+
+int
+main (int argc, char *argv[])
+{
+ int i;
+
+ for (i = 1; i < argc; i++)
+ {
+ int fd;
+ mapid_t map;
+ void *data = (void *) 0x10000000;
+ int size;
+
+ /* Open input file. */
+ fd = open (argv[i]);
+ if (fd < 0)
+ {
+ printf ("%s: open failed\n", argv[i]);
+ return EXIT_FAILURE;
+ }
+ size = filesize (fd);
+
+ /* Map files. */
+ map = mmap (fd, data);
+ if (map == MAP_FAILED)
+ {
+ printf ("%s: mmap failed\n", argv[i]);
+ return EXIT_FAILURE;
+ }
+
+ /* Write file to console. */
+ write (STDOUT_FILENO, data, size);
+
+ /* Unmap files (optional). */
+ munmap (map);
+ }
+ return EXIT_SUCCESS;
+}
diff --git a/src/examples/mcp.c b/src/examples/mcp.c
new file mode 100644
index 0000000..6091dc8
--- /dev/null
+++ b/src/examples/mcp.c
@@ -0,0 +1,68 @@
+/* mcp.c
+
+ Copies one file to another, using mmap. */
+
+#include <stdio.h>
+#include <string.h>
+#include <syscall.h>
+
+int
+main (int argc, char *argv[])
+{
+ int in_fd, out_fd;
+ mapid_t in_map, out_map;
+ void *in_data = (void *) 0x10000000;
+ void *out_data = (void *) 0x20000000;
+ int size;
+
+ if (argc != 3)
+ {
+ printf ("usage: cp OLD NEW\n");
+ return EXIT_FAILURE;
+ }
+
+ /* Open input file. */
+ in_fd = open (argv[1]);
+ if (in_fd < 0)
+ {
+ printf ("%s: open failed\n", argv[1]);
+ return EXIT_FAILURE;
+ }
+ size = filesize (in_fd);
+
+ /* Create and open output file. */
+ if (!create (argv[2], size))
+ {
+ printf ("%s: create failed\n", argv[2]);
+ return EXIT_FAILURE;
+ }
+ out_fd = open (argv[2]);
+ if (out_fd < 0)
+ {
+ printf ("%s: open failed\n", argv[2]);
+ return EXIT_FAILURE;
+ }
+
+ /* Map files. */
+ in_map = mmap (in_fd, in_data);
+ if (in_map == MAP_FAILED)
+ {
+ printf ("%s: mmap failed\n", argv[1]);
+ return EXIT_FAILURE;
+ }
+ out_map = mmap (out_fd, out_data);
+ if (out_map == MAP_FAILED)
+ {
+ printf ("%s: mmap failed\n", argv[2]);
+ return EXIT_FAILURE;
+ }
+
+ /* Copy files. */
+ memcpy (out_data, in_data, size);
+
+ /* Unmap files (optional). */
+ munmap (in_map);
+ munmap (out_map);
+
+ return EXIT_SUCCESS;
+}
diff --git a/src/examples/mkdir.c b/src/examples/mkdir.c
new file mode 100644
index 0000000..7ddbc3f
--- /dev/null
+++ b/src/examples/mkdir.c
@@ -0,0 +1,24 @@
+/* mkdir.c
+
+ Creates a directory. */
+
+#include <stdio.h>
+#include <syscall.h>
+
+int
+main (int argc, char *argv[])
+{
+ if (argc != 2)
+ {
+ printf ("usage: %s DIRECTORY\n", argv[0]);
+ return EXIT_FAILURE;
+ }
+
+ if (!mkdir (argv[1]))
+ {
+ printf ("%s: mkdir failed\n", argv[1]);
+ return EXIT_FAILURE;
+ }
+
+ return EXIT_SUCCESS;
+}
diff --git a/src/examples/parent.c b/src/examples/parent.c
new file mode 100644
index 0000000..7555b2b
--- /dev/null
+++ b/src/examples/parent.c
@@ -0,0 +1,41 @@
+/* parent.c
+ * A test program that calls itself recursively.
+ * In the last step of the recursion child.c is started.
+ * Do not use with large CHILDREN or DEPTH.
+ */
+#include <syscall.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#define CHILDREN 4
+#define DEPTH 3
+
+int main(int argc, char* argv[])
+{
+ int i;
+ int pid[CHILDREN];
+ int depth = DEPTH - 1;
+ char cmd[10];
+
+ if (argc == 2)
+ depth = atoi(argv[1]) - 1;
+
+ for(i = 0; i < CHILDREN; i++)
+ {
+ if (depth)
+ snprintf(cmd, 10, "parent %i", depth);
+ else
+ snprintf(cmd, 10, "child %i", i);
+
+ printf("%s\n", cmd);
+ pid[i] = exec(cmd);
+ }
+// if (depth <= 1)
+ {
+ for(i = 0; i < CHILDREN; i++)
+ {
+ wait(pid[i]);
+ }
+ }
+ exit(0);
+}
diff --git a/src/examples/pfs.c b/src/examples/pfs.c
new file mode 100644
index 0000000..0d9cd52
--- /dev/null
+++ b/src/examples/pfs.c
@@ -0,0 +1,22 @@
+#include "syscall.h"
+
+int main(void)
+{
+ int i;
+ int pid[5];
+
+ create("file.1", 50000);
+ create("messages", 5000);
+
+ pid[0] = exec("pfs_writer a z");
+ pid[1] = exec("pfs_writer A Z");
+ pid[2] = exec("pfs_reader");
+ pid[3] = exec("pfs_reader");
+ pid[4] = exec("pfs_reader");
+
+ for (i = 0; i < 5; i++)
+ {
+ wait(pid[i]);
+ }
+ exit(0);
+}
diff --git a/src/examples/pfs.h b/src/examples/pfs.h
new file mode 100644
index 0000000..2ba7fce
--- /dev/null
+++ b/src/examples/pfs.h
@@ -0,0 +1,2 @@
+#define BIG 3000
+#define TIMES 500
diff --git a/src/examples/pfs_reader.c b/src/examples/pfs_reader.c
new file mode 100644
index 0000000..583583a
--- /dev/null
+++ b/src/examples/pfs_reader.c
@@ -0,0 +1,48 @@
+/* Reads from the file and checks consistency.
+ * The buffer should all contain the same character!!
+ */
+
+#include <syscall.h>
+#include <stdio.h>
+#include "pfs.h"
+
+char buffer[BIG];
+
+int main(void)
+{
+ int bytes, i, j, inconsistency;
+ int id, messages;
+
+ messages = open("messages");
+
+ for (i = 0; i < TIMES; ++i)
+ {
+ id = open("file.1");
+ bytes = read(id, buffer, BIG);
+ close(id);
+
+ if (bytes != BIG)
+ {
+ write(messages, "Buffer not filled!\n", 19);
+ continue;
+ }
+ /* now check for consistency */
+ for (j = 1, inconsistency = 0; j < BIG; ++j)
+ {
+ if (buffer[0] != buffer[j])
+ {
+ /* Ooops, inconsistency */
+ write(messages, "INCONSISTENCY.", 14);
+ printf("INCONSISTENCY\n");
+ inconsistency = 1;
+ break; /* no need to check further */
+ }
+ }
+ if (!inconsistency)
+ {
+ write(messages, "cool\n", 5);
+ }
+ }
+ close(messages);
+ exit(0);
+}
diff --git a/src/examples/pfs_writer.c b/src/examples/pfs_writer.c
new file mode 100644
index 0000000..0ebd772
--- /dev/null
+++ b/src/examples/pfs_writer.c
@@ -0,0 +1,47 @@
+/* Write on the disk.
+ * Each time the buffer is filled with same character.
+ * Different character every time!
+ */
+
+#include <syscall.h>
+#include <stdio.h>
+#include <string.h>
+#include "pfs.h"
+
+char buffer[BIG];
+
+int main(int argc, char* argv[])
+{
+ int i,j;
+ char c;
+ int id;
+ int write_count;
+ char start;
+ char end;
+
+ if (argc != 3 || strlen(argv[1]) != 1 || strlen(argv[2]) != 1)
+ exit(1);
+
+ start = argv[1][0];
+ end = argv[2][0];
+
+ for (i = 0; i < TIMES / (end - start + 1) + 1; ++i)
+ {
+ for (c = start; c <= end; ++c)
+ {
+ for (j = 0; j < BIG; j++)
+ buffer[j] = c;
+
+ id = open("file.1");
+ write_count = write(id, buffer, BIG);
+
+ if ( write_count != BIG )
+ {
+ printf("TEST ERROR: write() wrote only %d bytes out of %d bytes\n",
+ write_count, BIG);
+ }
+ close(id);
+ }
+ }
+ exit(0);
+}
diff --git a/src/examples/pwd.c b/src/examples/pwd.c
new file mode 100644
index 0000000..d2305cf
--- /dev/null
+++ b/src/examples/pwd.c
@@ -0,0 +1,152 @@
+/* pwd.c
+
+ Prints the absolute name of the present working directory. */
+
+#include <syscall.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+
+static bool getcwd (char *cwd, size_t cwd_size);
+
+int
+main (void)
+{
+ char cwd[128];
+ if (getcwd (cwd, sizeof cwd))
+ {
+ printf ("%s\n", cwd);
+ return EXIT_SUCCESS;
+ }
+ else
+ {
+ printf ("error\n");
+ return EXIT_FAILURE;
+ }
+}
+
+/* Stores the inode number for FILE_NAME in *INUM.
+ Returns true if successful, false if the file could not be
+ opened. */
+static bool
+get_inumber (const char *file_name, int *inum)
+{
+ int fd = open (file_name);
+ if (fd >= 0)
+ {
+ *inum = inumber (fd);
+ close (fd);
+ return true;
+ }
+ else
+ return false;
+}
+
+/* Prepends PREFIX to the characters stored in the final *DST_LEN
+ bytes of the DST_SIZE-byte buffer that starts at DST.
+ Returns true if successful, false if adding that many
+ characters, plus a null terminator, would overflow the buffer.
+ (No null terminator is actually added or depended upon, but
+ its space is accounted for.) */
+static bool
+prepend (const char *prefix,
+ char *dst, size_t *dst_len, size_t dst_size)
+{
+ size_t prefix_len = strlen (prefix);
+ if (prefix_len + *dst_len + 1 <= dst_size)
+ {
+ *dst_len += prefix_len;
+ memcpy ((dst + dst_size) - *dst_len, prefix, prefix_len);
+ return true;
+ }
+ else
+ return false;
+}
+
+/* Stores the current working directory, as a null-terminated
+ string, in the CWD_SIZE bytes in CWD.
+ Returns true if successful, false on error. Errors include
+ system errors, directory trees deeper than MAX_LEVEL levels,
+ and insufficient space in CWD. */
+static bool
+getcwd (char *cwd, size_t cwd_size)
+{
+ size_t cwd_len = 0;
+
+#define MAX_LEVEL 20
+ char name[MAX_LEVEL * 3 + 1 + READDIR_MAX_LEN + 1];
+ char *namep;
+
+ int child_inum;
+
+ /* Make sure there's enough space for at least "/". */
+ if (cwd_size < 2)
+ return false;
+
+ /* Get inumber for current directory. */
+ if (!get_inumber (".", &child_inum))
+ return false;
+
+ namep = name;
+ for (;;)
+ {
+ int parent_inum, parent_fd;
+
+ /* Compose "../../../..", etc., in NAME. */
+ if ((namep - name) > MAX_LEVEL * 3)
+ return false;
+ *namep++ = '.';
+ *namep++ = '.';
+ *namep = '\0';
+
+ /* Open directory. */
+ parent_fd = open (name);
+ if (parent_fd < 0)
+ return false;
+ *namep++ = '/';
+
+ /* If parent and child have the same inumber,
+ then we've arrived at the root. */
+ parent_inum = inumber (parent_fd);
+ if (parent_inum == child_inum)
+ break;
+
+ /* Find name of file in parent directory with the child's
+ inumber. */
+ for (;;)
+ {
+ int test_inum;
+ if (!readdir (parent_fd, namep) || !get_inumber (name, &test_inum))
+ {
+ close (parent_fd);
+ return false;
+ }
+ if (test_inum == child_inum)
+ break;
+ }
+ close (parent_fd);
+
+ /* Prepend "/name" to CWD. */
+ if (!prepend (namep - 1, cwd, &cwd_len, cwd_size))
+ return false;
+
+ /* Move up. */
+ child_inum = parent_inum;
+ }
+
+ /* Finalize CWD. */
+ if (cwd_len > 0)
+ {
+ /* Move the string to the beginning of CWD,
+ and null-terminate it. */
+ memmove (cwd, (cwd + cwd_size) - cwd_len, cwd_len);
+ cwd[cwd_len] = '\0';
+ }
+ else
+ {
+ /* Special case for the root. */
+ strlcpy (cwd, "/", cwd_size);
+ }
+
+ return true;
+}
diff --git a/src/examples/recursor.c b/src/examples/recursor.c
new file mode 100644
index 0000000..79c784a
--- /dev/null
+++ b/src/examples/recursor.c
@@ -0,0 +1,34 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <syscall.h>
+
+int
+main (int argc, char *argv[])
+{
+ char buffer[128];
+ pid_t pid;
+ int retval = 0;
+
+ if (argc != 4)
+ {
+ printf ("usage: recursor <string> <depth> <waitp>\n");
+ exit (1);
+ }
+
+ /* Print args. */
+ printf ("%s %s %s %s\n", argv[0], argv[1], argv[2], argv[3]);
+
+ /* Execute child and wait for it to finish if requested. */
+ if (atoi (argv[2]) != 0)
+ {
+ snprintf (buffer, sizeof buffer,
+ "recursor %s %d %s", argv[1], atoi (argv[2]) - 1, argv[3]);
+ pid = exec (buffer);
+ if (atoi (argv[3]))
+ retval = wait (pid);
+ }
+
+ /* Done. */
+ printf ("%s %s: dying, retval=%d\n", argv[1], argv[2], retval);
+ exit (retval);
+}
diff --git a/src/examples/rm.c b/src/examples/rm.c
new file mode 100644
index 0000000..0db7f7b
--- /dev/null
+++ b/src/examples/rm.c
@@ -0,0 +1,21 @@
+/* rm.c
+
+ Removes files specified on command line. */
+
+#include <stdio.h>
+#include <syscall.h>
+
+int
+main (int argc, char *argv[])
+{
+ bool success = true;
+ int i;
+
+ for (i = 1; i < argc; i++)
+ if (!remove (argv[i]))
+ {
+ printf ("%s: remove failed\n", argv[i]);
+ success = false;
+ }
+ return success ? EXIT_SUCCESS : EXIT_FAILURE;
+}
diff --git a/src/examples/shell.c b/src/examples/shell.c
new file mode 100644
index 0000000..93641b4
--- /dev/null
+++ b/src/examples/shell.c
@@ -0,0 +1,104 @@
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+#include <syscall.h>
+
+static void read_line (char line[], size_t);
+static bool backspace (char **pos, char line[]);
+
+int
+main (void)
+{
+ printf ("Shell starting...\n");
+ for (;;)
+ {
+ char command[80];
+
+ /* Read command. */
+ printf ("--");
+ read_line (command, sizeof command);
+
+ /* Execute command. */
+ if (!strcmp (command, "exit"))
+ break;
+ else if (!memcmp (command, "cd ", 3))
+ {
+ if (!chdir (command + 3))
+ printf ("\"%s\": chdir failed\n", command + 3);
+ }
+ else if (command[0] == '\0')
+ {
+ /* Empty command. */
+ }
+ else
+ {
+ pid_t pid = exec (command);
+ if (pid != PID_ERROR)
+ printf ("\"%s\": exit code %d\n", command, wait (pid));
+ else
+ printf ("exec failed\n");
+ }
+ }
+
+ printf ("Shell exiting.");
+ return EXIT_SUCCESS;
+}
+
+/* Reads a line of input from the user into LINE, which has room
+ for SIZE bytes. Handles backspace and Ctrl+U in the ways
+ expected by Unix users. On return, LINE will always be
+ null-terminated and will not end in a new-line character. */
+static void
+read_line (char line[], size_t size)
+{
+ char *pos = line;
+ for (;;)
+ {
+ char c;
+ read (STDIN_FILENO, &c, 1);
+
+ switch (c)
+ {
+ case '\r':
+ *pos = '\0';
+ putchar ('\n');
+ return;
+
+ case '\b':
+ backspace (&pos, line);
+ break;
+
+ case ('U' - 'A') + 1: /* Ctrl+U. */
+ while (backspace (&pos, line))
+ continue;
+ break;
+
+ default:
+ /* Add character to line. */
+ if (pos < line + size - 1)
+ {
+ putchar (c);
+ *pos++ = c;
+ }
+ break;
+ }
+ }
+}
+
+/* If *POS is past the beginning of LINE, backs up one character
+ position. Returns true if successful, false if nothing was
+ done. */
+static bool
+backspace (char **pos, char line[])
+{
+ if (*pos > line)
+ {
+ /* Back up cursor, overwrite character, back up
+ again. */
+ printf ("\b \b");
+ (*pos)--;
+ return true;
+ }
+ else
+ return false;
+}
diff --git a/src/examples/sumargv.c b/src/examples/sumargv.c
new file mode 100644
index 0000000..06962f9
--- /dev/null
+++ b/src/examples/sumargv.c
@@ -0,0 +1,26 @@
+#include <stdlib.h>
+
+int
+main (int argc, char **argv)
+{
+ int i;
+ int sum = 0;
+ char* argv_me = "sumargv";
+ char* p;
+
+ for (p = argv_me, i = 0; *p; ++p, ++i)
+ sum += (*p - 'a') * i;
+
+ for (p = argv[0], i = 0; *p; ++p, ++i)
+ sum -= (*p - 'a') * i;
+
+ /* if program name is correctly set up sum should now be zero */
+
+ for (i = 1; i < argc; i++)
+ sum += atoi(argv[i]);
+
+ /* if argv ends correctly with a null pointer this has no effect */
+ sum += argv[argc];
+
+ return sum;
+}