From 17a856577f9db766b8ef7099d0575d378dff5dd1 Mon Sep 17 00:00:00 2001
From: rtm <rtm>
Date: Fri, 11 Aug 2006 13:55:18 +0000
Subject: [PATCH] init creates console, opens 0/1/2, runs sh sh accepts
 0-argument commands (like userfs) reads from console

---
 Makefile  | 18 +++++++++++++-----
 console.c | 32 +++++++++++++++++++++++++++++---
 defs.h    |  5 +++--
 dev.h     |  4 ++--
 fs.c      | 11 ++++++-----
 init.c    | 32 ++++++++++++++++++++++++++++++++
 main.c    |  8 ++++----
 sh.c      | 31 +++++++++++++++++++++++++++++++
 syscall.c | 19 +++++++++++++------
 ulib.c    | 39 ++++++++++++++++++++++++++++-----------
 user.h    |  5 +++--
 11 files changed, 164 insertions(+), 40 deletions(-)
 create mode 100644 init.c
 create mode 100644 sh.c

diff --git a/Makefile b/Makefile
index 3f5a3ce..943f719 100644
--- a/Makefile
+++ b/Makefile
@@ -46,12 +46,12 @@ bootblock : bootasm.S bootmain.c
 	$(OBJCOPY) -S -O binary bootblock.o bootblock
 	./sign.pl bootblock
 
-kernel : $(OBJS) bootother.S user1 usertests userfs
+kernel : $(OBJS) bootother.S userfs init
 	$(CC) -nostdinc -I. -c bootother.S
 	$(LD) -N -e start -Ttext 0x7000 -o bootother.out bootother.o
 	$(OBJCOPY) -S -O binary bootother.out bootother
 	$(OBJDUMP) -S bootother.o > bootother.asm
-	$(LD) -Ttext 0x100000 -e main0 -o kernel $(OBJS) -b binary bootother user1 usertests userfs
+	$(LD) -Ttext 0x100000 -e main0 -o kernel $(OBJS) -b binary bootother userfs init
 	$(OBJDUMP) -S kernel > kernel.asm
 
 vectors.S : vectors.pl
@@ -79,15 +79,23 @@ userfs : userfs.o $(ULIB)
 	$(LD) -N -e main -Ttext 0 -o userfs userfs.o $(ULIB)
 	$(OBJDUMP) -S userfs > userfs.asm
 
+init : init.o $(ULIB)
+	$(LD) -N -e main -Ttext 0 -o init init.o $(ULIB)
+	$(OBJDUMP) -S init > init.asm
+
+sh : sh.o $(ULIB)
+	$(LD) -N -e main -Ttext 0 -o sh sh.o $(ULIB)
+	$(OBJDUMP) -S sh > sh.asm
+
 mkfs : mkfs.c fs.h
 	cc -o mkfs mkfs.c
 
-fs.img : mkfs usertests echo cat README
-	./mkfs fs.img usertests echo cat README
+fs.img : mkfs userfs usertests echo cat README init sh
+	./mkfs fs.img userfs usertests echo cat README init sh
 
 -include *.d
 
 clean : 
 	rm -f *.o *.d *.asm vectors.S parport.out \
 		bootblock kernel xv6.img user1 userfs usertests \
-		fs.img mkfs echo
+		fs.img mkfs echo init
diff --git a/console.c b/console.c
index 5fc1920..a91029f 100644
--- a/console.c
+++ b/console.c
@@ -169,15 +169,14 @@ panic(char *s)
 }
 
 int
-console_write (int minor, void *buf, int n)
+console_write (int minor, char *buf, int n)
 {
   int i;
-  uchar *b = buf;
 
   acquire(&console_lock);
 
   for (i = 0; i < n; i++) {
-    cons_putc((int) b[i]);
+    cons_putc(buf[i] & 0xff);
   }
 
   release(&console_lock);
@@ -349,6 +348,7 @@ kbd_intr()
     kbd_buf[kbd_w++] = c;
     if(kbd_w >= KBD_BUF)
       kbd_w = 0;
+    wakeup(&kbd_r);
   } else {
     cprintf("kbd overflow\n");
   }
@@ -356,6 +356,31 @@ kbd_intr()
   release(&kbd_lock);
 }
 
