#include #include #include #include "parse.h" #define PIPE ('|') #define BG ('&') #define RIN ('<') #define RUT ('>') #define ispipe(c) ((c) == PIPE) #define isbg(c) ((c) == BG) #define isrin(c) ((c) == RIN) #define isrut(c) ((c) == RUT) #define isspec(c) (ispipe(c) || isbg(c) || isrin(c) || isrut(c)) static Pgm cmdbuf[20], *cmds; static char cbuf[256], *cp; static char *pbuf[50], **pp; /* * A quick hack to parse a commandline */ int parse (char *buf, Command *c) { int n; Pgm *cmd0; char *t = buf; char *tok; init(); c->rstdin = NULL; c->rstdout = NULL; c->rstderr = NULL; c->bakground = 0; /* false */ c->pgm = NULL; newcmd: if ((n = acmd(t, &cmd0)) <= 0) return -1; t += n; cmd0->next = c->pgm; c->pgm = cmd0; newtoken: n = nexttoken(t, &tok); if (n == 0) { return 1; } t += n; switch(*tok) { case PIPE: goto newcmd; break; case BG: n = nexttoken(t, &tok); if (n == 0) { c->bakground = 1; return 1; } else { fprintf(stderr, "illegal bakgrounding\n"); return -1; } break; case RIN: if (c->rstdin != NULL) { fprintf(stderr, "duplicate redirection of stdin\n"); return -1; } if ((n = nexttoken(t, &(c->rstdin))) < 0) return -1; if (!isidentifier(c->rstdin)) { fprintf(stderr, "Illegal filename: \"%s\"\n", c->rstdin); return -1; } t += n; goto newtoken; break; case RUT: if (c->rstdout != NULL) { fprintf(stderr, "duplicate redirection of stdout\n"); return -1; } if ((n = nexttoken(t, &(c->rstdout))) < 0) return -1; if (!isidentifier(c->rstdout)) { fprintf(stderr, "Illegal filename: \"%s\"\n", c->rstdout); return -1; } t += n; goto newtoken; break; default: return -1; } goto newcmd; } void init( void ) { int i; for (i=0;i<19;i++) cmdbuf[i].next = &cmdbuf[i+1]; cmdbuf[19].next = NULL; cmds = cmdbuf; cp = cbuf; pp = pbuf; } int nexttoken( char *s, char **tok) { char *s0 = s; char c; *tok = cp; while (isspace(c = *s++) && c); if (c == '\0') { return 0; } if (isspec(c)) { *cp++ = c; *cp++ = '\0'; } else { *cp++ = c; do { c = *cp++ = *s++; } while (!isspace(c) && !isspec(c) && (c != '\0')); --s; --cp; *cp++ = '\0'; } return s - s0; } int acmd (char *s, Pgm **cmd) { char *tok; int n, cnt = 0; Pgm *cmd0 = cmds; cmds = cmds->next; cmd0->next = NULL; cmd0->pgmlist = pp; next: n = nexttoken(s, &tok); if (n == 0 || isspec(*tok)) { *cmd = cmd0; *pp++ = NULL; return cnt; } else { *pp++ = tok; cnt += n; s += n; goto next; } } #define IDCHARS "_-.,/~+" int isidentifier (char *s) { while (*s) { char *p = strrchr (IDCHARS, *s); if (! isalnum(*s++) && (p == NULL)) return 0; } return 1; }