diff --git a/Makefile b/Makefile
index 059434fc1c148f8f0edf6ac05ad8a6569d7bbb25..a476cf4179a27c449f5a31bfcae2c9c27d09cf36 100644
--- a/Makefile
+++ b/Makefile
@@ -91,11 +91,19 @@ ls : ls.o $(ULIB)
 	$(LD) -N -e main -Ttext 0 -o ls ls.o $(ULIB)
 	$(OBJDUMP) -S ls > ls.asm
 
+mkdir : mkdir.o $(ULIB)
+	$(LD) -N -e main -Ttext 0 -o mkdir mkdir.o $(ULIB)
+	$(OBJDUMP) -S mkdir > mkdir.asm
+
+rm : rm.o $(ULIB)
+	$(LD) -N -e main -Ttext 0 -o rm rm.o $(ULIB)
+	$(OBJDUMP) -S rm > rm.asm
+
 mkfs : mkfs.c fs.h
 	cc -o mkfs mkfs.c
 
-fs.img : mkfs userfs usertests echo cat README init sh ls
-	./mkfs fs.img userfs usertests echo cat README init sh ls
+fs.img : mkfs userfs usertests echo cat readme init sh ls mkdir rm
+	./mkfs fs.img userfs usertests echo cat readme init sh ls mkdir rm
 
 -include *.d
 
diff --git a/ls.c b/ls.c
index 9731f6f13554da544cb55cf2714515f676d5b395..607a857d15abfae19158d6bdbe6071c6d6b110f7 100644
--- a/ls.c
+++ b/ls.c
@@ -13,6 +13,7 @@ main(int argc, char *argv[])
   int fd;
   uint off;
   uint sz;
+  int i;
 
   if(argc > 1){
     puts("Usage: ls\n");
@@ -42,8 +43,13 @@ main(int argc, char *argv[])
 	printf(1, "stat: failed\n");
 	break;
       }
-      printf(1, "%s t %d ino %d sz %d\n", dirent.name, st.st_type, 
-	     dirent.inum, st.st_size);
+      for (i = 0; i < DIRSIZ; i++) {
+	if (dirent.name[i] != '\0')
+	  printf(1, "%c", dirent.name[i]);
+	else
+	  printf(1, " ");
+      }
+      printf(1, "%d %d %d\n", st.st_type, dirent.inum, st.st_size);
     }
   }
   close(fd);
diff --git a/mkdir.c b/mkdir.c
new file mode 100644
index 0000000000000000000000000000000000000000..1e208325ca113cee034c55204b5ccbd1a181f8c7
--- /dev/null
+++ b/mkdir.c
@@ -0,0 +1,22 @@
+#include "types.h"
+#include "stat.h"
+#include "user.h"
+
+main(int argc, char *argv[])
+{
+  int i;
+
+  if(argc < 2){
+    printf(2, "Usage: mkdir files...\n");
+    exit();
+  }
+
+  for(i = 1; i < argc; i++){
+    if (mkdir(argv[i]) < 0) {
+      printf(2, "mkdir: %s failed to create\n", argv[i]);
+      break;
+    }
+  }
+
+  exit();
+}
diff --git a/printf.c b/printf.c
index 0d42236c1625dce89c0b3f9446b7f1bb08088bb6..10e743ae3bfe1f2b2309d4b3ee612308441cd75f 100644
--- a/printf.c
+++ b/printf.c
@@ -1,5 +1,6 @@
-#include "user.h"
 #include "types.h"
+#include "stat.h"
+#include "user.h"
 
 static void
 putc(int fd, char c)
@@ -63,6 +64,9 @@ printf(int fd, char *fmt, ...)
           putc(fd, *s);
           s++;
         }
+      } else if(c == 'c'){
+	putc(fd, *ap);
+	ap++;
       } else if(c == '%'){
         putc(fd, c);
       } else {
diff --git a/readme b/readme
new file mode 100644
index 0000000000000000000000000000000000000000..ce0bbfb2db79dced53ef630acc88dea65325da4b
--- /dev/null
+++ b/readme
@@ -0,0 +1 @@
+This is the content of file README.
diff --git a/rm.c b/rm.c
new file mode 100644
index 0000000000000000000000000000000000000000..661e88d8319ee236eb91c41dae89ac99a83e41db
--- /dev/null
+++ b/rm.c
@@ -0,0 +1,22 @@
+#include "types.h"
+#include "stat.h"
+#include "user.h"
+
+main(int argc, char *argv[])
+{
+  int i;
+
+  if(argc < 2){
+    printf(2, "Usage: rm files...\n");
+    exit();
+  }
+
+  for(i = 1; i < argc; i++){
+    if (unlink(argv[i]) < 0) {
+      printf(2, "mkdir: %s failed to create\n", argv[i]);
+      break;
+    }
+  }
+
+  exit();
+}
diff --git a/sh.c b/sh.c
index 9d4a308957c2cfaca0bcc35a46dd62a34a9512d3..e2b8959a8269951b50d8046a8c72765534b54c36 100644
--- a/sh.c
+++ b/sh.c
@@ -1,9 +1,11 @@
-#include "user.h"
 #include "types.h"
+#include "stat.h"
+#include "user.h"
 #include "fs.h"
 #include "fcntl.h"
 
 char *args[100];
+void parse(char buf[]);
 
 int
 main(void)
@@ -18,8 +20,7 @@ main(void)
       continue;
     pid = fork();
     if(pid == 0){
-      args[0] = buf;
-      args[1] = 0;
+      parse(buf);
       exec(buf, args);
       printf(1, "%s: not found\n", buf);
       exit();
@@ -28,3 +29,21 @@ main(void)
       wait();
   }
 }
+
+void
+parse(char buf[])
+{
+  int j = 1;
+  int i;
+  args[0] = buf;
+  for (i = 0; buf[i] != '\0'; i++) {
+    if (buf[i] == ' ') {
+      buf[i] = '\0';
+      args[j++] = buf + i+1;
+      if (j >= 100) {
+	printf(2, "too many args\n");
+	exit();
+      }
+    }
+  }
+}
diff --git a/userfs.c b/userfs.c
index 5e46814b1e3e67940b9b7ff045e4c94fb6f1adcc..5d0c8593c3cf4623c92b651ff2bdbca611de4c3c 100644
--- a/userfs.c
+++ b/userfs.c
@@ -9,7 +9,7 @@
 char buf[2000];
 char name[3];
 char *echo_args[] = { "echo", "hello", "goodbye", 0 };
-char *cat_args[] = { "cat", "README", 0 };
+char *cat_args[] = { "cat", "readme", 0 };
 
 int
 main(void)