+int
+console_read(int minor, char *dst, int n)
+{
+  uint target = n;
+
+  acquire(&kbd_lock);
+
+  while(kbd_w == kbd_r)
+    sleep(&kbd_r, &kbd_lock);
+
+  while(n > 0 && kbd_w != kbd_r){
+    *dst = kbd_buf[kbd_r];
+    cons_putc(*dst & 0xff);
+    dst++;
+    --n;
+    kbd_r++;
+    if(kbd_r >= KBD_BUF)
+      kbd_r = 0;
+  }
+
+  release(&kbd_lock);
+
+  return target - n;
+}
+
 void
 console_init()
 {
@@ -363,6 +388,7 @@ console_init()
   initlock(&kbd_lock, "kbd");
 
   devsw[CONSOLE].d_write = console_write;
+  devsw[CONSOLE].d_read = console_read;
 
   ioapic_enable (IRQ_KBD, 1);
 
diff --git a/defs.h b/defs.h
index 0b94488..5e3c1e4 100644
--- a/defs.h
+++ b/defs.h
@@ -115,6 +115,7 @@ void iunlock(struct inode *ip);
 void idecref(struct inode *ip);
 void iput(struct inode *ip);
 struct inode * namei(char *path);
-int readi(struct inode *ip, void *xdst, uint off, uint n);
-int writei(struct inode *ip, void *addr, uint off, uint n);
+int readi(struct inode *ip, char *xdst, uint off, uint n);
+int writei(struct inode *ip, char *addr, uint off, uint n);
 struct inode *mknod(struct inode *, char *, short, short, short);
+void iupdate (struct inode *ip);
diff --git a/dev.h b/dev.h
index 48c6b9a..686dec8 100644
--- a/dev.h
+++ b/dev.h
@@ -1,7 +1,7 @@
 struct devsw {
   int (*d_open)(char *, int);
-  int (*d_read)(int, void *, int);
-  int (*d_write)(int, void *, int);
+  int (*d_read)(int, char *, int);
+  int (*d_write)(int, char *, int);
   int (*d_close)(int);
 };
 
diff --git a/fs.c b/fs.c
index b298d7f..cbf417e 100644
--- a/fs.c
+++ b/fs.c
@@ -101,6 +101,7 @@ iget(uint dev, uint inum)
         goto loop;
       }
       ip->count++;
+      ip->busy = 1;
       release(&inode_table_lock);
       return ip;
     }
@@ -269,16 +270,15 @@ bmap(struct inode *ip, uint bn)
 #define min(a, b) ((a) < (b) ? (a) : (b))
 
 int
