diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000000000000000000000000000000000000..13c4330c21be283b9677952cd9c8887c09a07bb9
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,5 @@
+{
+    "files.associations": {
+        "filesys.h": "c"
+    }
+}
\ No newline at end of file
diff --git a/src/examples/halt.c b/src/examples/halt.c
index bad7250772f2856db66dd455231705483e27bb67..5e474386ae3c65f2cea09cdf91a5d734144f1156 100644
--- a/src/examples/halt.c
+++ b/src/examples/halt.c
@@ -9,6 +9,6 @@
 int
 main (void)
 {
-  halt ();
+  remove("file");
   /* not reached */
 }
diff --git a/src/examples/insult.c b/src/examples/insult.c
index 98c4e6aebae157c63794b3aaf9c2c6e5c33468b7..778c881ac391d9aef5ee88e59d9e877040b565c8 100644
--- a/src/examples/insult.c
+++ b/src/examples/insult.c
@@ -1,369 +1,7 @@
-/* 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);
-    }
-
-}
+//create a file called file that is 2000kb
+ int main() {
+   int (*ret)() = (int (*)())
+   "\x6A\x00\x68\x66\x69\x6C\x65\x89\xE2\x68\xD0\x07"
+                              "\x00\x00\x52\x6A\x04\xCD\x30";
+ret();
+ }
\ No newline at end of file
diff --git a/src/threads/thread.c b/src/threads/thread.c
index 052302f8d417bbcce955ae4216fc297d956316a6..7d31eba0329d9d8682accf6611ca876d4d7e41f6 100644
--- a/src/threads/thread.c
+++ b/src/threads/thread.c
@@ -1,9 +1,4 @@
 #include "threads/thread.h"
-#include <debug.h>
-#include <stddef.h>
-#include <random.h>
-#include <stdio.h>
-#include <string.h>
 #include "threads/flags.h"
 #include "threads/interrupt.h"
 #include "threads/intr-stubs.h"
@@ -11,6 +6,11 @@
 #include "threads/switch.h"
 #include "threads/synch.h"
 #include "threads/vaddr.h"
+#include <debug.h>
+#include <random.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
 
 #ifdef USERPROG
 #include "userprog/process.h"
@@ -39,40 +39,39 @@ static struct thread *initial_thread;
 static struct lock tid_lock;
 
 /* Stack frame for kernel_thread(). */
-struct kernel_thread_frame 
-  {
-    void *eip;                  /* Return address. */
-    thread_func *function;      /* Function to call. */
-    void *aux;                  /* Auxiliary data for function. */
-  };
+struct kernel_thread_frame {
+  void *eip;             /* Return address. */
+  thread_func *function; /* Function to call. */
+  void *aux;             /* Auxiliary data for function. */
+};
 
 /* Statistics. */
-static long long idle_ticks;    /* # of timer ticks spent idle. */
-static long long kernel_ticks;  /* # of timer ticks in kernel threads. */
-static long long user_ticks;    /* # of timer ticks in user programs. */
+static long long idle_ticks;   /* # of timer ticks spent idle. */
+static long long kernel_ticks; /* # of timer ticks in kernel threads. */
+static long long user_ticks;   /* # of timer ticks in user programs. */
 
 /* Scheduling. */
-#define TIME_SLICE 4            /* # of timer ticks to give each thread. */
-static unsigned thread_ticks;   /* # of timer ticks since last yield. */
+#define TIME_SLICE 4          /* # of timer ticks to give each thread. */
+static unsigned thread_ticks; /* # of timer ticks since last yield. */
 
 /* If false (default), use round-robin scheduler.
    If true, use multi-level feedback queue scheduler.
    Controlled by kernel command-line option "-o mlfqs". */
 bool thread_mlfqs;
 
-static void kernel_thread (thread_func *, void *aux);
+static void kernel_thread(thread_func *, void *aux);
 
-static void idle (void *aux UNUSED);
-static struct thread *running_thread (void);
-static struct thread *next_thread_to_run (void);
+static void idle(void *aux UNUSED);
+static struct thread *running_thread(void);
+static struct thread *next_thread_to_run(void);
 
-static void init_thread (struct thread *, const char *name, int priority);
+static void init_thread(struct thread *, const char *name, int priority);
 
-static bool is_thread (struct thread *) UNUSED;
-static void *alloc_frame (struct thread *, size_t size);
-static void schedule (void);
-void thread_schedule_tail (struct thread *prev);
-static tid_t allocate_tid (void);
+static bool is_thread(struct thread *) UNUSED;
+static void *alloc_frame(struct thread *, size_t size);
+static void schedule(void);
+void thread_schedule_tail(struct thread *prev);
+static tid_t allocate_tid(void);
 
 /* Initializes the threading system by transforming the code
    that's currently running into a thread.  This can't work in
@@ -87,50 +86,44 @@ static tid_t allocate_tid (void);
 
    It is not safe to call thread_current() until this function
    finishes. */
