diff options
| author | Felipe Boeira <felipe.boeira@liu.se> | 2019-01-08 18:39:03 +0100 |
|---|---|---|
| committer | Felipe Boeira <felipe.boeira@liu.se> | 2019-01-08 18:39:03 +0100 |
| commit | d4522b8e9854178473adcea0fbb84f23f6e744bd (patch) | |
| tree | fbcf620617c5023154eba3f965b3a982daa64a47 /src/examples | |
| download | pintos-d4522b8e9854178473adcea0fbb84f23f6e744bd.tar.gz | |
Initial commit
Diffstat (limited to 'src/examples')
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; +} |