-readi(struct inode *ip, void *xdst, uint off, uint n)
+readi(struct inode *ip, char *dst, uint off, uint n)
 {
-  char *dst = (char *) xdst;
   uint target = n, n1;
   struct buf *bp;
 
   if (ip->type == T_DEV) {
     if (ip->major < 0 || ip->major >= NDEV || !devsw[ip->major].d_read)
       return -1;
-    return devsw[ip->major].d_read (ip->minor, xdst, n);
+    return devsw[ip->major].d_read (ip->minor, dst, n);
   }
 
   while(n > 0 && off < ip->size){
@@ -298,7 +298,7 @@ readi(struct inode *ip, void *xdst, uint off, uint n)
 #define MIN(a, b) ((a < b) ? a : b)
 
 int
-writei(struct inode *ip, void *addr, uint off, uint n)
+writei(struct inode *ip, char *addr, uint off, uint n)
 {
   if (ip->type == T_DEV) {
     if (ip->major < 0 || ip->major >= NDEV || !devsw[ip->major].d_write)
@@ -404,7 +404,8 @@ mknod(struct inode *dp, char *cp, short type, short major, short minor)
   int i;
   struct buf *bp = 0;
 
-  cprintf("mknod: %s %d %d %d\n", cp, type, major, minor);
+  cprintf("mknod: dir %d %s %d %d %d\n",
+          dp->inum, cp, type, major, minor);
 
   ip = ialloc(dp->dev, type);
   if (ip == 0) return 0;
diff --git a/init.c b/init.c
new file mode 100644
index 0000000..dcd0fda
--- /dev/null
+++ b/init.c
@@ -0,0 +1,32 @@
+#include "user.h"
+#include "types.h"
+#include "fs.h"
+#include "fcntl.h"
+
+char *sh_args[] = { "sh", 0 };
+
+int
+main(void)
+{
+  int pid;
+  
+  if(open("console", 0) < 0){
+    mknod("console", T_DEV, 1, 1);
+    open("console", 0);
+  }
+  open("console", 1);
+  open("console", 1);
+
+  write(1, "init...\n", 8);
+
+  while(1){
+    write(1, "running sh...\n", 14);
+    pid = fork();
+    if(pid == 0){
+      exec("sh", sh_args);
+      exit();
+    }
+    if(pid > 0)
+      wait();
+  }
+}
diff --git a/main.c b/main.c
index a7209b6..c164c48 100644
--- a/main.c
+++ b/main.c
@@ -11,9 +11,8 @@
 #include "spinlock.h"
 
 extern char edata[], end[];
-extern uchar _binary_user1_start[], _binary_user1_size[];
-extern uchar _binary_usertests_start[], _binary_usertests_size[];
 extern uchar _binary_userfs_start[], _binary_userfs_size[];
+extern uchar _binary_init_start[], _binary_init_size[];
 
 // CPU 0 starts running C code here.
 // This is called main0 not main so that it can have
@@ -96,9 +95,10 @@ main0(void)
   p = copyproc(&proc[0]);
   
   //load_icode(p, _binary_usertests_start, (uint) _binary_usertests_size);
-  load_icode(p, _binary_userfs_start, (uint) _binary_userfs_size);
+  //load_icode(p, _binary_userfs_start, (uint) _binary_userfs_size);
+  load_icode(p, _binary_init_start, (uint) _binary_init_size);
   p->state = RUNNABLE;
-  cprintf("loaded userfs\n");
+  cprintf("loaded init\n");
 
   scheduler();
 }
diff --git a/sh.c b/sh.c
new file mode 100644
index 0000000..e9ed2d9
--- /dev/null
+++ b/sh.c
@@ -0,0 +1,31 @@
+#include "user.h"
+#include "types.h"
+#include "fs.h"
+#include "fcntl.h"
+
+char *args[100];
+
+int
+main(void)
+{
+  char buf[128];
+  int pid;
+
+  while(1){
+    write(1, "$ ", 2);
+    gets(buf, sizeof(buf));
+    if(buf[0] == '\0')
+      continue;
+    pid = fork();
+    if(pid == 0){
+      args[0] = buf;
+      args[1] = 0;
+      exec(buf, args);
+      write(1, buf, strlen(buf));
+      write(1, ": not found\n", 12);
+      exit();
+    }
+    if(pid > 0)
+      wait();
+  }
+}
diff --git a/syscall.c b/syscall.c
index c53c447..6ba185e 100644
--- a/syscall.c
+++ b/syscall.c
@@ -319,14 +319,19 @@ sys_mknod(void)
     return -1;
 
   dp = iget(rootdev, 1);    // XXX should parse name
-  if (dp->type != T_DIR) 
+  if (dp->type != T_DIR) {
+    iput(dp);
     return -1;
+  }
+
   nip = mknod (dp, cp->mem + arg0, (short) arg1, (short) arg2, 
 		   (short) arg3);
 
-  if (nip == 0) return -1;
-  iput(nip);
   iput(dp);
+
+  if (nip == 0) return -1;
+
+  iput(nip);
   
   return 0;
 }
@@ -376,7 +381,7 @@ sys_exec(void)
   if(ip == 0)
     return -1;
 
-  if(readi(ip, &elf, 0, sizeof(elf)) < sizeof(elf))
+  if(readi(ip, (char*)&elf, 0, sizeof(elf)) < sizeof(elf))
     goto bad;
 
   if(elf.magic != ELF_MAGIC)
@@ -384,7 +389,8 @@ sys_exec(void)
 
   sz = 0;
   for(i = 0; i < elf.phnum; i++){
-    if(readi(ip, &ph, elf.phoff + i * sizeof(ph), sizeof(ph)) != sizeof(ph))
+    if(readi(ip, (char*)&ph, elf.phoff + i * sizeof(ph),
+             sizeof(ph)) != sizeof(ph))
       goto bad;
     if(ph.type != ELF_PROG_LOAD)
       continue;
@@ -450,7 +456,8 @@ sys_exec(void)
   mem = 0;
 
   for(i = 0; i < elf.phnum; i++){
-    if(readi(ip, &ph, elf.phoff + i * sizeof(ph), sizeof(ph)) != sizeof(ph))
+    if(readi(ip, (char*)&ph, elf.phoff + i * sizeof(ph),
+             sizeof(ph)) != sizeof(ph))
       goto bad2;
     if(ph.type != ELF_PROG_LOAD)
       continue;
diff --git a/ulib.c b/ulib.c
index d7e8934..ccb9fd6 100644
--- a/ulib.c
+++ b/ulib.c
@@ -3,17 +3,7 @@
 int
 puts(char *s)
 {
-  return cons_puts(s);
-}
-
-int
-puts1(char *s)
-{
-  int i;
-
-  for(i = 0; s[i]; i++)
-    cons_putc(s[i]);
-  return i;
+  return write(1, s, strlen(s));
 }
 
 char*
@@ -26,3 +16,30 @@ strcpy(char *s, char *t)
 		;
 	return os;
 }
+
+unsigned int
+strlen(char *s)
+{
+  int n = 0;
+  for(n = 0; s[n]; n++)
+    ;
+  return n;
+}
+
+char *
+gets(char *buf, int max)
+{
+  int i = 0, cc;
+  char c;
+  
+  while(i+1 < max){
+    cc = read(0, &c, 1);
+    if(cc < 1)
+      break;
+    if(c == '\n' || c == '\r')
+      break;
+    buf[i++] = c;
+  }
+  buf[i] = '\0';
+  return buf;
+}
diff --git a/user.h b/user.h
index 351b970..8154aeb 100644
--- a/user.h
+++ b/user.h
@@ -14,8 +14,9 @@ int exec(char *, char **);
 int open(char *, int);
 int mknod (char*,short,short,short);
 int unlink (char*);
+
 int puts(char*);
-int puts1(char*);
 char* strcpy(char*, char*);
 void printf(int fd, char *fmt, ...);
-
+char *gets(char *, int max);
+unsigned int strlen(char *);