i/o redirection in sh
better parsing of sh commands (copied from jos sh) cat: read from 1 if no args sbrk system call, but untested getpid system call moved locks in keyboard intr, but why do we get intr w. null characters from keyboard?
This commit is contained in:
		
							parent
							
								
									f18ab5c04e
								
							
						
					
					
						commit
						8b58e81077
					
				
					 15 changed files with 433 additions and 74 deletions
				
			
		
							
								
								
									
										8
									
								
								Notes
									
										
									
									
									
								
							
							
						
						
									
										8
									
								
								Notes
									
										
									
									
									
								
							| 
						 | 
					@ -131,3 +131,11 @@ maybe get rid of per-proc gdt and ts
 | 
				
			||||||
  one per cpu
 | 
					  one per cpu
 | 
				
			||||||
  refresh it when needed
 | 
					  refresh it when needed
 | 
				
			||||||
  setupsegs(proc *)
 | 
					  setupsegs(proc *)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					why do we get 0 characters from keyboard?
 | 
				
			||||||
 | 
					are the locks in the right place in keyboardintr?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sh: support pipes?  leave it for the class?
 | 
				
			||||||
 | 
					sh: dynamic memory allocation?
 | 
				
			||||||
 | 
					sh: should sh support ; () &  --- need malloc
 | 
				
			||||||
 | 
					sh: stop stdin on ctrl-d (for cat > y)
 | 
				
			||||||
							
								
								
									
										37
									
								
								cat.c
									
										
									
									
									
								
							
							
						
						
									
										37
									
								
								cat.c
									
										
									
									
									
								
							| 
						 | 
					@ -1,17 +1,32 @@
 | 
				
			||||||
 | 
					#include "types.h"
 | 
				
			||||||
 | 
					#include "stat.h"
 | 
				
			||||||
#include "user.h"
 | 
					#include "user.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