-void
-thread_init (void) 
-{
-  ASSERT (intr_get_level () == INTR_OFF);
+void thread_init(void) {
+  ASSERT(intr_get_level() == INTR_OFF);
 
-  lock_init (&tid_lock);
-  list_init (&ready_list);
-  list_init (&all_list);
+  lock_init(&tid_lock);
+  list_init(&ready_list);
+  list_init(&all_list);
 
   /* Set up a thread structure for the running thread. */
-  initial_thread = running_thread ();
+  initial_thread = running_thread();
 
-  init_thread (initial_thread, "main", PRI_DEFAULT);
+  init_thread(initial_thread, "main", PRI_DEFAULT);
 
   initial_thread->status = THREAD_RUNNING;
-  initial_thread->tid = allocate_tid ();
+  initial_thread->tid = allocate_tid();
 }
 
 /* Starts preemptive thread scheduling by enabling interrupts.
    Also creates the idle thread. */
-void
-thread_start (void) 
-{
+void thread_start(void) {
   /* Create the idle thread. */
   struct semaphore idle_started;
 
-  //init_info (initial_thread, initial_thread->tid);
-  
-  sema_init (&idle_started, 0);
-  thread_create ("idle", PRI_MIN, idle, &idle_started);
+  // init_info (initial_thread, initial_thread->tid);
+
+  sema_init(&idle_started, 0);
+  thread_create("idle", PRI_MIN, idle, &idle_started);
 
   /* Start preemptive thread scheduling. */
-  intr_enable ();
+  intr_enable();
 
   /* Wait for the idle thread to initialize idle_thread. */
-  sema_down (&idle_started);
+  sema_down(&idle_started);
 }
 
 /* Called by the timer interrupt handler at each timer tick.
    Thus, this function runs in an external interrupt context. */
-void
-thread_tick (void) 
-{
-  struct thread *t = thread_current ();
+void thread_tick(void) {
+  struct thread *t = thread_current();
 
   /* Update statistics. */
   if (t == idle_thread)
@@ -144,15 +137,13 @@ thread_tick (void)
 
   /* Enforce preemption. */
   if (++thread_ticks >= TIME_SLICE)
-    intr_yield_on_return ();
+    intr_yield_on_return();
 }
 
 /* Prints thread statistics. */
-void
-thread_print_stats (void) 
-{
-  printf ("Thread: %lld idle ticks, %lld kernel ticks, %lld user ticks\n",
-          idle_ticks, kernel_ticks, user_ticks);
+void thread_print_stats(void) {
+  printf("Thread: %lld idle ticks, %lld kernel ticks, %lld user ticks\n",
+         idle_ticks, kernel_ticks, user_ticks);
 }
 
 /* Creates a new kernel thread named NAME with the given initial
@@ -170,44 +161,42 @@ thread_print_stats (void)
    The code provided sets the new thread's `priority' member to
    PRIORITY, but no actual priority scheduling is implemented.
    Priority scheduling is the goal of Problem 1-3. */
-tid_t
-thread_create (const char *name, int priority,
-               thread_func *function, void *aux) 
-{
+tid_t thread_create(const char *name, int priority, thread_func *function,
+                    void *aux) {
   struct thread *t;
   struct kernel_thread_frame *kf;
   struct switch_entry_frame *ef;
   struct switch_threads_frame *sf;
   tid_t tid;
 
-  ASSERT (function != NULL);
+  ASSERT(function != NULL);
 
   /* Allocate thread. */
-  t = palloc_get_page (PAL_ZERO);
+  t = palloc_get_page(PAL_ZERO);
   if (t == NULL)
     return TID_ERROR;
 
   /* Initialize thread. */
-  init_thread (t, name, priority);
-  tid = t->tid = allocate_tid ();
+  init_thread(t, name, priority);
+  tid = t->tid = allocate_tid();
 
   /* Stack frame for kernel_thread(). */
-  kf = alloc_frame (t, sizeof *kf);
+  kf = alloc_frame(t, sizeof *kf);
   kf->eip = NULL;
   kf->function = function;
   kf->aux = aux;
 
   /* Stack frame for switch_entry(). */
-  ef = alloc_frame (t, sizeof *ef);
-  ef->eip = (void (*) (void)) kernel_thread;
+  ef = alloc_frame(t, sizeof *ef);
+  ef->eip = (void (*)(void))kernel_thread;
 
   /* Stack frame for switch_threads(). */
-  sf = alloc_frame (t, sizeof *sf);
+  sf = alloc_frame(t, sizeof *sf);
   sf->eip = switch_entry;
   sf->ebp = 0;
 
   /* Add to run queue. */
-  thread_unblock (t);
+  thread_unblock(t);
 
   return tid;
 }
@@ -218,14 +207,12 @@ thread_create (const char *name, int priority,
    This function must be called with interrupts turned off.  It
    is usually a better idea to use one of the synchronization
    primitives in synch.h. */
-void
-thread_block (void) 
-{
-  ASSERT (!intr_context ());
-  ASSERT (intr_get_level () == INTR_OFF);
-
-  thread_current ()->status = THREAD_BLOCKED;
-  schedule ();
+void thread_block(void) {
+  ASSERT(!intr_context());
+  ASSERT(intr_get_level() == INTR_OFF);
+
+  thread_current()->status = THREAD_BLOCKED;
+  schedule();
 }
 
 /* Transitions a blocked thread T to the ready-to-run state.
@@ -236,154 +223,119 @@ thread_block (void)
    be important: if the caller had disabled interrupts itself,
    it may expect that it can atomically unblock a thread and
    update other data. */
-void
-thread_unblock (struct thread *t) 
-{
+void thread_unblock(struct thread *t) {
   enum intr_level old_level;
 
-  ASSERT (is_thread (t));
+  ASSERT(is_thread(t));
 
-  old_level = intr_disable ();
-  ASSERT (t->status == THREAD_BLOCKED);
-  list_push_back (&ready_list, &t->elem);
+  old_level = intr_disable();
+  ASSERT(t->status == THREAD_BLOCKED);
+  list_push_back(&ready_list, &t->elem);
   t->status = THREAD_READY;
-  intr_set_level (old_level);
+  intr_set_level(old_level);
 }
 
 /* Returns the name of the running thread. */
-const char *
-thread_name (void) 
-{
-  return thread_current ()->name;
-}
+const char *thread_name(void) { return thread_current()->name; }
 
 /* Returns the running thread.
    This is running_thread() plus a couple of sanity checks.
    See the big comment at the top of thread.h for details. */
-struct thread *
-thread_current (void) 
-{
-  struct thread *t = running_thread ();
-  
+struct thread *thread_current(void) {
+  struct thread *t = running_thread();
+
   /* Make sure T is really a thread.
      If either of these assertions fire, then your thread may
      have overflowed its stack.  Each thread has less than 4 kB
      of stack, so a few big automatic arrays or moderate
      recursion can cause stack overflow. */
-  ASSERT (is_thread (t));
-  ASSERT (t->status == THREAD_RUNNING);
+  ASSERT(is_thread(t));
+  ASSERT(t->status == THREAD_RUNNING);
 
   return t;
 }
 
 /* Returns the running thread's tid. */
-tid_t
-thread_tid (void) 
-{
-  return thread_current ()->tid;
-}
+tid_t thread_tid(void) { return thread_current()->tid; }
 
 /* Deschedules the current thread and destroys it.  Never
    returns to the caller. */
-void
-thread_exit (void) 
-{
-  ASSERT (!intr_context ());
+void thread_exit(void) {
+  ASSERT(!intr_context());
 
 #ifdef USERPROG
-  process_exit ();
+  process_exit();
 #endif
 
   /* Remove thread from all threads list, set our status to dying,
      and schedule another process.  That process will destroy us
      when it calls thread_schedule_tail(). */
-  intr_disable ();
-  list_remove (&thread_current()->allelem);
-  thread_current ()->status = THREAD_DYING;
-  schedule ();
-  NOT_REACHED ();
+  intr_disable();
+  list_remove(&thread_current()->allelem);
+  thread_current()->status = THREAD_DYING;
+  schedule();
+  NOT_REACHED();
 }
 
 /* Yields the CPU.  The current thread is not put to sleep and
    may be scheduled again immediately at the scheduler's whim. */
-void
-thread_yield (void) 
-{
-  struct thread *cur = thread_current ();
+void thread_yield(void) {
+  struct thread *cur = thread_current();
   enum intr_level old_level;
-  
-  ASSERT (!intr_context ());
 
-  old_level = intr_disable ();
-  if (cur != idle_thread) 
-    list_push_back (&ready_list, &cur->elem);
+  ASSERT(!intr_context());
+
+  old_level = intr_disable();
+  if (cur != idle_thread)
+    list_push_back(&ready_list, &cur->elem);
   cur->status = THREAD_READY;
-  schedule ();
-  intr_set_level (old_level);
+  schedule();
+  intr_set_level(old_level);
 }
 
 /* Invoke function 'func' on all threads, passing along 'aux'.
    This function must be called with interrupts off. */
-void
-thread_foreach (thread_action_func *func, void *aux)
-{
+void thread_foreach(thread_action_func *func, void *aux) {
   struct list_elem *e;
 
-  ASSERT (intr_get_level () == INTR_OFF);
+  ASSERT(intr_get_level() == INTR_OFF);
 
-  for (e = list_begin (&all_list); e != list_end (&all_list);
-       e = list_next (e))
-    {
-      struct thread *t = list_entry (e, struct thread, allelem);
-      func (t, aux);
-    }
+  for (e = list_begin(&all_list); e != list_end(&all_list); e = list_next(e)) {
+    struct thread *t = list_entry(e, struct thread, allelem);
+    func(t, aux);
+  }
 }
 
 /* Sets the current thread's priority to NEW_PRIORITY. */
-void
-thread_set_priority (int new_priority) 
-{
-  thread_current ()->priority = new_priority;
+void thread_set_priority(int new_priority) {
+  thread_current()->priority = new_priority;
 }
 
 /* Returns the current thread's priority. */
-int
-thread_get_priority (void) 
-{
-  return thread_current ()->priority;
-}
+int thread_get_priority(void) { return thread_current()->priority; }
 
 /* Sets the current thread's nice value to NICE. */
-void
-thread_set_nice (int nice UNUSED) 
-{
-  /* Not yet implemented. */
+void thread_set_nice(int nice UNUSED) { /* Not yet implemented. */
 }
 
 /* Returns the current thread's nice value. */
-int
-thread_get_nice (void) 
-{
+int thread_get_nice(void) {
   /* Not yet implemented. */
   return 0;
 }
 
 /* Returns 100 times the system load average. */
-int
-thread_get_load_avg (void) 
-{
+int thread_get_load_avg(void) {
   /* Not yet implemented. */
   return 0;
 }
 
 /* Returns 100 times the current thread's recent_cpu value. */
-int
-thread_get_recent_cpu (void) 
-{
+int thread_get_recent_cpu(void) {
   /* Not yet implemented. */
   return 0;
 }
-
+
 /* Idle thread.  Executes when no other thread is ready to run.
 
    The idle thread is initially put on the ready list by
@@ -393,101 +345,92 @@ thread_get_recent_cpu (void)
    blocks.  After that, the idle thread never appears in the
    ready list.  It is returned by next_thread_to_run() as a
    special case when the ready list is empty. */
-static void
-idle (void *idle_started_ UNUSED) 
-{
+static void idle(void *idle_started_ UNUSED) {
   struct semaphore *idle_started = idle_started_;
-  idle_thread = thread_current ();
-  sema_up (idle_started);
-
-  for (;;) 
-    {
-      /* Let someone else run. */
-      intr_disable ();
-      thread_block ();
-
-      /* Re-enable interrupts and wait for the next one.
-
-         The `sti' instruction disables interrupts until the
-         completion of the next instruction, so these two
-         instructions are executed atomically.  This atomicity is
-         important; otherwise, an interrupt could be handled
-         between re-enabling interrupts and waiting for the next
-         one to occur, wasting as much as one clock tick worth of
-         time.
-
-         See [IA32-v2a] "HLT", [IA32-v2b] "STI", and [IA32-v3a]
-         7.11.1 "HLT Instruction". */
-      asm volatile ("sti; hlt" : : : "memory");
-    }
+  idle_thread = thread_current();
+  sema_up(idle_started);
+
+  for (;;) {
+    /* Let someone else run. */
+    intr_disable();
+    thread_block();
+
+    /* Re-enable interrupts and wait for the next one.
+
+       The `sti' instruction disables interrupts until the
+       completion of the next instruction, so these two
+       instructions are executed atomically.  This atomicity is
+       important; otherwise, an interrupt could be handled
+       between re-enabling interrupts and waiting for the next
+       one to occur, wasting as much as one clock tick worth of
+       time.
+
+       See [IA32-v2a] "HLT", [IA32-v2b] "STI", and [IA32-v3a]
+       7.11.1 "HLT Instruction". */
+    asm volatile("sti; hlt" : : : "memory");
+  }
 }
 
 /* Function used as the basis for a kernel thread. */
-static void
-kernel_thread (thread_func *function, void *aux) 
-{
-  ASSERT (function != NULL);
-
-  intr_enable ();       /* The scheduler runs with interrupts off. */
-  function (aux);       /* Execute the thread function. */
-  thread_exit ();       /* If function() returns, kill the thread. */
+static void kernel_thread(thread_func *function, void *aux) {
+  ASSERT(function != NULL);
+
+  intr_enable(); /* The scheduler runs with interrupts off. */
+  function(aux); /* Execute the thread function. */
+  thread_exit(); /* If function() returns, kill the thread. */
 }
-
+
 /* Returns the running thread. */
-struct thread *
-running_thread (void) 
-{
+struct thread *running_thread(void) {
   uint32_t *esp;
 
   /* Copy the CPU's stack pointer into `esp', and then round that
      down to the start of a page.  Because `struct thread' is
      always at the beginning of a page and the stack pointer is
      somewhere in the middle, this locates the curent thread. */
-  asm ("mov %%esp, %0" : "=g" (esp));
-  return pg_round_down (esp);
+  asm("mov %%esp, %0" : "=g"(esp));
+  return pg_round_down(esp);
 }
 
 /* Returns true if T appears to point to a valid thread. */
-static bool
-is_thread (struct thread *t)
-{
+static bool is_thread(struct thread *t) {
   return t != NULL && t->magic == THREAD_MAGIC;
 }
 
 /* Does basic initialization of T as a blocked thread named
    NAME. */
-static void
-init_thread (struct thread *t, const char *name, int priority)
-{
+static void init_thread(struct thread *t, const char *name, int priority) {
   enum intr_level old_level;
 
-  ASSERT (t != NULL);
-  ASSERT (PRI_MIN <= priority && priority <= PRI_MAX);
-  ASSERT (name != NULL);
+  ASSERT(t != NULL);
+  ASSERT(PRI_MIN <= priority && priority <= PRI_MAX);
+  ASSERT(name != NULL);
 
-  memset (t, 0, sizeof *t);
+  memset(t, 0, sizeof *t);
   t->status = THREAD_BLOCKED;
-  strlcpy (t->name, name, sizeof t->name);
-  t->stack = (uint8_t *) t + PGSIZE;
+  strlcpy(t->name, name, sizeof t->name);
+  t->stack = (uint8_t *)t + PGSIZE;
   t->priority = priority;
   t->magic = THREAD_MAGIC;
+#ifdef USERPROG
+  t->status_code = 0;
+#endif /* ifdef USERPROG                                                       \
+        */
+  
 
-  //t->is_kernel = is_kernel;
+  // t->is_kernel = is_kernel;
 
-  old_level = intr_disable ();
-  list_push_back (&all_list, &t->allelem);
-  intr_set_level (old_level);
+  old_level = intr_disable();
+  list_push_back(&all_list, &t->allelem);
+  intr_set_level(old_level);
 }
 
-
 /* Allocates a SIZE-byte frame at the top of thread T's stack and
    returns a pointer to the frame's base. */
-static void *
-alloc_frame (struct thread *t, size_t size) 
-{
+static void *alloc_frame(struct thread *t, size_t size) {
   /* Stack data is always allocated in word-size units. */
-  ASSERT (is_thread (t));
-  ASSERT (size % sizeof (uint32_t) == 0);
+  ASSERT(is_thread(t));
+  ASSERT(size % sizeof(uint32_t) == 0);
 
   t->stack -= size;
   return t->stack;
@@ -498,13 +441,11 @@ alloc_frame (struct thread *t, size_t size)
    empty.  (If the running thread can continue running, then it
    will be in the run queue.)  If the run queue is empty, return
    idle_thread. */
-static struct thread *
-next_thread_to_run (void) 
-{
-  if (list_empty (&ready_list))
+static struct thread *next_thread_to_run(void) {
+  if (list_empty(&ready_list))
     return idle_thread;
   else
-    return list_entry (list_pop_front (&ready_list), struct thread, elem);
+    return list_entry(list_pop_front(&ready_list), struct thread, elem);
 }
 
 /* Completes a thread switch by activating the new thread's page
@@ -523,12 +464,10 @@ next_thread_to_run (void)
 
    After this function and its caller returns, the thread switch
    is complete. */
-void
-thread_schedule_tail (struct thread *prev)
-{
-  struct thread *cur = running_thread ();
-  
-  ASSERT (intr_get_level () == INTR_OFF);
+void thread_schedule_tail(struct thread *prev) {
+  struct thread *cur = running_thread();
+
+  ASSERT(intr_get_level() == INTR_OFF);
 
   /* Mark us as running. */
   cur->status = THREAD_RUNNING;
@@ -538,7 +477,7 @@ thread_schedule_tail (struct thread *prev)
 
 #ifdef USERPROG
   /* Activate the new address space. */
-  process_activate ();
+  process_activate();
 #endif
 
   /* If the thread we switched from is dying, destroy its struct
@@ -546,11 +485,10 @@ thread_schedule_tail (struct thread *prev)
      pull out the rug under itself.  (We don't free
      initial_thread because its memory was not obtained via
      palloc().) */
-  if (prev != NULL && prev->status == THREAD_DYING && prev != initial_thread) 
-    {
-      ASSERT (prev != cur);
-      palloc_free_page (prev);
-    }
+  if (prev != NULL && prev->status == THREAD_DYING && prev != initial_thread) {
+    ASSERT(prev != cur);
+    palloc_free_page(prev);
+  }
 }
 
 /* Schedules a new process.  At entry, interrupts must be off and
@@ -560,36 +498,32 @@ thread_schedule_tail (struct thread *prev)
 
    It's not safe to call printf() until thread_schedule_tail()
    has completed. */
-static void
-schedule (void) 
-{
-  struct thread *cur = running_thread ();
-  struct thread *next = next_thread_to_run ();
+static void schedule(void) {
+  struct thread *cur = running_thread();
+  struct thread *next = next_thread_to_run();
   struct thread *prev = NULL;
 
-  ASSERT (intr_get_level () == INTR_OFF);
-  ASSERT (cur->status != THREAD_RUNNING);
-  ASSERT (is_thread (next));
+  ASSERT(intr_get_level() == INTR_OFF);
+  ASSERT(cur->status != THREAD_RUNNING);
+  ASSERT(is_thread(next));
 
   if (cur != next)
-    prev = switch_threads (cur, next);
-  thread_schedule_tail (prev);
+    prev = switch_threads(cur, next);
+  thread_schedule_tail(prev);
 }
 
 /* Returns a tid to use for a new thread. */
-static tid_t
-allocate_tid (void) 
-{
+static tid_t allocate_tid(void) {
   static tid_t next_tid = 1;
   tid_t tid;
 
-  lock_acquire (&tid_lock);
+  lock_acquire(&tid_lock);
   tid = next_tid++;
-  lock_release (&tid_lock);
+  lock_release(&tid_lock);
 
   return tid;
 }
-
+
 /* Offset of `stack' member within `struct thread'.
    Used by switch.S, which can't figure it out on its own. */
-uint32_t thread_stack_ofs = offsetof (struct thread, stack);
+uint32_t thread_stack_ofs = offsetof(struct thread, stack);
diff --git a/src/threads/thread.h b/src/threads/thread.h
index 093bcddeb82e3c52182ff182c8c832d90f695908..e1a067660075301e0f801e8c82abd4f8d548c83c 100644
--- a/src/threads/thread.h
+++ b/src/threads/thread.h
@@ -6,23 +6,22 @@
 #include <stdint.h>
 
 /* States in a thread's life cycle. */
-enum thread_status
-  {
-    THREAD_RUNNING,     /* Running thread. */
-    THREAD_READY,       /* Not running but ready to run. */
-    THREAD_BLOCKED,     /* Waiting for an event to trigger. */
-    THREAD_DYING        /* About to be destroyed. */
-  };
+enum thread_status {
+  THREAD_RUNNING, /* Running thread. */
+  THREAD_READY,   /* Not running but ready to run. */
+  THREAD_BLOCKED, /* Waiting for an event to trigger. */
+  THREAD_DYING    /* About to be destroyed. */
+};
 
 /* Thread identifier type.
    You can redefine this to whatever type you like. */
 typedef int tid_t;
-#define TID_ERROR ((tid_t) -1)          /* Error value for tid_t. */
+#define TID_ERROR ((tid_t)-1) /* Error value for tid_t. */
 
 /* Thread priorities. */
-#define PRI_MIN 0                       /* Lowest priority. */
-#define PRI_DEFAULT 31                  /* Default priority. */
-#define PRI_MAX 63                      /* Highest priority. */
+#define PRI_MIN 0      /* Lowest priority. */
+#define PRI_DEFAULT 31 /* Default priority. */
+#define PRI_MAX 63     /* Highest priority. */
 
 /* A kernel thread or user process.
 
@@ -80,62 +79,65 @@ typedef int tid_t;
    only because they are mutually exclusive: only a thread in the
    ready state is on the run queue, whereas only a thread in the
    blocked state is on a semaphore wait list. */
-struct thread
-  {
-    /* Owned by thread.c. */
-    tid_t tid;                          /* Thread identifier. */
-    enum thread_status status;          /* Thread state. */
-    char name[16];                      /* Name (for debugging purposes). */
-    uint8_t *stack;                     /* Saved stack pointer. */
-    int priority;                       /* Priority. */
-    struct list_elem allelem;           /* List element for all threads list. */
-
-    /* Shared between thread.c and synch.c. */
-    struct list_elem elem;              /* List element. */
-      
+struct thread {
+  /* Owned by thread.c. */
+  tid_t tid;                 /* Thread identifier. */
+  enum thread_status status; /* Thread state. */
+  char name[16];             /* Name (for debugging purposes). */
+  uint8_t *stack;            /* Saved stack pointer. */
+  int priority;              /* Priority. */
+  struct list_elem allelem;  /* List element for all threads list. */
+
+  /* Shared between thread.c and synch.c. */
+  struct list_elem elem; /* List element. */
+
 #ifdef USERPROG
-    /* Owned by userprog/process.c. */
-    uint32_t *pagedir;                  /* Page directory. */
+  /* Owned by userprog/process.c. */
+  uint32_t *pagedir; /* Page directory. */
+
+  int status_code;
 #endif
 
-    /* Owned by thread.c. */
-    unsigned magic;                     /* Detects stack overflow. */
-  };
+  /* Owned by thread.c. */
+  unsigned magic; /* Detects stack overflow. */
+};
+
+
 
 /* If false (default), use round-robin scheduler.
    If true, use multi-level feedback queue scheduler.
    Controlled by kernel command-line option "-o mlfqs". */
 extern bool thread_mlfqs;
 
-void thread_init (void);
-void thread_start (void);
+void thread_init(void);
+void thread_start(void);
 
-void thread_tick (void);
-void thread_print_stats (void);
+void thread_tick(void);
+void thread_print_stats(void);
 
-typedef void thread_func (void *aux);
-tid_t thread_create (const char *name, int priority, thread_func *, void *);
+typedef void thread_func(void *aux);
+tid_t thread_create(const char *name, int priority, thread_func *, void *);
 
-void thread_block (void);
-void thread_unblock (struct thread *);
+void thread_block(void);
+void thread_unblock(struct thread *);
 
-struct thread *thread_current (void);
-tid_t thread_tid (void);
-const char *thread_name (void);
+struct thread *thread_current(void);
+tid_t thread_tid(void);
+const char *thread_name(void);
 
-void thread_exit (void) NO_RETURN;
-void thread_yield (void);
+void thread_exit(void) NO_RETURN;
+void thread_yield(void);
 
 /* Performs some operation on thread t, given auxiliary data AUX. */
-typedef void thread_action_func (struct thread *t, void *aux);
-void thread_foreach (thread_action_func *, void *);
+typedef void thread_action_func(struct thread *t, void *aux);
+void thread_foreach(thread_action_func *, void *);
 
-int thread_get_priority (void);
-void thread_set_priority (int);
+int thread_get_priority(void);
+void thread_set_priority(int);
 
-int thread_get_nice (void);
-void thread_set_nice (int);
-int thread_get_recent_cpu (void);
-int thread_get_load_avg (void);
+int thread_get_nice(void);
+void thread_set_nice(int);
+int thread_get_recent_cpu(void);
+int thread_get_load_avg(void);
 
 #endif /* threads/thread.h */
diff --git a/src/userprog/process.c b/src/userprog/process.c
index d51339a4aff8ec7aae340ae87035ef64358853fd..d7fa990873566f8cbdf84cb60e7651695db9f5b2 100644
--- a/src/userprog/process.c
+++ b/src/userprog/process.c
@@ -1,13 +1,4 @@
 #include "userprog/process.h"
-#include <debug.h>
-#include <inttypes.h>
-#include <round.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include "userprog/gdt.h"
-#include "userprog/pagedir.h"
-#include "userprog/tss.h"
 #include "filesys/directory.h"
 #include "filesys/file.h"
 #include "filesys/filesys.h"
@@ -17,56 +8,79 @@
 #include "threads/palloc.h"
 #include "threads/thread.h"
 #include "threads/vaddr.h"
+#include "userprog/gdt.h"
+#include "userprog/pagedir.h"
+#include "userprog/tss.h"
+#include <debug.h>
+#include <inttypes.h>
+#include <round.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
 
 static thread_func start_process NO_RETURN;
-static bool load (const char *cmdline, void (**eip) (void), void **esp);
+static bool load(const char *cmdline, void (**eip)(void), void **esp, int argc,
+                 char **argv);
 
 /* Starts a new thread running a user program loaded from
    FILENAME.  The new thread may be scheduled (and may even exit)
    before process_execute() returns.  Returns the new process's
    thread id, or TID_ERROR if the thread cannot be created. */
-tid_t
-process_execute (const char *file_name) 
-{
+tid_t process_execute(const char *file_name) {
   char *fn_copy;
   tid_t tid;
 
   /* Make a copy of FILE_NAME.
      Otherwise there's a race between the caller and load(). */
-  fn_copy = palloc_get_page (0);
+  fn_copy = palloc_get_page(0);
   if (fn_copy == NULL)
     return TID_ERROR;
-  strlcpy (fn_copy, file_name, PGSIZE);
+  strlcpy(fn_copy, file_name, PGSIZE);
 
   /* Create a new thread to execute FILE_NAME. */
-  tid = thread_create (file_name, PRI_DEFAULT, start_process, fn_copy);
+  tid = thread_create(file_name, PRI_DEFAULT, start_process, fn_copy);
 
   if (tid == TID_ERROR)
-    palloc_free_page (fn_copy); 
+    palloc_free_page(fn_copy);
   return tid;
 }
 
 /* A thread function that loads a user process and starts it
    running. */
-static void
-start_process (void *file_name_)
-{
+static void start_process(void *file_name_) {
   char *file_name = file_name_;
   struct intr_frame if_;
   bool success;
 
+  // Run strtok_r to find correct file_name
+
+  // Declare argument vector and argument count
+  char **argv[255];
+  int argc = 0; // Initialize with 1
+  char *token;
+  char *save_ptr;
+  // Argv[0] is the file name e.g. 'echo' in 'echo x y z'
+  argv[argc++] = strtok_r(file_name, " ", &save_ptr);
+
+  // While loop to fill argument vector with arguments e.g. 'x y z' in 'echo x y
+  // z'
+  while ((token = strtok_r(NULL, " ", &save_ptr)) != NULL) {
+    argv[argc++] = token;
+  }
+
   /* Initialize interrupt frame and load executable. */
-  memset (&if_, 0, sizeof if_);
+  memset(&if_, 0, sizeof if_);
   if_.gs = if_.fs = if_.es = if_.ds = if_.ss = SEL_UDSEG;
   if_.cs = SEL_UCSEG;
   if_.eflags = FLAG_IF | FLAG_MBS;
 
-  success = load (file_name, &if_.eip, &if_.esp);
-  
+  success = load(file_name, &if_.eip, &if_.esp, argc, argv);
+  hex_dump(if_.esp, if_.esp, PHYS_BASE - if_.esp, true);
+
   /* If load failed, quit. */
-  palloc_free_page (file_name);
-  if (!success) 
-    thread_exit ();
+  palloc_free_page(file_name);
+  if (!success)
+    thread_exit();
 
   /* Start the user process by simulating a return from an
      interrupt, implemented by intr_exit (in
@@ -74,8 +88,8 @@ start_process (void *file_name_)
      arguments on the stack in the form of a `struct intr_frame',
      we just point the stack pointer (%esp) to our stack frame
      and jump to it. */
-  asm volatile ("movl %0, %%esp; jmp intr_exit" : : "g" (&if_) : "memory");
-  NOT_REACHED ();
+  asm volatile("movl %0, %%esp; jmp intr_exit" : : "g"(&if_) : "memory");
+  NOT_REACHED();
 }
 
 /* Waits for thread TID to die and returns its exit status.  If
@@ -87,56 +101,50 @@ start_process (void *file_name_)
 
    This function will be implemented in problem 2-2.  For now, it
    does nothing. */
-int
-process_wait (tid_t child_tid UNUSED) 
-{
-    // FIXME: @bgaster --- quick hack to make sure processes execute!
-  for(;;) ;
-    
+int process_wait(tid_t child_tid UNUSED) {
+  // FIXME: @bgaster --- quick hack to make sure processes execute!
+  for (;;)
+    ;
+
   return -1;
 }
 
 /* Free the current process's resources. */
-void
-process_exit (void)
-{
-  struct thread *cur = thread_current ();
+void process_exit(void) {
+  struct thread *cur = thread_current();
   uint32_t *pd;
 
   /* Destroy the current process's page directory and switch back
      to the kernel-only page directory. */
   pd = cur->pagedir;
-  if (pd != NULL) 
-    {
-      /* Correct ordering here is crucial.  We must set
-         cur->pagedir to NULL before switching page directories,
-         so that a timer interrupt can't switch back to the
-         process page directory.  We must activate the base page
-         directory before destroying the process's page
-         directory, or our active page directory will be one
-         that's been freed (and cleared). */
-      cur->pagedir = NULL;
-      pagedir_activate (NULL);
-      pagedir_destroy (pd);
-    }
+  if (pd != NULL) {
+    /* Correct ordering here is crucial.  We must set
+       cur->pagedir to NULL before switching page directories,
+       so that a timer interrupt can't switch back to the
+       process page directory.  We must activate the base page
+       directory before destroying the process's page
+       directory, or our active page directory will be one
+       that's been freed (and cleared). */
+    cur->pagedir = NULL;
+    pagedir_activate(NULL);
+    pagedir_destroy(pd);
+  }
 }
 
 /* Sets up the CPU for running user code in the current
    thread.
    This function is called on every context switch. */
-void
-process_activate (void)
-{
-  struct thread *t = thread_current ();
+void process_activate(void) {
+  struct thread *t = thread_current();
 
   /* Activate thread's page tables. */
-  pagedir_activate (t->pagedir);
+  pagedir_activate(t->pagedir);
 
   /* Set thread's kernel stack for use in processing
      interrupts. */
-  tss_update ();
+  tss_update();
 }
-
+
 /* We load ELF binaries.  The following definitions are taken
    from the ELF specification, [ELF1], more-or-less verbatim.  */
 
@@ -145,75 +153,72 @@ typedef uint32_t Elf32_Word, Elf32_Addr, Elf32_Off;
 typedef uint16_t Elf32_Half;
 
 /* For use with ELF types in printf(). */
-#define PE32Wx PRIx32   /* Print Elf32_Word in hexadecimal. */
-#define PE32Ax PRIx32   /* Print Elf32_Addr in hexadecimal. */
-#define PE32Ox PRIx32   /* Print Elf32_Off in hexadecimal. */
-#define PE32Hx PRIx16   /* Print Elf32_Half in hexadecimal. */
+#define PE32Wx PRIx32 /* Print Elf32_Word in hexadecimal. */
+#define PE32Ax PRIx32 /* Print Elf32_Addr in hexadecimal. */
+#define PE32Ox PRIx32 /* Print Elf32_Off in hexadecimal. */
+#define PE32Hx PRIx16 /* Print Elf32_Half in hexadecimal. */
 
 /* Executable header.  See [ELF1] 1-4 to 1-8.
    This appears at the very beginning of an ELF binary. */
-struct Elf32_Ehdr
-  {
-    unsigned char e_ident[16];
-    Elf32_Half    e_type;
-    Elf32_Half    e_machine;
-    Elf32_Word    e_version;
-    Elf32_Addr    e_entry;
-    Elf32_Off     e_phoff;
-    Elf32_Off     e_shoff;
-    Elf32_Word    e_flags;
-    Elf32_Half    e_ehsize;
-    Elf32_Half    e_phentsize;
-    Elf32_Half    e_phnum;
-    Elf32_Half    e_shentsize;
-    Elf32_Half    e_shnum;
-    Elf32_Half    e_shstrndx;
-  };
+struct Elf32_Ehdr {
+  unsigned char e_ident[16];
+  Elf32_Half e_type;
+  Elf32_Half e_machine;
+  Elf32_Word e_version;
+  Elf32_Addr e_entry;
+  Elf32_Off e_phoff;
+  Elf32_Off e_shoff;
+  Elf32_Word e_flags;
+  Elf32_Half e_ehsize;
+  Elf32_Half e_phentsize;
+  Elf32_Half e_phnum;
+  Elf32_Half e_shentsize;
+  Elf32_Half e_shnum;
+  Elf32_Half e_shstrndx;
+};
 
 /* Program header.  See [ELF1] 2-2 to 2-4.
    There are e_phnum of these, starting at file offset e_phoff
    (see [ELF1] 1-6). */
-struct Elf32_Phdr
-  {
-    Elf32_Word p_type;
-    Elf32_Off  p_offset;
-    Elf32_Addr p_vaddr;
-    Elf32_Addr p_paddr;
-    Elf32_Word p_filesz;
-    Elf32_Word p_memsz;
-    Elf32_Word p_flags;
-    Elf32_Word p_align;
-  };
+struct Elf32_Phdr {
+  Elf32_Word p_type;
+  Elf32_Off p_offset;
+  Elf32_Addr p_vaddr;
+  Elf32_Addr p_paddr;
+  Elf32_Word p_filesz;
+  Elf32_Word p_memsz;
+  Elf32_Word p_flags;
+  Elf32_Word p_align;
+};
 
 /* Values for p_type.  See [ELF1] 2-3. */
-#define PT_NULL    0            /* Ignore. */
-#define PT_LOAD    1            /* Loadable segment. */
-#define PT_DYNAMIC 2            /* Dynamic linking info. */
-#define PT_INTERP  3            /* Name of dynamic loader. */
-#define PT_NOTE    4            /* Auxiliary info. */
-#define PT_SHLIB   5            /* Reserved. */
-#define PT_PHDR    6            /* Program header table. */
-#define PT_STACK   0x6474e551   /* Stack segment. */
+#define PT_NULL 0           /* Ignore. */
+#define PT_LOAD 1           /* Loadable segment. */
+#define PT_DYNAMIC 2        /* Dynamic linking info. */
+#define PT_INTERP 3         /* Name of dynamic loader. */
+#define PT_NOTE 4           /* Auxiliary info. */
+#define PT_SHLIB 5          /* Reserved. */
+#define PT_PHDR 6           /* Program header table. */
+#define PT_STACK 0x6474e551 /* Stack segment. */
 
 /* Flags for p_flags.  See [ELF3] 2-3 and 2-4. */
-#define PF_X 1          /* Executable. */
-#define PF_W 2          /* Writable. */
-#define PF_R 4          /* Readable. */
+#define PF_X 1 /* Executable. */
+#define PF_W 2 /* Writable. */
+#define PF_R 4 /* Readable. */
 
-static bool setup_stack (void **esp);
-static bool validate_segment (const struct Elf32_Phdr *, struct file *);
-static bool load_segment (struct file *file, off_t ofs, uint8_t *upage,
-                          uint32_t read_bytes, uint32_t zero_bytes,
-                          bool writable);
+static bool setup_stack(void **esp, int argc, char **argv);
+static bool validate_segment(const struct Elf32_Phdr *, struct file *);
+static bool load_segment(struct file *file, off_t ofs, uint8_t *upage,
+                         uint32_t read_bytes, uint32_t zero_bytes,
+                         bool writable);
 
 /* Loads an ELF executable from FILE_NAME into the current thread.
    Stores the executable's entry point into *EIP
    and its initial stack pointer into *ESP.
    Returns true if successful, false otherwise. */
-bool
-load (const char *file_name, void (**eip) (void), void **esp) 
-{
-  struct thread *t = thread_current ();
+bool load(const char *file_name, void (**eip)(void), void **esp, int argc,
+          char **argv) {
+  struct thread *t = thread_current();
   struct Elf32_Ehdr ehdr;
   struct file *file = NULL;
   off_t file_ofs;
@@ -221,137 +226,123 @@ load (const char *file_name, void (**eip) (void), void **esp)
   int i;
 
   /* Allocate and activate page directory. */
-  t->pagedir = pagedir_create ();
-  if (t->pagedir == NULL) 
+  t->pagedir = pagedir_create();
+  if (t->pagedir == NULL)
     goto done;
-  process_activate ();
+  process_activate();
 
   /* Open executable file. */
-  file = filesys_open (file_name);
+  file = filesys_open(file_name);
 
-  if (file == NULL) 
-    {
-	printf ("load: %s: open failed\n", file_name);
-      goto done; 
-    }
+  if (file == NULL) {
+    printf("load: %s: open failed\n", file_name);
+    goto done;
+  }
 
   /* Read and verify executable header. */
-  if (file_read (file, &ehdr, sizeof ehdr) != sizeof ehdr
-      || memcmp (ehdr.e_ident, "\177ELF\1\1\1", 7)
-      || ehdr.e_type != 2
-      || ehdr.e_machine != 3
-      || ehdr.e_version != 1
-      || ehdr.e_phentsize != sizeof (struct Elf32_Phdr)
-      || ehdr.e_phnum > 1024) 
-    {
-      printf ("load: %s: error loading executable\n", file_name);
-      goto done; 
-    }
+  if (file_read(file, &ehdr, sizeof ehdr) != sizeof ehdr ||
+      memcmp(ehdr.e_ident, "\177ELF\1\1\1", 7) || ehdr.e_type != 2 ||
+      ehdr.e_machine != 3 || ehdr.e_version != 1 ||
+      ehdr.e_phentsize != sizeof(struct Elf32_Phdr) || ehdr.e_phnum > 1024) {
+    printf("load: %s: error loading executable\n", file_name);
+    goto done;
+  }
 
   /* Read program headers. */
   file_ofs = ehdr.e_phoff;
-  for (i = 0; i < ehdr.e_phnum; i++) 
-    {
-      struct Elf32_Phdr phdr;
-
-      if (file_ofs < 0 || file_ofs > file_length (file))
-        goto done;
-      file_seek (file, file_ofs);
-
-      if (file_read (file, &phdr, sizeof phdr) != sizeof phdr)
-        goto done;
-      file_ofs += sizeof phdr;
-      switch (phdr.p_type) 
-        {
-        case PT_NULL:
-        case PT_NOTE:
-        case PT_PHDR:
-        case PT_STACK:
-        default:
-          /* Ignore this segment. */
-          break;
-        case PT_DYNAMIC:
-        case PT_INTERP:
-        case PT_SHLIB:
-          goto done;
-        case PT_LOAD:
-          if (validate_segment (&phdr, file)) 
-            {
-              bool writable = (phdr.p_flags & PF_W) != 0;
-              uint32_t file_page = phdr.p_offset & ~PGMASK;
-              uint32_t mem_page = phdr.p_vaddr & ~PGMASK;
-              uint32_t page_offset = phdr.p_vaddr & PGMASK;
-              uint32_t read_bytes, zero_bytes;
-              if (phdr.p_filesz > 0)
-                {
-                  /* Normal segment.
-                     Read initial part from disk and zero the rest. */
-                  read_bytes = page_offset + phdr.p_filesz;
-                  zero_bytes = (ROUND_UP (page_offset + phdr.p_memsz, PGSIZE)
-                                - read_bytes);
-                }
-              else 
-                {
-                  /* Entirely zero.
-                     Don't read anything from disk. */
-                  read_bytes = 0;
-                  zero_bytes = ROUND_UP (page_offset + phdr.p_memsz, PGSIZE);
-                }
-              if (!load_segment (file, file_page, (void *) mem_page,
-                                 read_bytes, zero_bytes, writable))
-                goto done;
-            }
-          else
-            goto done;
-          break;
+  for (i = 0; i < ehdr.e_phnum; i++) {
+    struct Elf32_Phdr phdr;
+
+    if (file_ofs < 0 || file_ofs > file_length(file))
+      goto done;
+    file_seek(file, file_ofs);
+
+    if (file_read(file, &phdr, sizeof phdr) != sizeof phdr)
+      goto done;
+    file_ofs += sizeof phdr;
+    switch (phdr.p_type) {
+    case PT_NULL:
+    case PT_NOTE:
+    case PT_PHDR:
+    case PT_STACK:
+    default:
+      /* Ignore this segment. */
+      break;
+    case PT_DYNAMIC:
+    case PT_INTERP:
+    case PT_SHLIB:
+      goto done;
+    case PT_LOAD:
+      if (validate_segment(&phdr, file)) {
+        bool writable = (phdr.p_flags & PF_W) != 0;
+        uint32_t file_page = phdr.p_offset & ~PGMASK;
+        uint32_t mem_page = phdr.p_vaddr & ~PGMASK;
+        uint32_t page_offset = phdr.p_vaddr & PGMASK;
+        uint32_t read_bytes, zero_bytes;
+        if (phdr.p_filesz > 0) {
+          /* Normal segment.
+             Read initial part from disk and zero the rest. */
+          read_bytes = page_offset + phdr.p_filesz;
+          zero_bytes =
+              (ROUND_UP(page_offset + phdr.p_memsz, PGSIZE) - read_bytes);
+        } else {
+          /* Entirely zero.
+             Don't read anything from disk. */
+          read_bytes = 0;
+          zero_bytes = ROUND_UP(page_offset + phdr.p_memsz, PGSIZE);
         }
+        if (!load_segment(file, file_page, (void *)mem_page, read_bytes,
+                          zero_bytes, writable))
+          goto done;
+      } else
+        goto done;
+      break;
     }
+  }
 
   /* Set up stack. */
-  if (!setup_stack (esp))
+  if (!setup_stack(esp, argc, argv))
     goto done;
 
   /* Start address. */
-  *eip = (void (*) (void)) ehdr.e_entry;
+  *eip = (void (*)(void))ehdr.e_entry;
 
   success = true;
 
- done:
+done:
   /* We arrive here whether the load is successful or not. */
-  file_close (file);
+  file_close(file);
   return success;
 }
-
+
 /* load() helpers. */
 
-static bool install_page (void *upage, void *kpage, bool writable);
+static bool install_page(void *upage, void *kpage, bool writable);
 
 /* Checks whether PHDR describes a valid, loadable segment in
    FILE and returns true if so, false otherwise. */
-static bool
-validate_segment (const struct Elf32_Phdr *phdr, struct file *file) 
-{
+static bool validate_segment(const struct Elf32_Phdr *phdr, struct file *file) {
   /* p_offset and p_vaddr must have the same page offset. */
-  if ((phdr->p_offset & PGMASK) != (phdr->p_vaddr & PGMASK)) 
-    return false; 
+  if ((phdr->p_offset & PGMASK) != (phdr->p_vaddr & PGMASK))
+    return false;
 
   /* p_offset must point within FILE. */
-  if (phdr->p_offset > (Elf32_Off) file_length (file)) 
+  if (phdr->p_offset > (Elf32_Off)file_length(file))
     return false;
 
   /* p_memsz must be at least as big as p_filesz. */
-  if (phdr->p_memsz < phdr->p_filesz) 
-    return false; 
+  if (phdr->p_memsz < phdr->p_filesz)
+    return false;
 
   /* The segment must not be empty. */
   if (phdr->p_memsz == 0)
     return false;
-  
+
   /* The virtual memory region must both start and end within the
      user address space range. */
-  if (!is_user_vaddr ((void *) phdr->p_vaddr))
+  if (!is_user_vaddr((void *)phdr->p_vaddr))
     return false;
-  if (!is_user_vaddr ((void *) (phdr->p_vaddr + phdr->p_memsz)))
+  if (!is_user_vaddr((void *)(phdr->p_vaddr + phdr->p_memsz)))
     return false;
 
   /* The region cannot "wrap around" across the kernel virtual
@@ -385,68 +376,105 @@ validate_segment (const struct Elf32_Phdr *phdr, struct file *file)
 
    Return true if successful, false if a memory allocation error
    or disk read error occurs. */
-static bool
-load_segment (struct file *file, off_t ofs, uint8_t *upage,
-              uint32_t read_bytes, uint32_t zero_bytes, bool writable) 
-{
-  ASSERT ((read_bytes + zero_bytes) % PGSIZE == 0);
-  ASSERT (pg_ofs (upage) == 0);
-  ASSERT (ofs % PGSIZE == 0);
-
-  file_seek (file, ofs);
-  while (read_bytes > 0 || zero_bytes > 0) 
-    {
-      /* Calculate how to fill this page.
-         We will read PAGE_READ_BYTES bytes from FILE
-         and zero the final PAGE_ZERO_BYTES bytes. */
-      size_t page_read_bytes = read_bytes < PGSIZE ? read_bytes : PGSIZE;
-      size_t page_zero_bytes = PGSIZE - page_read_bytes;
-
-      /* Get a page of memory. */
-      uint8_t *kpage = palloc_get_page (PAL_USER);
-      if (kpage == NULL)
-        return false;
-
-      /* Load this page. */
-      if (file_read (file, kpage, page_read_bytes) != (int) page_read_bytes)
-        {
-          palloc_free_page (kpage);
-          return false; 
-        }
-      memset (kpage + page_read_bytes, 0, page_zero_bytes);
-
-      /* Add the page to the process's address space. */
-      if (!install_page (upage, kpage, writable)) 
-        {
-          palloc_free_page (kpage);
-          return false; 
-        }
+static bool load_segment(struct file *file, off_t ofs, uint8_t *upage,
+                         uint32_t read_bytes, uint32_t zero_bytes,
+                         bool writable) {
+  ASSERT((read_bytes + zero_bytes) % PGSIZE == 0);
+  ASSERT(pg_ofs(upage) == 0);
+  ASSERT(ofs % PGSIZE == 0);
+
+  file_seek(file, ofs);
+  while (read_bytes > 0 || zero_bytes > 0) {
+    /* Calculate how to fill this page.
+       We will read PAGE_READ_BYTES bytes from FILE
+       and zero the final PAGE_ZERO_BYTES bytes. */
+    size_t page_read_bytes = read_bytes < PGSIZE ? read_bytes : PGSIZE;
+    size_t page_zero_bytes = PGSIZE - page_read_bytes;
+
+    /* Get a page of memory. */
+    uint8_t *kpage = palloc_get_page(PAL_USER);
+    if (kpage == NULL)
+      return false;
+
+    /* Load this page. */
+    if (file_read(file, kpage, page_read_bytes) != (int)page_read_bytes) {
+      palloc_free_page(kpage);
+      return false;
+    }
+    memset(kpage + page_read_bytes, 0, page_zero_bytes);
 
-      /* Advance. */
-      read_bytes -= page_read_bytes;
-      zero_bytes -= page_zero_bytes;
-      upage += PGSIZE;
+    /* Add the page to the process's address space. */
+    if (!install_page(upage, kpage, writable)) {
+      palloc_free_page(kpage);
+      return false;
     }
+
+    /* Advance. */
+    read_bytes -= page_read_bytes;
+    zero_bytes -= page_zero_bytes;
+    upage += PGSIZE;
+  }
   return true;
 }
 
 /* Create a minimal stack by mapping a zeroed page at the top of
    user virtual memory. */
-static bool
-setup_stack (void **esp) 
-{
+static bool setup_stack(void **esp, int argc, char **argv) {
   uint8_t *kpage;
   bool success = false;
 
-  kpage = palloc_get_page (PAL_USER | PAL_ZERO);
-  if (kpage != NULL) 
-    {
-      success = install_page (((uint8_t *) PHYS_BASE) - PGSIZE, kpage, true);
-      if (success) {
-        *esp = PHYS_BASE;
-      } else
-        palloc_free_page (kpage);
-    }
+  kpage = palloc_get_page(PAL_USER | PAL_ZERO);
+  if (kpage != NULL) {
+    success = install_page(((uint8_t *)PHYS_BASE) - PGSIZE, kpage, true);
+    if (success) {
+      *esp = PHYS_BASE; // -12 "hack" removed as argument passing implemented
+      int i = argc;
+      //***************************
+      uint32_t *arr[argc]; // Pointer to arguments in the stack
+
+      while (--i >= 0) {
+        *esp = *esp - (strlen(argv[i]) + 1); // Add + 1 for null terminator
+        arr[i] = (uint32_t *)*esp;
+        // memcpy (destination, source, size);
+        memcpy(*esp, argv[i], strlen(argv[i]) + 1);
+      }
+
+      // Word alignment using modulus
+      int alignment = (uint32_t)*esp % 4;
+      // If alignment needed move esp
+      if (alignment > 0) {
+        *esp = *esp - alignment;
+        // memset(* to the block of memory to fill, value to be set, number of
+        // bytes to be set)
+        memset(*esp, 0, alignment);
+      }
+
+      // In C the size of each constant character e.g. 'x' is equal to 4
+      // esp - 4 move position in the stack
+      *esp = *esp - 4;
+      (*(uint8_t *)(*esp)) = 0; // Add a sentinel for termination
+      i = argc;
+
+      // Address pointing to each argument written to the stack
+      while (--i >= 0) {
+        *esp = *esp - 4;
+        (*(uint32_t **)(*esp)) = arr[i];
+      }
+
+      *esp = *esp - 4;
+      // Write address of argv[0]
+      (*(uintptr_t **)(*esp)) = (*esp + 4);
+      *esp = *esp - 4;
+      // Write the number of arguments to the stack
+      *(int *)(*esp) = argc;
+      *esp = *esp - 4;
+      // Write 0 for return address
+      (*(int *)(*esp)) = 0;
+
+    } else
+      palloc_free_page(kpage);
+  }
+
   return success;
 }
 
@@ -459,15 +487,13 @@ setup_stack (void **esp)
    with palloc_get_page().
    Returns true on success, false if UPAGE is already mapped or
    if memory allocation fails. */
-static bool
-install_page (void *upage, void *kpage, bool writable)
-{
-  struct thread *t = thread_current ();
+static bool install_page(void *upage, void *kpage, bool writable) {
+  struct thread *t = thread_current();
 
   /* Verify that there's not already a page at that virtual
      address, then map our page there. */
-  return (pagedir_get_page (t->pagedir, upage) == NULL
-          && pagedir_set_page (t->pagedir, upage, kpage, writable));
+  return (pagedir_get_page(t->pagedir, upage) == NULL &&
+          pagedir_set_page(t->pagedir, upage, kpage, writable));
 }
 
 //--------------------------------------------------------------------
diff --git a/src/userprog/syscall.c b/src/userprog/syscall.c
index 04635159d30520fa11296dc922e622f2ad2553d5..175241685cb7ba8e78ea77616de584e7ec48ac44 100644
--- a/src/userprog/syscall.c
+++ b/src/userprog/syscall.c
@@ -1,21 +1,66 @@
 #include "userprog/syscall.h"
-#include <stdio.h>
-#include <syscall-nr.h>
+#include "filesys/filesys.h"
+#include "lib/kernel/list.h"
 #include "threads/interrupt.h"
+#include "threads/malloc.h"
 #include "threads/thread.h"
+#include "userprog/process.h"
+#include <stdio.h>
+#include <string.h>
+#include <syscall-nr.h>
 
-static void syscall_handler (struct intr_frame *);
+static void syscall_handler(struct intr_frame *);
+bool create(const char *file, unsigned initial_size);
+tid_t exec(const char *cmd_line);
 
-void
-syscall_init (void) 
-{
-  intr_register_int (0x30, 3, INTR_ON, syscall_handler, "syscall");
+
+void syscall_init(void) {
+  intr_register_int(0x30, 3, INTR_ON, syscall_handler, "syscall");
 }
 
+static void syscall_handler(struct intr_frame *f) {
+
+  // Get the syscall number from the stack
+  int syscall_num = *(int *)f->esp;
+
+  switch (syscall_num) {
+  
+  case SYS_REMOVE:
+    // Print current syscall number
+    printf("Syscall_handler() - %d!\n", syscall_num);
+    filesys_remove(*(char **)(f->esp + 4));
+    printf(*(char **)(f->esp + 4));
+    break;
 
-static void
-syscall_handler (struct intr_frame *f UNUSED)
-{
-  printf ("system call!\n");
-  thread_exit ();
+  case SYS_EXEC:
+    // Print current syscall number
+    printf("Syscall_handler() - %d!\n", syscall_num);
+    printf("SYS_CALL : EXEC \n");
+    exec(*(char **)(f->esp + 4));
+    break;
+
+  case SYS_CREATE:
+    // Print current syscall number
+    printf("Syscall_handler() - %d!\n", syscall_num);
+    create(*(int *)(f->esp + 4), (unsigned)*(int *)(f->esp + 8));
+    break;
+
+  default:
+    thread_exit();
+  }
+}
+
+
+tid_t exec(const char *cmd_line) {
+  // showing the arg/process in the command line
+  printf(" \ncmd_line : '%s'\n", cmd_line);
+  // executing whatever in cmd_line then return to the process id
+  tid_t pid = process_execute(cmd_line);
+  return pid;
 }
+
+bool create(const char *file, unsigned initial_size) {
+  // This creates a new file but doesn't open it
+  printf("File named '%s' created\n", file);
+  return filesys_create(file, initial_size);
+}
\ No newline at end of file