/* * EXECOM.C * * Matthew Dillon, 28 Apr 1986 * * This code is particular hacked up and needs re-writing. * */ #include "shell.h" struct COMMAND { int (*func)(); short minargs; short stat; short val; char *name; }; struct MLIST { struct MLIST *next; }; #define F_EXACT 0 #define F_ABBR 1 extern char *breakout(); extern int do_run(), do_number(); extern int do_quit(), do_set_var(), do_unset_var(); extern int do_echo(), do_source(), do_mv(); extern int do_cd(), do_rm(), do_mkdir(), do_history(); extern int do_mem(), do_cat(), do_dir(); extern int do_foreach(), do_return(), do_if(), do_label(), do_goto(); extern int do_failat(), do_checkbrk(), do_inc(); extern int do_input(), do_ver(); static struct MLIST *Mlist; static struct COMMAND Command[] = { do_run , 0, 0, 0 , "\001", do_number , 0, 0, 0 , "\001", do_quit , 0, 0, 0 , "quit", do_set_var , 0, 0, LEVEL_SET , "set", do_unset_var, 0, 0, LEVEL_SET , "unset", do_set_var , 0, 0, LEVEL_ALIAS, "alias", do_unset_var, 0, 0, LEVEL_ALIAS, "unalias", do_echo , 0, 0, 0 , "echo", do_source , 0, 0, 0 , "source", do_mv , 2, 0, 0 , "mv", do_cd , 0, 0, 0 , "cd", do_rm , 0, 0, 0 , "rm", do_mkdir , 0, 0, 0 , "mkdir", do_history , 0, 0, 0 , "history", do_mem , 0, 0, 0 , "mem", do_cat , 0, 0, 0 , "cat", do_dir , 0, 0, 0 , "dir", do_dir , 0, 0, -1 , "devinfo", do_foreach , 3, 0, 0 , "foreach", do_return , 0, 0, 0 , "return", do_if , 1, 1, 0 , "if", do_if , 0, 1, 1 , "else", do_if , 0, 1, 2 , "endif", do_label , 1, 1, 0 , "label", do_goto , 1, 0, 0 , "goto", do_failat , 1, 0, 0 , "failat", do_checkbrk , 0, 0, 0 , "checkbreak", do_inc , 1, 0, 1 , "inc", do_inc , 1, 0, -1, "dec", do_input , 1, 0, 0, "input", do_ver , 0, 0, 0, "version", NULL , 0, 0, 0 , NULL }; static char * mpush(amount) { struct MLIST *ml; ml = (struct MLIST *)malloc (amount + sizeof(*Mlist)); ml->next = Mlist; Mlist = ml; return ((char *)Mlist + sizeof(*Mlist)); } static char * mpop() { char *old = NULL; if (Mlist == NULL) { puts ("Internal MLIST error"); fflush (stdout); } else { old = (char *)Mlist + sizeof(*Mlist); Free (Mlist); Mlist = Mlist->next; } return (old); } mrm() { while (Mlist) { Free (Mlist); Mlist = Mlist->next; } } exec_command(base) char *base; { char *str; int i; if (!H_stack) add_history(base); strcpy (str = mpush(strlen(base) + 1), base); i = e_command(str); if (mpop() != str) { puts ("POP ERROR"); fflush (stdout); } return (1); } static e_command(base) char *base; { char *com, *start, *avline, *alias; char *s1, *s2, *s3, *s4; int flag = 0; int i, pcount, len, ccno; loop: com = breakout (&base, &flag); if (*com == '\0') { if (flag & FL_EOL) return (1); goto loop; } alias = NULL; if ((ccno = find_command(com, F_EXACT)) < 0) { switch (flag & FL_MASK) { case FL_BANG: alias = get_history (com); replace_head (alias, base, flag); break; case FL_DOLLAR: alias = get_var (LEVEL_SET, com + 1); break; default: alias = get_var (LEVEL_ALIAS, com); break; } if (alias == NULL) { if ((ccno = find_command (com, F_ABBR)) < 0) { printf ("%s Command Not Found\n", com); return (-1); } else { goto good_command; } } if (*alias == '%') goto good_command; start = (!(flag & FL_EOC)) ? base : ""; while (!(flag & FL_EOC)) { flag = FL_OVERIDE; breakout (&base, &flag); } com = mpush (strlen(alias) + strlen(start) + 2); strcpy (com, alias); strcat (com, " "); strcat (com, start); i = e_command (com); if (mpop() != com) puts ("ME BAE ERROR"); if (i < 0) return (-1); if (flag & FL_EOL) return (1); goto loop; } good_command: if (ccno < 0 || Command[ccno].stat == 0) { if (Disable) { while (!(flag & FL_EOC)) breakout (&base, &flag); goto eocc; } } pcount = 0; i = pcount = 0; av[i] = mpush (strlen(com) + 1); ++pcount; strcpy (av[i++], com); while (!(flag & FL_EOC)) { com = breakout (&base, &flag); if (*com == '\0') continue; switch (flag & FL_MASK) { case FL_DOLLAR: av[i] = get_var (LEVEL_SET, com + 1); if (av[i] == NULL) av[i] = com; av[i] = strcpy(mpush (strlen(av[i]) + 1), av[i]); ++pcount; break; case FL_QUOTE: default: av[i] = com; break; } if (flag & FL_IDOLLAR) { for (s1 = av[i]; *s1 && *s1 != '$'; ++s1); if (*s1) { *s1 = '\0'; s1 = get_var (LEVEL_SET, s1 + 1); if (s1) { register char *scr_str = mpush(strlen(av[i])+strlen(s1)+1); ++pcount; strcpy (scr_str, av[i]); strcat (scr_str, s1); av[i] = scr_str; } } } if (flag & FL_WILD) { /* av[i] has a wild card, expand it */ int eac; char **eav, **ebase; eav = ebase = expand (av[i], &eac); /* returns malloc'd av list */ if (eav == NULL) { puts ("Null expansion"); goto fail; } if (i + eac > MAXAV - 2) { free_expand (ebase); goto avovr; } for (; eac; --eac, ++eav) { av[i++] = strcpy(mpush(strlen(*eav)+1), *eav); ++pcount; } --i; free_expand (ebase); } if (++i > MAXAV - 2) { avovr: puts ("AV overflow"); goto fail; } } av[i] = NULL; ac = i; for (len = 0, i = 0; i < ac; ++i) len += strlen(av[i]) + 1; avline = mpush (len + 1); *avline = '\0'; for (i = 0; i < ac; ++i) { strcat (avline, av[i]); if (i + 1 < ac) strcat (avline, " "); } if (*alias) { for (s2 = alias; *s2 && *s2 != ' '; ++s2); if (*s2) { *s2 = '\0'; s3 = strcpy(mpush(strlen(next_word(avline))+1), next_word(avline)); s4 = strcpy(malloc(strlen(alias)), alias + 1); set_var (LEVEL_SET, s4, s3); *s2 = ' '; s1 = strcpy(mpush(strlen(s2)+1), s2); i = e_command (s1); unset_var (LEVEL_SET, s4); free (s4); if (mpop() != s1) puts ("AL-LINE ERROR"); mpop(); } } else { i = -1; if (ac < Command[ccno].minargs + 1) ierror (NULL, 500); else i = (*Command[ccno].func)(avline, Command[ccno].val); } if (mpop() != avline) { puts ("AVLINE ERROR"); fail: i = -1; } while (pcount--) mpop(); if (i < 0) return (i); eocc: if (flag & FL_EOL) return (1); goto loop; } static char * breakout(base, flag) register int *flag; char **base; { register char *str, *scr; register int oflag = *flag; loop: *flag = 0; str = *base; while (*str == ' ' || *str == 9) ++str; switch (*str) { case '\0': *flag = FL_EOC | FL_EOL; *base = str; return (str); case '*': case '?': *flag = FL_WILD; break; case ';': *flag = FL_EOC; *str = '\0'; *base = str + 1; return (str); case '\"': *flag = FL_QUOTE; break; case '$': *flag = FL_DOLLAR; break; case '%': *flag = FL_PERCENT; break; case '!': *flag = FL_BANG; break; default: break; } scr = str; for (;;) { switch (*scr) { case '$': if (scr != str) *flag |= FL_IDOLLAR; ++scr; break; case '*': case '?': *flag |= FL_WILD; ++scr; break; case ' ': case 9: if (!(oflag & FL_OVERIDE)) *scr = '\0'; *base = scr + 1; return (str); case '\"': /* Quote */ del_char(scr); while (*scr && *scr != '\"') { if (*scr == '\\') { del_char(scr); if (*scr) ++scr; } else { ++scr; } } if (*scr == '\"') del_char(scr); break; case '\0': *flag |= FL_EOL | FL_EOC; *base = scr; return (str); case ';': *flag |= FL_EOC; *base = scr + 1; *scr = '\0'; return (str); case '^': ++scr; if (*scr) { *(scr - 1) = *scr & 0x1f; del_char (scr); } break; case '\\': del_char(scr); if (*scr) ++scr; break; default: ++scr; } } } del_char(str) register char *str; { for (; *str; ++str) str[0] = str[1]; } static find_command(str, arg) char *str; { int i; int len = strlen(str); if (*str >= '0' && *str <= '9') return (1); for (i = 0; Command[i].func; ++i) { if (strncmp (str, Command[i].name, len) == 0) { if (arg == F_ABBR) return (i); if (strcmp (str, Command[i].name) == 0) return (i); return (-1); } } if (arg == F_ABBR) return (0); return (-1); }