char buf[513];
 | 
					char buf[513];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					rfile(int fd)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  int cc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  while((cc = read(fd, buf, sizeof(buf) - 1)) > 0){
 | 
				
			||||||
 | 
					    buf[cc] = '\0';
 | 
				
			||||||
 | 
					    puts(buf);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  if(cc < 0){
 | 
				
			||||||
 | 
					    puts("cat: read error\n");
 | 
				
			||||||
 | 
					    exit();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int
 | 
					int
 | 
				
			||||||
main(int argc, char *argv[])
 | 
					main(int argc, char *argv[])
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  int fd, i, cc;
 | 
					  int fd, i;
 | 
				
			||||||
 | 
					 | 
				
			||||||
  if(argc < 2){
 | 
					 | 
				
			||||||
    puts("Usage: cat files...\n");
 | 
					 | 
				
			||||||
    exit();
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (argc <= 1) {
 | 
				
			||||||
 | 
					    rfile(0);
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
  for(i = 1; i < argc; i++){
 | 
					  for(i = 1; i < argc; i++){
 | 
				
			||||||
    fd = open(argv[i], 0);
 | 
					    fd = open(argv[i], 0);
 | 
				
			||||||
    if(fd < 0){
 | 
					    if(fd < 0){
 | 
				
			||||||
| 
						 | 
					@ -20,16 +35,10 @@ main(int argc, char *argv[])
 | 
				
			||||||
      puts("\n");
 | 
					      puts("\n");
 | 
				
			||||||
      exit();
 | 
					      exit();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    while((cc = read(fd, buf, sizeof(buf) - 1)) > 0){
 | 
					    rfile(fd);
 | 
				
			||||||
      buf[cc] = '\0';
 | 
					 | 
				
			||||||
      puts(buf);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    if(cc < 0){
 | 
					 | 
				
			||||||
      puts("cat: read error\n");
 | 
					 | 
				
			||||||
      exit();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    close(fd);
 | 
					    close(fd);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  exit();
 | 
					  exit();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										15
									
								
								console.c
									
										
									
									
									
								
							
							
						
						
									
										15
									
								
								console.c
									
										
									
									
									
								
							| 
						 | 
					@ -304,26 +304,31 @@ char kbd_buf[KBD_BUF];
 | 
				
			||||||
int kbd_r;
 | 
					int kbd_r;
 | 
				
			||||||
int kbd_w;
 | 
					int kbd_w;
 | 
				
			||||||
struct spinlock kbd_lock;
 | 
					struct spinlock kbd_lock;
 | 
				
			||||||
 | 
					static uint shift;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
kbd_intr()
 | 
					kbd_intr()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  uint st, data, c;
 | 
					  uint st, data, c;
 | 
				
			||||||
  static uint shift;
 | 
					
 | 
				
			||||||
 | 
					  acquire(&kbd_lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  st = inb(KBSTATP);
 | 
					  st = inb(KBSTATP);
 | 
				
			||||||
  if ((st & KBS_DIB) == 0){
 | 
					  if ((st & KBS_DIB) == 0){
 | 
				
			||||||
 | 
					    release(&kbd_lock);
 | 
				
			||||||
    return;
 | 
					    return;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  data = inb(KBDATAP);
 | 
					  data = inb(KBDATAP);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (data == 0xE0) {
 | 
					  if (data == 0xE0) {
 | 
				
			||||||
    shift |= E0ESC;
 | 
					    shift |= E0ESC;
 | 
				
			||||||
 | 
					    release(&kbd_lock);
 | 
				
			||||||
    return;
 | 
					    return;
 | 
				
			||||||
  } else if (data & 0x80) {
 | 
					  } else if (data & 0x80) {
 | 
				
			||||||
    // Key released
 | 
					    // Key released
 | 
				
			||||||
    data = (shift & E0ESC ? data : data & 0x7F);
 | 
					    data = (shift & E0ESC ? data : data & 0x7F);
 | 
				
			||||||
    shift &= ~(shiftcode[data] | E0ESC);
 | 
					    shift &= ~(shiftcode[data] | E0ESC);
 | 
				
			||||||
 | 
					    release(&kbd_lock);
 | 
				
			||||||
    return;
 | 
					    return;
 | 
				
			||||||
  } else if (shift & E0ESC) {
 | 
					  } else if (shift & E0ESC) {
 | 
				
			||||||
    // Last character was an E0 escape; or with 0x80
 | 
					    // Last character was an E0 escape; or with 0x80
 | 
				
			||||||
| 
						 | 
					@ -342,7 +347,11 @@ kbd_intr()
 | 
				
			||||||
      c += 'a' - 'A';
 | 
					      c += 'a' - 'A';
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  acquire(&kbd_lock);
 | 
					  // xxx hack
 | 
				
			||||||
 | 
					  if (c == 0x0) {
 | 
				
			||||||
 | 
					    release(&kbd_lock);
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if(((kbd_w + 1) % KBD_BUF) != kbd_r){
 | 
					  if(((kbd_w + 1) % KBD_BUF) != kbd_r){
 | 
				
			||||||
    kbd_buf[kbd_w++] = c;
 | 
					    kbd_buf[kbd_w++] = c;
 | 
				
			||||||
| 
						 | 
					@ -367,7 +376,7 @@ console_read(int minor, char *dst, int n)
 | 
				
			||||||
    sleep(&kbd_r, &kbd_lock);
 | 
					    sleep(&kbd_r, &kbd_lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  while(n > 0 && kbd_w != kbd_r){
 | 
					  while(n > 0 && kbd_w != kbd_r){
 | 
				
			||||||
    *dst = kbd_buf[kbd_r];
 | 
					    *dst = (kbd_buf[kbd_r]) & 0xff;
 | 
				
			||||||
    cons_putc(*dst & 0xff);
 | 
					    cons_putc(*dst & 0xff);
 | 
				
			||||||
    dst++;
 | 
					    dst++;
 | 
				
			||||||
    --n;
 | 
					    --n;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										1
									
								
								defs.h
									
										
									
									
									
								
							
							
						
						
									
										1
									
								
								defs.h
									
										
									
									
									
								
							| 
						 | 
					@ -16,6 +16,7 @@ struct jmpbuf;
 | 
				
			||||||
void setupsegs(struct proc *);
 | 
					void setupsegs(struct proc *);
 | 
				
			||||||
struct proc * copyproc(struct proc*);
 | 
					struct proc * copyproc(struct proc*);
 | 
				
			||||||
struct spinlock;
 | 
					struct spinlock;
 | 
				
			||||||
 | 
					int growproc(int);
 | 
				
			||||||
void sleep(void *, struct spinlock *);
 | 
					void sleep(void *, struct spinlock *);
 | 
				
			||||||
void wakeup(void *);
 | 
					void wakeup(void *);
 | 
				
			||||||
void scheduler(void);
 | 
					void scheduler(void);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										2
									
								
								echo.c
									
										
									
									
									
								
							
							
						
						
									
										2
									
								
								echo.c
									
										
									
									
									
								
							| 
						 | 
					@ -1,3 +1,5 @@
 | 
				
			||||||
 | 
					#include "types.h"
 | 
				
			||||||
 | 
					#include "stat.h"
 | 
				
			||||||
#include "user.h"
 | 
					#include "user.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int
 | 
					int
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										2
									
								
								lapic.c
									
										
									
									
									
								
							
							
						
						
									
										2
									
								
								lapic.c
									
										
									
									
									
								
							| 
						 | 
					@ -120,7 +120,7 @@ lapic_timerinit(void)
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
lapic_timerintr(void)
 | 
					lapic_timerintr(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  cprintf("cpu%d: timer interrupt!\n", cpu());
 | 
					  // cprintf("cpu%d: timer interrupt!\n", cpu());
 | 
				
			||||||
  lapic_write (LAPIC_EOI, 0);
 | 
					  lapic_write (LAPIC_EOI, 0);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										57
									
								
								ls.c
									
										
									
									
									
								
							
							
						
						
									
										57
									
								
								ls.c
									
										
									
									
									
								
							| 
						 | 
					@ -7,13 +7,24 @@ char buf[512];
 | 
				
			||||||
struct stat st;
 | 
					struct stat st;
 | 
				
			||||||
struct dirent dirent;
 | 
					struct dirent dirent;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					pname(char *n)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  for (i = 0; (i < DIRSIZ) && (n[i] != '\0') ; i++) {
 | 
				
			||||||
 | 
					      printf(1, "%c", n[i]);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  for (; i < DIRSIZ; i++)
 | 
				
			||||||
 | 
					    printf(1, " ");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int
 | 
					int
 | 
				
			||||||
main(int argc, char *argv[])
 | 
					main(int argc, char *argv[])
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  int fd;
 | 
					  int fd;
 | 
				
			||||||
  uint off;
 | 
					  uint off;
 | 
				
			||||||
  uint sz;
 | 
					  uint sz;
 | 
				
			||||||
  int i;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if(argc > 2){
 | 
					  if(argc > 2){
 | 
				
			||||||
    puts("Usage: ls [dir]\n");
 | 
					    puts("Usage: ls [dir]\n");
 | 
				
			||||||
| 
						 | 
					@ -23,7 +34,7 @@ main(int argc, char *argv[])
 | 
				
			||||||
  if (argc == 2) {
 | 
					  if (argc == 2) {
 | 
				
			||||||
    fd = open(argv[1], 0);
 | 
					    fd = open(argv[1], 0);
 | 
				
			||||||
    if(fd < 0){
 | 
					    if(fd < 0){
 | 
				
			||||||
      printf(2, "ls: cannot open dir %s\n", argv[1]);
 | 
					      printf(2, "ls: cannot open %s\n", argv[1]);
 | 
				
			||||||
      exit();
 | 
					      exit();
 | 
				
			||||||
    } 
 | 
					    } 
 | 
				
			||||||
  } else {
 | 
					  } else {
 | 
				
			||||||
| 
						 | 
					@ -38,31 +49,31 @@ main(int argc, char *argv[])
 | 
				
			||||||
    printf(2, "ls: cannot stat dir\n");
 | 
					    printf(2, "ls: cannot stat dir\n");
 | 
				
			||||||
    exit();
 | 
					    exit();
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  if (st.st_type != T_DIR) {
 | 
					
 | 
				
			||||||
    printf(2, "ls: dir is not a directory\n");
 | 
					  switch (st.st_type) {
 | 
				
			||||||
  }
 | 
					  case T_FILE:
 | 
				
			||||||
  sz = st.st_size;
 | 
					    pname(argv[1]);
 | 
				
			||||||
  for(off = 0; off < sz; off += sizeof(struct dirent)) {
 | 
					    printf(1, "%d %d %d\n", st.st_type, st.st_ino, st.st_size);
 | 
				
			||||||
    if (read(fd, &dirent, sizeof(struct dirent)) != sizeof(struct dirent)) {
 | 
					    break;
 | 
				
			||||||
      printf(1, "ls: read error\n");
 | 
					  case T_DIR:
 | 
				
			||||||
      break;
 | 
					    sz = st.st_size;
 | 
				
			||||||
    }
 | 
					    for(off = 0; off < sz; off += sizeof(struct dirent)) {
 | 
				
			||||||
    if (dirent.inum != 0) {
 | 
					      if (read(fd, &dirent, sizeof(struct dirent)) != sizeof(struct dirent)) {
 | 
				
			||||||
      // xxx prepend to name the pathname supplied to ls (e.g. .. in ls ..)
 | 
						printf(1, "ls: read error\n");
 | 
				
			||||||
      if (stat (dirent.name, &st) < 0)  {
 | 
						break;
 | 
				
			||||||
	printf(1, "stat: failed %s\n", dirent.name);
 | 
					 | 
				
			||||||
	continue;
 | 
					 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      for (i = 0; i < DIRSIZ; i++) {
 | 
					      if (dirent.inum != 0) {
 | 
				
			||||||
	if (dirent.name[i] != '\0')
 | 
						// xxx prepend to name the pathname supplied to ls (e.g. .. in ls ..)
 | 
				
			||||||
	  printf(1, "%c", dirent.name[i]);
 | 
						if (stat (dirent.name, &st) < 0)  {
 | 
				
			||||||
	else
 | 
						  printf(1, "stat: failed %s\n", dirent.name);
 | 
				
			||||||
	  printf(1, " ");
 | 
						  continue;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						pname(dirent.name);
 | 
				
			||||||
 | 
						printf(1, "%d %d %d\n", st.st_type, dirent.inum, st.st_size);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      printf(1, "%d %d %d\n", st.st_type, dirent.inum, st.st_size);
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    break;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  close(fd);
 | 
					  close(fd);
 | 
				
			||||||
 | 
					 | 
				
			||||||
  exit();
 | 
					  exit();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										18
									
								
								proc.c
									
										
									
									
									
								
							
							
						
						
									
										18
									
								
								proc.c
									
										
									
									
									
								
							| 
						 | 
					@ -138,6 +138,24 @@ copyproc(struct proc* p)
 | 
				
			||||||
  return np;
 | 
					  return np;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int
 | 
				
			||||||
 | 
					growproc(int n)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  struct proc *cp = curproc[cpu()];
 | 
				
			||||||
 | 
					  char *newmem, *oldmem;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  newmem = kalloc(cp->sz + n);
 | 
				
			||||||
 | 
					  if(newmem == 0) return -1;
 | 
				
			||||||
 | 
					  memmove(newmem, cp->mem, cp->sz);
 | 
				
			||||||
 | 
					  memset(newmem + cp->sz, 0, n);
 | 
				
			||||||
 | 
					  oldmem = cp->mem;
 | 
				
			||||||
 | 
					  cp->mem = newmem;
 | 
				
			||||||
 | 
					  kfree(oldmem, cp->sz);
 | 
				
			||||||
 | 
					  cp->sz += n;
 | 
				
			||||||
 | 
					  cprintf("growproc: added %d bytes\n", n);
 | 
				
			||||||
 | 
					  return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Per-CPU process scheduler. 
 | 
					// Per-CPU process scheduler. 
 | 
				
			||||||
// Each CPU calls scheduler() after setting itself up.
 | 
					// Each CPU calls scheduler() after setting itself up.
 | 
				
			||||||
// Scheduler never returns.  It loops, doing:
 | 
					// Scheduler never returns.  It loops, doing:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										308
									
								
								sh.c
									
										
									
									
									
								
							
							
						
						
									
										308
									
								
								sh.c
									
										
									
									
									
								
							| 
						 | 
					@ -4,52 +4,296 @@
 | 
				
			||||||
#include "fs.h"
 | 
					#include "fs.h"
 | 
				
			||||||
#include "fcntl.h"
 | 
					#include "fcntl.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
char *args[100];
 | 
					#define BUFSIZ  512
 | 
				
			||||||
void parse(char buf[]);
 | 
					#define MAXARGS  10
 | 
				
			||||||
 | 
					#define MAXNODE 2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// only allocate nodes for i/o redir; at some point we may have to build a 
 | 
				
			||||||
 | 
					// a real parse tree.
 | 
				
			||||||
 | 
					struct node {
 | 
				
			||||||
 | 
					  int token;
 | 
				
			||||||
 | 
					  char *s;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					struct node list[MAXNODE];
 | 
				
			||||||
 | 
					int nextnode;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					char buf[BUFSIZ];
 | 
				
			||||||
 | 
					char *argv[MAXARGS];
 | 
				
			||||||
 | 
					char argv0buf[BUFSIZ];
 | 
				
			||||||
 | 
					int argc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int debug = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int parse(char *s);
 | 
				
			||||||
 | 
					void runcmd(void);
 | 
				
			||||||
 | 
					int ioredirection(void);
 | 
				
			||||||
 | 
					int gettoken(char *s, char **token);
 | 
				
			||||||
 | 
					int _gettoken(char *s, char **p1, char **p2);
 | 
				
			||||||
 | 
					void addnode(int token, char *s);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int
 | 
					int
 | 
				
			||||||
main(void)
 | 
					main(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  char buf[128];
 | 
					 | 
				
			||||||
  int pid;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  while(1){
 | 
					  while(1){
 | 
				
			||||||
    puts("$ ");
 | 
					    puts("$ ");
 | 
				
			||||||
    memset (buf, '\0', sizeof(buf));
 | 
					    memset (buf, '\0', sizeof(buf));
 | 
				
			||||||
    gets(buf, sizeof(buf));
 | 
					    gets(buf, sizeof(buf));
 | 
				
			||||||
    if(buf[0] == '\0')
 | 
					    if (parse(buf) < 0)
 | 
				
			||||||
      continue;
 | 
					      continue;
 | 
				
			||||||
    pid = fork();
 | 
					    runcmd();
 | 
				
			||||||
    if(pid == 0){
 | 
					 | 
				
			||||||
      parse(buf);
 | 
					 | 
				
			||||||
      if (buf[0] == 'c' && buf[1] == 'd' && buf[2] == '\0') {  // cd
 | 
					 | 
				
			||||||
	chdir(&buf[3]);
 | 
					 | 
				
			||||||
      } else {
 | 
					 | 
				
			||||||
	exec(buf, args);
 | 
					 | 
				
			||||||
	printf(1, "%s: not found\n", buf);
 | 
					 | 
				
			||||||
	exit();
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    if(pid > 0)
 | 
					 | 
				
			||||||
      wait();
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					int 
 | 
				
			||||||
parse(char buf[])
 | 
					parse(char *s)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  int j = 1;
 | 
					  char *t;
 | 
				
			||||||
  int i;
 | 
					  int c;
 | 
				
			||||||
  args[0] = buf;
 | 
					
 | 
				
			||||||
  for (i = 0; buf[i] != '\0'; i++) {
 | 
					  gettoken(s, 0);
 | 
				
			||||||
    if (buf[i] == ' ') {
 | 
					
 | 
				
			||||||
      buf[i] = '\0';
 | 
					  argc = 0;
 | 
				
			||||||
      args[j++] = buf + i + 1;
 | 
					  nextnode = 0;
 | 
				
			||||||
      if (j >= 100) {
 | 
					  while (1) {
 | 
				
			||||||
	printf(2, "too many args\n");
 | 
					    switch ((c = gettoken(0, &t))) {
 | 
				
			||||||
	exit();
 | 
					
 | 
				
			||||||
 | 
					    case 'w':	// Add an argument
 | 
				
			||||||
 | 
					      if (argc == MAXARGS) {
 | 
				
			||||||
 | 
						printf(2, "too many arguments\n");
 | 
				
			||||||
 | 
						return -1;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					      argv[argc++] = t;
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
								
 | 
				
			||||||
 | 
					    case '<':	// Input redirection
 | 
				
			||||||
 | 
					      // Grab the filename from the argument list
 | 
				
			||||||
 | 
					      if (gettoken(0, &t) != 'w') {
 | 
				
			||||||
 | 
						printf(2, "syntax error: < not followed by word\n");
 | 
				
			||||||
 | 
						return -1;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      addnode('<', t);
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
								
 | 
				
			||||||
 | 
					    case '>':	// Output redirection
 | 
				
			||||||
 | 
					      // Grab the filename from the argument list
 | 
				
			||||||
 | 
					      if (gettoken(0, &t) != 'w') {
 | 
				
			||||||
 | 
						printf(2, "syntax error: > not followed by word\n");
 | 
				
			||||||
 | 
						return -1;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      addnode('>', t);
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    case 0:		// String is complete
 | 
				
			||||||
 | 
					      return 0;
 | 
				
			||||||
 | 
								
 | 
				
			||||||
 | 
					    default:
 | 
				
			||||||
 | 
					      printf(2, "syntax error: bad return %d from gettoken", c);
 | 
				
			||||||
 | 
					      return -1;
 | 
				
			||||||
 | 
								
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  args[j] = '\0';
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					runcmd(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  int i, r, pid;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Return immediately if command line was empty.
 | 
				
			||||||
 | 
					  if(argc == 0) {
 | 
				
			||||||
 | 
					    if (debug)
 | 
				
			||||||
 | 
					      printf(2, "EMPTY COMMAND\n");
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Clean up command line.
 | 
				
			||||||
 | 
					  // Read all commands from the filesystem: add an initial '/' to
 | 
				
			||||||
 | 
					  // the command name.
 | 
				
			||||||
 | 
					  // This essentially acts like 'PATH=/'.
 | 
				
			||||||
 | 
					  if (argv[0][0] != '/') {
 | 
				
			||||||
 | 
					    argv0buf[0] = '/';
 | 
				
			||||||
 | 
					    strcpy(argv0buf + 1, argv[0]);
 | 
				
			||||||
 | 
					    argv[0] = argv0buf;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  argv[argc] = 0;
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
					  // Print the command.
 | 
				
			||||||
 | 
					  if (debug) {
 | 
				
			||||||
 | 
					    printf(2, "[%d] SPAWN:", getpid());
 | 
				
			||||||
 | 
					    for (i = 0; argv[i]; i++)
 | 
				
			||||||
 | 
					      printf(2, " %s", argv[i]);
 | 
				
			||||||
 | 
					    for (i = 0; i < nextnode; i++) {
 | 
				
			||||||
 | 
					      printf(2, "%c %s", list[i].token, list[i].s);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    printf(2, "\n");
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (strcmp(argv[0], "/cd") == 0) {
 | 
				
			||||||
 | 
					    if (debug) printf (2, "/cd %s is build in\n", argv[1]);
 | 
				
			||||||
 | 
					    chdir(argv[1]);
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  pid = fork();
 | 
				
			||||||
 | 
					  if (pid == 0) {
 | 
				
			||||||
 | 
					    if (ioredirection() < 0)
 | 
				
			||||||
 | 
					      exit();
 | 
				
			||||||
 | 
					    if ((r = exec(argv0buf, (char**) argv)) < 0) {
 | 
				
			||||||
 | 
					      printf(2, "exec %s: %d\n", argv[0], r);
 | 
				
			||||||
 | 
					      exit();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (pid > 0) {
 | 
				
			||||||
 | 
					    if (debug)
 | 
				
			||||||
 | 
					      printf(2, "[%d] WAIT %s\n", getpid(), argv[0]);
 | 
				
			||||||
 | 
					    wait();
 | 
				
			||||||
 | 
					    if (debug)
 | 
				
			||||||
 | 
					      printf(2, "[%d] wait finished\n", getpid());
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int
 | 
				
			||||||
 | 
					ioredirection(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  int i, fd, dfd;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  for (i = 0; i < nextnode; i++) {
 | 
				
			||||||
 | 
					    switch (list[i].token) {
 | 
				
			||||||
 | 
					    case '<':
 | 
				
			||||||
 | 
					      if ((fd = open(list[i].s, O_RDONLY)) < 0) {
 | 
				
			||||||
 | 
						printf(2, "failed to open %s for read: %d", list[i].s, fd);
 | 
				
			||||||
 | 
						return -1;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (debug)
 | 
				
			||||||
 | 
						printf(2, "redirect 0 from %s\n", list[i].s);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      close(0);
 | 
				
			||||||
 | 
					      if ((dfd = dup(fd)) < 0)
 | 
				
			||||||
 | 
						printf(2, "dup failed\n");
 | 
				
			||||||
 | 
					      if (debug)
 | 
				
			||||||
 | 
						printf(2, "dup returns %d\n", dfd);
 | 
				
			||||||
 | 
					      close(fd);
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					    case '>':
 | 
				
			||||||
 | 
					      if ((fd = open(list[i].s, O_WRONLY|O_CREATE)) < 0) {
 | 
				
			||||||
 | 
						printf(2, "failed to open %s for write: %d", list[i].s, fd);
 | 
				
			||||||
 | 
						exit();
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (debug)
 | 
				
			||||||
 | 
						printf(2, "redirect 1 to %s\n", list[i].s);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (close(1) < 0)
 | 
				
			||||||
 | 
						printf(2, "close 1 failed\n");
 | 
				
			||||||
 | 
					      if ((dfd = dup(fd)) < 0)
 | 
				
			||||||
 | 
						printf(2, "dup failed\n");
 | 
				
			||||||
 | 
					      if (debug)
 | 
				
			||||||
 | 
						printf(2, "dup returns %d\n", dfd);
 | 
				
			||||||
 | 
					      close(fd);
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					addnode(int token, char *s)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  if (nextnode >= MAXNODE) {
 | 
				
			||||||
 | 
					    printf(2, "addnode: ran out of nodes\n");
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					  list[nextnode].token = token;
 | 
				
			||||||
 | 
					  list[nextnode].s = s;
 | 
				
			||||||
 | 
					  nextnode++;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// gettoken(s, 0) prepares gettoken for subsequent calls and returns 0.
 | 
				
			||||||
 | 
					// gettoken(0, token) parses a shell token from the previously set string,
 | 
				
			||||||
 | 
					// null-terminates that token, stores the token pointer in '*token',
 | 
				
			||||||
 | 
					// and returns a token ID (0, '<', '>', '|', or 'w').
 | 
				
			||||||
 | 
					// Subsequent calls to 'gettoken(0, token)' will return subsequent
 | 
				
			||||||
 | 
					// tokens from the string.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int
 | 
				
			||||||
 | 
					gettoken(char *s, char **p1)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  static int c, nc;
 | 
				
			||||||
 | 
					  static char* np1, *np2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (s) {
 | 
				
			||||||
 | 
					    nc = _gettoken(s, &np1, &np2);
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  c = nc;
 | 
				
			||||||
 | 
					  *p1 = np1;
 | 
				
			||||||
 | 
					  nc = _gettoken(np2, &np1, &np2);
 | 
				
			||||||
 | 
					  return c;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Get the next token from string s.
 | 
				
			||||||
 | 
					// Set *p1 to the beginning of the token and *p2 just past the token.
 | 
				
			||||||
 | 
					// Returns
 | 
				
			||||||
 | 
					//	0 for end-of-string;
 | 
				
			||||||
 | 
					//	< for <;
 | 
				
			||||||
 | 
					//	> for >;
 | 
				
			||||||
 | 
					//	| for |;
 | 
				
			||||||
 | 
					//	w for a word.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Eventually (once we parse the space where the \0 will go),
 | 
				
			||||||
 | 
					// words get nul-terminated.
 | 
				
			||||||
 | 
					#define WHITESPACE " \t\r\n"
 | 
				
			||||||
 | 
					#define SYMBOLS "<|>&;()"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int
 | 
				
			||||||
 | 
					_gettoken(char *s, char **p1, char **p2)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  int t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (s == 0) {
 | 
				
			||||||
 | 
					    if (debug > 1)
 | 
				
			||||||
 | 
					      printf(2, "GETTOKEN NULL\n");
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (debug > 1)
 | 
				
			||||||
 | 
					    printf(2, "GETTOKEN: %s\n", s);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  *p1 = 0;
 | 
				
			||||||
 | 
					  *p2 = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  while (strchr(WHITESPACE, *s))
 | 
				
			||||||
 | 
					    *s++ = 0;
 | 
				
			||||||
 | 
					  if (*s == 0) {
 | 
				
			||||||
 | 
					    if (debug > 1)
 | 
				
			||||||
 | 
					      printf(2, "EOL\n");
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  if (strchr(SYMBOLS, *s)) {
 | 
				
			||||||
 | 
					    t = *s;
 | 
				
			||||||
 | 
					    *p1 = s;
 | 
				
			||||||
 | 
					    *s++ = 0;
 | 
				
			||||||
 | 
					    *p2 = s;
 | 
				
			||||||
 | 
					    if (debug > 1)
 | 
				
			||||||
 | 
					      printf(2, "TOK %c\n", t);
 | 
				
			||||||
 | 
					    return t;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  *p1 = s;
 | 
				
			||||||
 | 
					  while (*s && !strchr(WHITESPACE SYMBOLS, *s))
 | 
				
			||||||
 | 
					    s++;
 | 
				
			||||||
 | 
					  *p2 = s;
 | 
				
			||||||
 | 
					  if (debug > 1) {
 | 
				
			||||||
 | 
					    t = **p2;
 | 
				
			||||||
 | 
					    **p2 = 0;
 | 
				
			||||||
 | 
					    printf(2, "WORD: %s\n", *p1);
 | 
				
			||||||
 | 
					    **p2 = t;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  return 'w';
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										29
									
								
								syscall.c
									
										
									
									
									
								
							
							
						
						
									
										29
									
								
								syscall.c
									
										
									
									
									
								
							| 
						 | 
					@ -140,6 +140,7 @@ sys_write(void)
 | 
				
			||||||
    return -1;
 | 
					    return -1;
 | 
				
			||||||
  if(addr + n > p->sz)
 | 
					  if(addr + n > p->sz)
 | 
				
			||||||
    return -1;
 | 
					    return -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  ret = fd_write(p->fds[fd], p->mem + addr, n);
 | 
					  ret = fd_write(p->fds[fd], p->mem + addr, n);
 | 
				
			||||||
  return ret;
 | 
					  return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -421,6 +422,7 @@ sys_dup(void)
 | 
				
			||||||
    fd_close(fd1);
 | 
					    fd_close(fd1);
 | 
				
			||||||
    return -1;
 | 
					    return -1;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					  cp->fds[ufd1] = fd1;
 | 
				
			||||||
  fd1->type = cp->fds[fd]->type;
 | 
					  fd1->type = cp->fds[fd]->type;
 | 
				
			||||||
  fd1->readable = cp->fds[fd]->readable;
 | 
					  fd1->readable = cp->fds[fd]->readable;
 | 
				
			||||||
  fd1->writeable = cp->fds[fd]->writeable;
 | 
					  fd1->writeable = cp->fds[fd]->writeable;
 | 
				
			||||||
| 
						 | 
					@ -449,6 +451,27 @@ sys_link(void)
 | 
				
			||||||
  return r;
 | 
					  return r;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int
 | 
				
			||||||
 | 
					sys_getpid(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  struct proc *cp = curproc[cpu()];
 | 
				
			||||||
 | 
					  return cp->pid;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int
 | 
				
			||||||
 | 
					sys_sbrk(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  int r, n;
 | 
				
			||||||
 | 
					  struct proc *cp = curproc[cpu()];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if(fetcharg(0, &n) < 0)
 | 
				
			||||||
 | 
					    return -1;
 | 
				
			||||||
 | 
					  r = growproc(n);
 | 
				
			||||||
 | 
					  setupsegs(cp);  
 | 
				
			||||||
 | 
					  return r;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int
 | 
					int
 | 
				
			||||||
sys_exec(void)
 | 
					sys_exec(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -638,6 +661,12 @@ syscall(void)
 | 
				
			||||||
  case SYS_dup:
 | 
					  case SYS_dup:
 | 
				
			||||||
    ret = sys_dup();
 | 
					    ret = sys_dup();
 | 
				
			||||||
    break;
 | 
					    break;
 | 
				
			||||||
 | 
					  case SYS_getpid:
 | 
				
			||||||
 | 
					    ret = sys_getpid();
 | 
				
			||||||
 | 
					    break;
 | 
				
			||||||
 | 
					  case SYS_sbrk:
 | 
				
			||||||
 | 
					    ret = sys_sbrk();
 | 
				
			||||||
 | 
					    break;
 | 
				
			||||||
  default:
 | 
					  default:
 | 
				
			||||||
    cprintf("unknown sys call %d\n", num);
 | 
					    cprintf("unknown sys call %d\n", num);
 | 
				
			||||||
    // XXX fault
 | 
					    // XXX fault
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -15,4 +15,6 @@
 | 
				
			||||||
#define SYS_mkdir 16
 | 
					#define SYS_mkdir 16
 | 
				
			||||||
#define SYS_chdir 17
 | 
					#define SYS_chdir 17
 | 
				
			||||||
#define SYS_dup 18
 | 
					#define SYS_dup 18
 | 
				
			||||||
 | 
					#define SYS_getpid 19
 | 
				
			||||||
 | 
					#define SYS_sbrk 20
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										17
									
								
								ulib.c
									
										
									
									
									
								
							
							
						
						
									
										17
									
								
								ulib.c
									
										
									
									
									
								
							| 
						 | 
					@ -20,6 +20,14 @@ strcpy(char *s, char *t)
 | 
				
			||||||
	return os;
 | 
						return os;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int
 | 
				
			||||||
 | 
					strcmp(const char *p, const char *q)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						while (*p && *p == *q)
 | 
				
			||||||
 | 
							p++, q++;
 | 
				
			||||||
 | 
						return (int) ((unsigned char) *p - (unsigned char) *q);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
unsigned int
 | 
					unsigned int
 | 
				
			||||||
strlen(char *s)
 | 
					strlen(char *s)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -40,6 +48,15 @@ memset(void *dst, int c, unsigned int n)
 | 
				
			||||||
  return dst;
 | 
					  return dst;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					char *
 | 
				
			||||||
 | 
					strchr(const char *s, char c)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						for (; *s; s++)
 | 
				
			||||||
 | 
							if (*s == c)
 | 
				
			||||||
 | 
								return (char *) s;
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
char *
 | 
					char *
 | 
				
			||||||
gets(char *buf, int max)
 | 
					gets(char *buf, int max)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										3
									
								
								user.h
									
										
									
									
									
								
							
							
						
						
									
										3
									
								
								user.h
									
										
									
									
									
								
							| 
						 | 
					@ -18,10 +18,13 @@ int link(char *, char *);
 | 
				
			||||||
int mkdir(char *);
 | 
					int mkdir(char *);
 | 
				
			||||||
int chdir(char *);
 | 
					int chdir(char *);
 | 
				
			||||||
int dup(int);
 | 
					int dup(int);
 | 
				
			||||||
 | 
					int getpid();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int stat(char *, struct stat *stat);
 | 
					int stat(char *, struct stat *stat);
 | 
				
			||||||
int puts(char*);
 | 
					int puts(char*);
 | 
				
			||||||
char* strcpy(char*, char*);
 | 
					char* strcpy(char*, char*);
 | 
				
			||||||
 | 
					char *strchr(const char *s, char c);
 | 
				
			||||||
 | 
					int strcmp(const char *p, const char *q);
 | 
				
			||||||
void printf(int fd, char *fmt, ...);
 | 
					void printf(int fd, char *fmt, ...);
 | 
				
			||||||
char *gets(char *, int max);
 | 
					char *gets(char *, int max);
 | 
				
			||||||
unsigned int strlen(char *);
 | 
					unsigned int strlen(char *);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										4
									
								
								userfs.c
									
										
									
									
									
								
							
							
						
						
									
										4
									
								
								userfs.c
									
										
									
									
									
								
							| 
						 | 
					@ -20,6 +20,10 @@ main(void)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  printf(stdout, "userfs is running\n");
 | 
					  printf(stdout, "userfs is running\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (sbrk(4096) < 0) {
 | 
				
			||||||
 | 
					    printf(stdout, "sbrk failed\n");
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  fd = open("echo", 0);
 | 
					  fd = open("echo", 0);
 | 
				
			||||||
  if(fd >= 0){
 | 
					  if(fd >= 0){
 | 
				
			||||||
    printf(stdout, "open echo ok\n");
 | 
					    printf(stdout, "open echo ok\n");
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										2
									
								
								usys.S
									
										
									
									
									
								
							
							
						
						
									
										2
									
								
								usys.S
									
										
									
									
									
								
							| 
						 | 
					@ -25,3 +25,5 @@ STUB(link)
 | 
				
			||||||
STUB(mkdir)
 | 
					STUB(mkdir)
 | 
				
			||||||
STUB(chdir)
 | 
					STUB(chdir)
 | 
				
			||||||
STUB(dup)
 | 
					STUB(dup)
 | 
				
			||||||
 | 
					STUB(getpid)
 | 
				
			||||||
 | 
					STUB(sbrk)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		
		Reference in a new issue