117a85657Srtm #include "types.h" 2d7b3b802Skaashoek #include "stat.h" 3d7b3b802Skaashoek #include "user.h" 417a85657Srtm #include "fs.h" 517a85657Srtm #include "fcntl.h" 617a85657Srtm 7*8b58e810Skaashoek #define BUFSIZ 512 8*8b58e810Skaashoek #define MAXARGS 10 9*8b58e810Skaashoek #define MAXNODE 2 10*8b58e810Skaashoek 11*8b58e810Skaashoek // only allocate nodes for i/o redir; at some point we may have to build a 12*8b58e810Skaashoek // a real parse tree. 13*8b58e810Skaashoek struct node { 14*8b58e810Skaashoek int token; 15*8b58e810Skaashoek char *s; 16*8b58e810Skaashoek }; 17*8b58e810Skaashoek struct node list[MAXNODE]; 18*8b58e810Skaashoek int nextnode; 19*8b58e810Skaashoek 20*8b58e810Skaashoek char buf[BUFSIZ]; 21*8b58e810Skaashoek char *argv[MAXARGS]; 22*8b58e810Skaashoek char argv0buf[BUFSIZ]; 23*8b58e810Skaashoek int argc; 24*8b58e810Skaashoek 25*8b58e810Skaashoek int debug = 1; 26*8b58e810Skaashoek 27*8b58e810Skaashoek int parse(char *s); 28*8b58e810Skaashoek void runcmd(void); 29*8b58e810Skaashoek int ioredirection(void); 30*8b58e810Skaashoek int gettoken(char *s, char **token); 31*8b58e810Skaashoek int _gettoken(char *s, char **p1, char **p2); 32*8b58e810Skaashoek void addnode(int token, char *s); 3317a85657Srtm 3417a85657Srtm int 3517a85657Srtm main(void) 3617a85657Srtm { 3717a85657Srtm while(1){ 3843572072Srtm puts("$ "); 398787cd01Skaashoek memset (buf, '\0', sizeof(buf)); 4017a85657Srtm gets(buf, sizeof(buf)); 41*8b58e810Skaashoek if (parse(buf) < 0) 4217a85657Srtm continue; 43*8b58e810Skaashoek runcmd(); 4417a85657Srtm } 4517a85657Srtm } 46d7b3b802Skaashoek 47*8b58e810Skaashoek int 48*8b58e810Skaashoek parse(char *s) 49d7b3b802Skaashoek { 50*8b58e810Skaashoek char *t; 51*8b58e810Skaashoek int c; 52*8b58e810Skaashoek 53*8b58e810Skaashoek gettoken(s, 0); 54*8b58e810Skaashoek 55*8b58e810Skaashoek argc = 0; 56*8b58e810Skaashoek nextnode = 0; 57*8b58e810Skaashoek while (1) { 58*8b58e810Skaashoek switch ((c = gettoken(0, &t))) { 59*8b58e810Skaashoek 60*8b58e810Skaashoek case 'w': // Add an argument 61*8b58e810Skaashoek if (argc == MAXARGS) { 62*8b58e810Skaashoek printf(2, "too many arguments\n"); 63*8b58e810Skaashoek return -1; 64*8b58e810Skaashoek } 65*8b58e810Skaashoek argv[argc++] = t; 66*8b58e810Skaashoek break; 67*8b58e810Skaashoek 68*8b58e810Skaashoek case '<': // Input redirection 69*8b58e810Skaashoek // Grab the filename from the argument list 70*8b58e810Skaashoek if (gettoken(0, &t) != 'w') { 71*8b58e810Skaashoek printf(2, "syntax error: < not followed by word\n"); 72*8b58e810Skaashoek return -1; 73*8b58e810Skaashoek } 74*8b58e810Skaashoek addnode('<', t); 75*8b58e810Skaashoek break; 76*8b58e810Skaashoek 77*8b58e810Skaashoek case '>': // Output redirection 78*8b58e810Skaashoek // Grab the filename from the argument list 79*8b58e810Skaashoek if (gettoken(0, &t) != 'w') { 80*8b58e810Skaashoek printf(2, "syntax error: > not followed by word\n"); 81*8b58e810Skaashoek return -1; 82*8b58e810Skaashoek } 83*8b58e810Skaashoek addnode('>', t); 84*8b58e810Skaashoek break; 85*8b58e810Skaashoek 86*8b58e810Skaashoek case 0: // String is complete 87*8b58e810Skaashoek return 0; 88*8b58e810Skaashoek 89*8b58e810Skaashoek default: 90*8b58e810Skaashoek printf(2, "syntax error: bad return %d from gettoken", c); 91*8b58e810Skaashoek return -1; 92*8b58e810Skaashoek 93*8b58e810Skaashoek } 94*8b58e810Skaashoek } 95*8b58e810Skaashoek } 96*8b58e810Skaashoek 97*8b58e810Skaashoek 98*8b58e810Skaashoek void 99*8b58e810Skaashoek runcmd(void) 100*8b58e810Skaashoek { 101*8b58e810Skaashoek int i, r, pid; 102*8b58e810Skaashoek 103*8b58e810Skaashoek // Return immediately if command line was empty. 104*8b58e810Skaashoek if(argc == 0) { 105*8b58e810Skaashoek if (debug) 106*8b58e810Skaashoek printf(2, "EMPTY COMMAND\n"); 107*8b58e810Skaashoek return; 108*8b58e810Skaashoek } 109*8b58e810Skaashoek 110*8b58e810Skaashoek // Clean up command line. 111*8b58e810Skaashoek // Read all commands from the filesystem: add an initial '/' to 112*8b58e810Skaashoek // the command name. 113*8b58e810Skaashoek // This essentially acts like 'PATH=/'. 114*8b58e810Skaashoek if (argv[0][0] != '/') { 115*8b58e810Skaashoek argv0buf[0] = '/'; 116*8b58e810Skaashoek strcpy(argv0buf + 1, argv[0]); 117*8b58e810Skaashoek argv[0] = argv0buf; 118*8b58e810Skaashoek } 119*8b58e810Skaashoek argv[argc] = 0; 120*8b58e810Skaashoek 121*8b58e810Skaashoek // Print the command. 122*8b58e810Skaashoek if (debug) { 123*8b58e810Skaashoek printf(2, "[%d] SPAWN:", getpid()); 124*8b58e810Skaashoek for (i = 0; argv[i]; i++) 125*8b58e810Skaashoek printf(2, " %s", argv[i]); 126*8b58e810Skaashoek for (i = 0; i < nextnode; i++) { 127*8b58e810Skaashoek printf(2, "%c %s", list[i].token, list[i].s); 128*8b58e810Skaashoek } 129*8b58e810Skaashoek printf(2, "\n"); 130*8b58e810Skaashoek } 131*8b58e810Skaashoek 132*8b58e810Skaashoek if (strcmp(argv[0], "/cd") == 0) { 133*8b58e810Skaashoek if (debug) printf (2, "/cd %s is build in\n", argv[1]); 134*8b58e810Skaashoek chdir(argv[1]); 135*8b58e810Skaashoek return; 136*8b58e810Skaashoek } 137*8b58e810Skaashoek 138*8b58e810Skaashoek pid = fork(); 139*8b58e810Skaashoek if (pid == 0) { 140*8b58e810Skaashoek if (ioredirection() < 0) 141*8b58e810Skaashoek exit(); 142*8b58e810Skaashoek if ((r = exec(argv0buf, (char**) argv)) < 0) { 143*8b58e810Skaashoek printf(2, "exec %s: %d\n", argv[0], r); 144d7b3b802Skaashoek exit(); 145d7b3b802Skaashoek } 146d7b3b802Skaashoek } 147*8b58e810Skaashoek 148*8b58e810Skaashoek if (pid > 0) { 149*8b58e810Skaashoek if (debug) 150*8b58e810Skaashoek printf(2, "[%d] WAIT %s\n", getpid(), argv[0]); 151*8b58e810Skaashoek wait(); 152*8b58e810Skaashoek if (debug) 153*8b58e810Skaashoek printf(2, "[%d] wait finished\n", getpid()); 154d7b3b802Skaashoek } 155d7b3b802Skaashoek } 156*8b58e810Skaashoek 157*8b58e810Skaashoek int 158*8b58e810Skaashoek ioredirection(void) 159*8b58e810Skaashoek { 160*8b58e810Skaashoek int i, fd, dfd; 161*8b58e810Skaashoek 162*8b58e810Skaashoek for (i = 0; i < nextnode; i++) { 163*8b58e810Skaashoek switch (list[i].token) { 164*8b58e810Skaashoek case '<': 165*8b58e810Skaashoek if ((fd = open(list[i].s, O_RDONLY)) < 0) { 166*8b58e810Skaashoek printf(2, "failed to open %s for read: %d", list[i].s, fd); 167*8b58e810Skaashoek return -1; 168*8b58e810Skaashoek } 169*8b58e810Skaashoek 170*8b58e810Skaashoek if (debug) 171*8b58e810Skaashoek printf(2, "redirect 0 from %s\n", list[i].s); 172*8b58e810Skaashoek 173*8b58e810Skaashoek close(0); 174*8b58e810Skaashoek if ((dfd = dup(fd)) < 0) 175*8b58e810Skaashoek printf(2, "dup failed\n"); 176*8b58e810Skaashoek if (debug) 177*8b58e810Skaashoek printf(2, "dup returns %d\n", dfd); 178*8b58e810Skaashoek close(fd); 179*8b58e810Skaashoek break; 180*8b58e810Skaashoek case '>': 181*8b58e810Skaashoek if ((fd = open(list[i].s, O_WRONLY|O_CREATE)) < 0) { 182*8b58e810Skaashoek printf(2, "failed to open %s for write: %d", list[i].s, fd); 183*8b58e810Skaashoek exit(); 184*8b58e810Skaashoek } 185*8b58e810Skaashoek 186*8b58e810Skaashoek if (debug) 187*8b58e810Skaashoek printf(2, "redirect 1 to %s\n", list[i].s); 188*8b58e810Skaashoek 189*8b58e810Skaashoek if (close(1) < 0) 190*8b58e810Skaashoek printf(2, "close 1 failed\n"); 191*8b58e810Skaashoek if ((dfd = dup(fd)) < 0) 192*8b58e810Skaashoek printf(2, "dup failed\n"); 193*8b58e810Skaashoek if (debug) 194*8b58e810Skaashoek printf(2, "dup returns %d\n", dfd); 195*8b58e810Skaashoek close(fd); 196*8b58e810Skaashoek break; 197*8b58e810Skaashoek } 198*8b58e810Skaashoek } 199*8b58e810Skaashoek return 0; 200*8b58e810Skaashoek } 201*8b58e810Skaashoek 202*8b58e810Skaashoek void 203*8b58e810Skaashoek addnode(int token, char *s) 204*8b58e810Skaashoek { 205*8b58e810Skaashoek if (nextnode >= MAXNODE) { 206*8b58e810Skaashoek printf(2, "addnode: ran out of nodes\n"); 207*8b58e810Skaashoek return; 208*8b58e810Skaashoek } 209*8b58e810Skaashoek 210*8b58e810Skaashoek list[nextnode].token = token; 211*8b58e810Skaashoek list[nextnode].s = s; 212*8b58e810Skaashoek nextnode++; 213*8b58e810Skaashoek } 214*8b58e810Skaashoek 215*8b58e810Skaashoek 216*8b58e810Skaashoek // gettoken(s, 0) prepares gettoken for subsequent calls and returns 0. 217*8b58e810Skaashoek // gettoken(0, token) parses a shell token from the previously set string, 218*8b58e810Skaashoek // null-terminates that token, stores the token pointer in '*token', 219*8b58e810Skaashoek // and returns a token ID (0, '<', '>', '|', or 'w'). 220*8b58e810Skaashoek // Subsequent calls to 'gettoken(0, token)' will return subsequent 221*8b58e810Skaashoek // tokens from the string. 222*8b58e810Skaashoek 223*8b58e810Skaashoek int 224*8b58e810Skaashoek gettoken(char *s, char **p1) 225*8b58e810Skaashoek { 226*8b58e810Skaashoek static int c, nc; 227*8b58e810Skaashoek static char* np1, *np2; 228*8b58e810Skaashoek 229*8b58e810Skaashoek if (s) { 230*8b58e810Skaashoek nc = _gettoken(s, &np1, &np2); 231*8b58e810Skaashoek return 0; 232*8b58e810Skaashoek } 233*8b58e810Skaashoek c = nc; 234*8b58e810Skaashoek *p1 = np1; 235*8b58e810Skaashoek nc = _gettoken(np2, &np1, &np2); 236*8b58e810Skaashoek return c; 237*8b58e810Skaashoek } 238*8b58e810Skaashoek 239*8b58e810Skaashoek 240*8b58e810Skaashoek // Get the next token from string s. 241*8b58e810Skaashoek // Set *p1 to the beginning of the token and *p2 just past the token. 242*8b58e810Skaashoek // Returns 243*8b58e810Skaashoek // 0 for end-of-string; 244*8b58e810Skaashoek // < for <; 245*8b58e810Skaashoek // > for >; 246*8b58e810Skaashoek // | for |; 247*8b58e810Skaashoek // w for a word. 248*8b58e810Skaashoek // 249*8b58e810Skaashoek // Eventually (once we parse the space where the \0 will go), 250*8b58e810Skaashoek // words get nul-terminated. 251*8b58e810Skaashoek #define WHITESPACE " \t\r\n" 252*8b58e810Skaashoek #define SYMBOLS "<|>&;()" 253*8b58e810Skaashoek 254*8b58e810Skaashoek int 255*8b58e810Skaashoek _gettoken(char *s, char **p1, char **p2) 256*8b58e810Skaashoek { 257*8b58e810Skaashoek int t; 258*8b58e810Skaashoek 259*8b58e810Skaashoek if (s == 0) { 260*8b58e810Skaashoek if (debug > 1) 261*8b58e810Skaashoek printf(2, "GETTOKEN NULL\n"); 262*8b58e810Skaashoek return 0; 263*8b58e810Skaashoek } 264*8b58e810Skaashoek 265*8b58e810Skaashoek if (debug > 1) 266*8b58e810Skaashoek printf(2, "GETTOKEN: %s\n", s); 267*8b58e810Skaashoek 268*8b58e810Skaashoek *p1 = 0; 269*8b58e810Skaashoek *p2 = 0; 270*8b58e810Skaashoek 271*8b58e810Skaashoek while (strchr(WHITESPACE, *s)) 272*8b58e810Skaashoek *s++ = 0; 273*8b58e810Skaashoek if (*s == 0) { 274*8b58e810Skaashoek if (debug > 1) 275*8b58e810Skaashoek printf(2, "EOL\n"); 276*8b58e810Skaashoek return 0; 277*8b58e810Skaashoek } 278*8b58e810Skaashoek if (strchr(SYMBOLS, *s)) { 279*8b58e810Skaashoek t = *s; 280*8b58e810Skaashoek *p1 = s; 281*8b58e810Skaashoek *s++ = 0; 282*8b58e810Skaashoek *p2 = s; 283*8b58e810Skaashoek if (debug > 1) 284*8b58e810Skaashoek printf(2, "TOK %c\n", t); 285*8b58e810Skaashoek return t; 286*8b58e810Skaashoek } 287*8b58e810Skaashoek *p1 = s; 288*8b58e810Skaashoek while (*s && !strchr(WHITESPACE SYMBOLS, *s)) 289*8b58e810Skaashoek s++; 290*8b58e810Skaashoek *p2 = s; 291*8b58e810Skaashoek if (debug > 1) { 292*8b58e810Skaashoek t = **p2; 293*8b58e810Skaashoek **p2 = 0; 294*8b58e810Skaashoek printf(2, "WORD: %s\n", *p1); 295*8b58e810Skaashoek **p2 = t; 296*8b58e810Skaashoek } 297*8b58e810Skaashoek return 'w'; 298*8b58e810Skaashoek } 299*8b58e810Skaashoek 300