home *** CD-ROM | disk | FTP | other *** search
- /*
- * EXECOM.C
- *
- * Matthew Dillon, 10 August 1986
- * Finally re-written.
- *
- * Version 2.07M by Steve Drew 10-Sep-87
- *
- * Version 3.00A by Carlo Borreo & Cesare Dieni 30-Oct-88
- *
- */
-
- extern char *v_histnum, *v_except;
-
- #define F_EXACT 0
- #define F_ABBR 1
-
- #define ST_COND 0x01
- #define ST_NORED 0x02
- #define ST_NOEXP 0x04
- #define ST_AV 0x08 /* delimit args within a variable */
-
- int has_wild = 0; /* set if any arg has wild card */
-
- struct COMMAND {
- int (*func)();
- short minargs;
- short stat;
- int val;
- char *name;
- };
-
- extern char *format_insert_string();
- extern char *mpush(), *exarg();
-
- extern int do_diskchange(), do_stack(), do_fault(), do_path(), do_pri();
- extern int do_rpn(), do_resident(), do_truerun(), do_aset(), do_howmany();
- extern int do_open(), do_close(), do_fileslist(), do_htype();
- extern int do_run(), do_number(), do_assign(), do_join();
- extern int do_quit(), do_set_var(), do_unset_var();
- extern int do_echo(), do_source(), do_mv(), do_addbuffers();
- extern int do_cd(), do_pwd(), do_rm(), do_mkdir(), do_history();
- extern int do_mem(), do_cat(), do_dir(), do_info(), do_inc();
- extern int do_foreach(), do_return(), do_if(), do_label(), do_goto();
- extern int do_input(), do_ver(), do_sleep(), do_help();
- extern int do_strhead(), do_strtail(), do_relabel();
- extern int do_copy(), date(), do_protect(), do_ps();
- extern int do_forever(), do_abortline(), do_strings(), do_touch();
- extern int do_window(), do_search(), do_filenote();
- char *push_cpy();
-
- static struct COMMAND Command[] = {
- do_run, 0, ST_AV, 0, "\001", /* may call do_source */
- do_set_var, 0, 0, LEVEL_ALIAS, "alias", /* uses avline */
- do_abortline, 0, 0, 0, "abortline",
- do_addbuffers, 2, 0, 0, "addbuffers",
- do_aset, 1, 0, 0, "aset",
- do_assign, 0, 0, 0, "assign",
- do_cat, 0, 0, 0, "cat",
- do_cd, 0, 0, 0, "cd",
- do_close, 0, 0, 0, "close",
- do_copy, 1, 0, 0, "copy",
- do_copy, 1, 0, 0, "cp",
- date, 0, 0, 0, "date",
- do_rm, 0, 0, 0, "delete",
- do_dir, 0, ST_NOEXP, 0, "dir",
- do_diskchange, 1, 0, 0, "diskchange",
- do_inc, 1, 0, -1, "dec",
- do_echo, 0, 0, 0, "echo", /* uses avline */
- do_if, 0, ST_COND, 1, "else",
- do_if, 0, ST_COND, 2, "endif",
- do_fault, 1, 0, 0, "fault",
- do_filenote, 2, 0, 0, "filenote",
- do_fileslist, 0, 0, 0, "flist",
- do_foreach, 3, ST_NORED, 0, "foreach",
- do_forever, 1, ST_NORED, 0, "forever",
- do_goto, 1, 0, 0, "goto",
- do_help, 0, 0, 0, "help",
- do_history, 0, 0, 0, "history",
- do_howmany, 0, 0, 0, "howmany",
- do_htype, 1, 0, 0, "htype",
- do_if, 1, ST_COND|ST_NORED,0, "if",
- do_inc, 1, 0, 1, "inc",
- do_info, 0, 0, 0, "info",
- do_join, 2, 0, 1, "join",
- do_input, 1, 0, 0, "input",
- do_label, 1, ST_COND, 0, "label",
- do_dir, 0, ST_NOEXP, 0, "ls",
- do_mkdir, 0, 0, 0, "md",
- do_mem , 0, 0, 0, "mem",
- do_mkdir, 0, 0, 0, "mkdir",
- do_mv, 2, 0, 0, "mv",
- do_open, 3, 0, 0, "open",
- do_path, 0, 0, 0, "path",
- do_pri, 2, 0, 0, "pri",
- do_protect, 2, 0, 0, "protect",
- do_ps, 0, 0, 0, "ps",
- do_pwd, 0, 0, 0, "pwd",
- do_quit, 0, ST_NORED, 0, "quit",
- do_truerun, 1, ST_NORED, 1, "rback",
- do_mv, 2, 0, 0, "rename",
- do_relabel, 2, 0, 0, "relabel",
- do_resident, 0, 0, 0, "resident",
- do_return, 0, 0, 0, "return",
- do_rm, 0, 0, 0, "rm",
- do_rpn, 0, ST_NOEXP|ST_NORED,0, "rpn",
- do_truerun, 1, ST_NORED, 0, "run",
- do_search, 2, 0, 0, "search",
- do_set_var, 0, ST_AV, LEVEL_SET, "set",
- do_sleep, 0, 0, 0, "sleep",
- do_source, 0, ST_NORED|ST_AV, 0, "source", /* uses avline */
- do_stack, 0, 0, 0, "stack",
- do_strhead, 3, 0, 0, "strhead",
- do_strings, 1, 0, 0, "strings",
- do_strtail, 3, 0, 0, "strtail",
- do_touch, 0, 0, 0, "touch",
- do_cat, 0, 0, 0, "type",
- do_unset_var, 0, 0, LEVEL_ALIAS, "unalias",
- do_unset_var, 0, 0, LEVEL_SET , "unset",
- do_ver, 0, 0, 0, "version",
- do_window, 0, ST_NOEXP, 0, "window",
- '\0', 0, 0, 0, NULL
- };
-
- static unsigned char elast; /* last end delimeter */
- static char Cin_ispipe, Cout_ispipe;
-
- exec_command(base)
- char *base;
- {
- register char *scr;
- char buf[32];
-
- if (!H_stack) {
- add_history(base);
- sprintf(buf, "%d", H_tail_base + H_len);
- set_var(LEVEL_SET, v_histnum, buf);
- }
- scr = malloc((strlen(base) << 2) + 2);
- preformat(base, scr);
- return (fcomm(scr, 1) ? -1 : 1);
- }
-
- isalphanum(c)
- register char c;
- {
- return (
- (c >= '0' && c <= '9') ||
- (c >= 'a' && c <= 'z') ||
- (c >= 'A' && c <= 'Z') ||
- (c == '_')
- );
- }
-
- preformat(s, d)
- register char *s, *d;
- {
- register int si, di, qm;
-
- si = di = qm = 0;
- while (s[si] == ' ' || s[si] == 9) ++si;
- while (s[si]) {
- if (qm && s[si] != '\"' && s[si] != '\\') {
- d[di++] = s[si++] | 0x80;
- continue;
- }
- switch (s[si]) {
- case ' ':
- case 9:
- d[di++] = ' ';
- while (s[si] == ' ' || s[si] == 9) ++si;
- if (s[si] == 0 || s[si] == '|' || s[si] == ';') --di;
- break;
- case '*':
- case '?':
- d[di++] = 0x80;
- case '!':
- d[di++] = s[si++];
- break;
- case '#':
- d[di++] = '\0';
- while (s[si]) ++si;
- break;
- case ';':
- case '|':
- d[di++] = s[si++];
- while (s[si] == ' ' || s[si] == 9) ++si;
- break;
- case '\\':
- d[di++] = s[++si] | 0x80;
- if (s[si]) ++si;
- break;
- case '\"':
- qm = 1 - qm;
- ++si;
- break;
- case '^':
- d[di++] = s[++si] & 0x1F;
- if (s[si]) ++si;
- break;
- case '$': /* search end of var name and place false space */
- d[di++] = 0x80;
- d[di++] = s[si++];
- while (isalphanum(s[si])) d[di++] = s[si++];
- d[di++] = 0x80;
- break;
- default:
- d[di++] = s[si++];
- break;
- }
- }
- d[di++]=0;
- d[di]=0;
- if (debug) fprintf (stderr,"PREFORMAT: %d :%s:\n", strlen(d), d);
- }
-
- extern BPTR extOpen();
-
- /*
- * process formatted string. ' ' is the delimeter.
- *
- * 0: check '\0': no more, stop, done.
- * 1: check $. if so, extract, format, insert
- * 2: check alias. if so, extract, format, insert. goto 1
- * 3: check history or substitution, extract, format, insert. goto 1
- *
- * 4: assume first element now internal or disk based command.
- *
- * 5: extract each ' ' or 0x80 delimited argument and process, placing
- * in av[] list (except 0x80 args appended). check in order:
- *
- * '$' insert string straight
- * '>' setup stdout
- * '>>' setup stdout flag for append
- * '<' setup stdin
- * '*' or '?' do directory search and insert as separate args.
- *
- * ';' 0 '|' end of command. if '|' setup stdout
- * -execute command, fix stdin and out (|) sets
- * up stdin for next guy.
- */
-
-
- fcomm(str, freeok)
- register char *str;
- {
- static int alias_count;
- int p_alias_count = 0;
- char *istr;
- char *nextstr;
- char *command;
- char *pend_alias = NULL;
- char err = 0;
- has_wild = 0;
-
- ++alias_count;
-
- mpush_base();
- if (*str == 0)
- goto done1;
- step1:
- if (alias_count == MAXALIAS || ++p_alias_count == MAXALIAS) {
- fprintf(stderr,"Alias Loop\n");
- err = 20;
- goto done1;
- }
- /*
- if (str[1] == '$') {
- if (istr = get_var (LEVEL_SET, str + 2))
- str = format_insert_string(str, istr, &freeok);
- }
- */
- istr = NULL;
- if (*(unsigned char *)str < 0x80)
- istr = get_var (LEVEL_ALIAS, str); /* only if not \command */
- *str &= 0x7F; /* remove \ teltail */
- if (istr) {
- if (*istr == '%') {
- pend_alias = istr;
- } else {
- str = format_insert_string(str, istr, &freeok);
- goto step1;
- }
- }
- if (*str == '!') {
- char *p, c; /* fix to allow !cmd1;!cmd2 */
- for(p = str; *p && *p != ';' ; ++p);
- c = *p;
- *p = '\0';
- istr = get_history(str);
- *p = c;
- replace_head(istr);
- str = format_insert_string(str, istr, &freeok);
- goto step1;
- }
- nextstr = str;
- command = exarg(&nextstr);
- if (*command == 0)
- goto done0;
- if (pend_alias == 0) {
- if (cmd_stat(command) & ST_COND)
- goto skipgood;
- }
- if (disable || forward_goto) {
- while (elast && elast != ';' && elast != '|')
- exarg(&nextstr);
- goto done0;
- }
- skipgood:
- {
- register char *arg, *ptr, *scr;
- short redir;
- short doexpand;
- short cont;
- short inc;
-
- ac = 1;
- av[0] = command;
- step5: /* ac = nextac */
- if (!elast || elast == ';' || elast == '|')
- goto stepdone;
-
- av[ac] = '\0';
- cont = 1;
- doexpand = redir = inc = 0;
-
- while (cont && elast) {
- int cstat = cmd_stat(command);
-
- ptr = exarg(&nextstr);
- inc = 1;
- arg = "";
- cont = (elast == 0x80);
- switch (*ptr) {
- case '<':
- redir = -2;
- case '>':
- if (cstat & (ST_NORED | ST_COND)) {
- /* don't extract */
- redir = 0; /* <> stuff if its */
- arg = ptr; /* external cmd. */
- break;
- }
- ++redir;
- arg = ptr + 1;
- if (*arg == '>') {
- redir = 2; /* append >> */
- ++arg;
- }
- cont = 1;
- break;
- case '$':
- /* restore args if from set command or pend_alias */
- if ((arg = get_var(LEVEL_SET, ptr + 1)) != NULL) {
- if (cstat & ST_COND) {
- char *tp;
- tp = push_cpy(arg);
- arg = tp;
- }
- else {
- char *pe, sv, *index();
- while (pe = index(arg,0xA0)) {
- sv = *pe;
- *pe = '\0';
- av[ac++] = push_cpy(arg);
- *pe = sv;
- av[ac] = '\0';
- arg = pe+1;
- }
- }
- }
- else
- arg = ptr;
- break;
- case '*':
- case '?':
- if ((cstat & ST_NOEXP) == 0)
- doexpand = 1;
- arg = ptr;
- break;
- default:
- arg = ptr;
- break;
- }
-
- /* Append arg to av[ac] */
-
- for (scr = arg; *scr; ++scr)
- *scr &= 0x7F;
- if (av[ac]) {
- register char *old = av[ac];
- av[ac] = mpush(strlen(arg)+strlen(av[ac]));
- strcpy(av[ac], old);
- strcat(av[ac], arg);
- } else {
- av[ac] = push_cpy(arg);
- }
- if (elast != 0x80)
- break;
- }
-
- /* process expansion */
-
- if (doexpand) {
- char **eav, **ebase;
- int eac;
- has_wild = 1;
- eav = ebase = expand(av[ac], &eac);
- inc = 0;
- if (eav) {
- if (ac + eac + 2 > MAXAV) {
- ierror (NULL, 506);
- err = 1;
- } else {
- QuickSort(eav, eac);
- for (; eac; --eac, ++eav)
- av[ac++] = push_cpy(*eav);
- }
- free_expand (ebase);
- }
- }
-
- /* process redirection */
-
- if (redir && !err) {
- register char *file = (doexpand) ? av[--ac] : av[ac];
-
- if (redir < 0)
- Cin_name = file;
- else {
- Cout_name = file;
- Cout_append = (redir == 2);
- }
- inc = 0;
- }
-
- /* check elast for space */
-
- if (inc) {
- ++ac;
- if (ac + 2 > MAXAV) {
- ierror (NULL, 506);
- err = 1; /* error condition */
- elast = 0; /* don't process any more arguemnts */
- }
- }
- if (elast == ' ')
- goto step5;
- }
- stepdone:
- av[ac] = '\0';
-
- /* process pipes via files */
-
- if (elast == '|' && !err) {
- static int which; /* 0 or 1 in case of multiple pipes */
- which = 1 - which;
- Cout_name = (which) ? Pipe1 : Pipe2;
- Cout_ispipe = 1;
- }
-
-
- if (err)
- goto done0;
-
- {
- register int i;
- char save_elast;
- char *compile_av();
- register char *avline;
- unsigned char delim = ' ';
-
- save_elast = elast;
- if (pend_alias || (cmd_stat(command) & ST_AV))
- delim = 0xA0;
- avline = compile_av(av,((pend_alias) ? 1 : 0), ac , delim);
-
-
- if (pend_alias) { /* special % alias */
- register char *ptr, *scr;
- for (ptr = pend_alias; *ptr && *ptr != ' '; ++ptr);
- set_var (LEVEL_SET, pend_alias + 1, avline);
- free (avline);
-
- scr = malloc((strlen(ptr) << 2) + 2);
- preformat (ptr, scr);
- fcomm (scr, 1);
- unset_var (LEVEL_SET, pend_alias + 1);
- } else { /* normal command */
- register int ccno;
- long oldcin = Myprocess->pr_CIS;
- long oldcout = Myprocess->pr_COS;
- char *Cin_buf;
- struct FileHandle *ci;
- long oldbuf;
-
- fflush(stdout);
- ccno = find_command (command);
- if ((Command[ccno].stat & (ST_NORED | ST_COND)) == 0) {
- if (Cin_name) {
- if ((Cin = (long)extOpen(Cin_name,1005L)) == 0L) {
- ierror (NULL, 504);
- err = 1;
- Cin_name = '\0';
- } else {
- Myprocess->pr_CIS = _devtab[stdin->_unit].fd = Cin;
- ci = (struct FileHandle *)(((long)Cin)<<2);
- Cin_buf = (char *)AllocMem(202L, MEMF_PUBLIC);
- oldbuf = ci->fh_Buf;
- if (ci->fh_Buf == 0) /* fexec expects a CIS buffer */
- ci->fh_Buf = (long)Cin_buf>>2;
- }
- }
- if (Cout_name) {
- if (Cout_append && (Cout =(long)extOpen(Cout_name, 1005L)) ) {
- Seek(Cout, 0L, 1L);
- } else {
- Cout = (long)extOpen(Cout_name,1006L);
- }
- if (Cout == NULL) {
- err = 1;
- ierror (NULL, 504);
- Cout_name = '\0';
- Cout_append = 0;
- } else {
- Myprocess->pr_COS = _devtab[stdout->_unit].fd = Cout;
- }
- }
- }
- if (ac < Command[ccno].minargs + 1) {
- ierror (NULL, 500);
- err = -1;
- } else if (!err) {
- i = (*Command[ccno].func)(avline, Command[ccno].val);
- if (i < 0)
- i = 20;
- err = i;
- }
- free (avline);
- if (E_stack == 0 && Lastresult != err) {
- Lastresult = err;
- seterr();
- }
- if ((Command[ccno].stat & (ST_NORED | ST_COND)) == 0) {
- if (Cin_name) {
- fflush(stdin);
- clearerr(stdin);
- ci->fh_Buf = oldbuf;
- extClose(Cin);
- FreeMem(Cin_buf, 202L);
- }
- if (Cout_name) {
- fflush(stdout);
- clearerr(stdout);
- stdout->_flags &= ~_DIRTY; /* because of nil: device */
- extClose(Cout);
- Cout_append = 0;
- }
- }
- Myprocess->pr_CIS = _devtab[stdin->_unit].fd = oldcin;
- Myprocess->pr_COS = _devtab[stdout->_unit].fd = oldcout;
- }
-
- if (Cin_ispipe && Cin_name)
- DeleteFile(Cin_name);
- if (Cout_ispipe) {
- Cin_name = Cout_name; /* ok to assign.. static name */
- Cin_ispipe = 1;
- } else {
- Cin_name = '\0';
- }
- Cout_name = '\0';
- Cout_ispipe = 0;
- elast = save_elast;
- }
- mpop_tobase(); /* free arguments */
- mpush_base(); /* push dummy base */
-
- done0:
- {
- char *str;
- if (err && E_stack == 0) {
- str = get_var(LEVEL_SET, v_except);
- if (err >= ((str)?atoi(str):1)) {
- if (str) {
- ++H_stack;
- ++E_stack;
- exec_command(str);
- --E_stack;
- --H_stack;
- } else {
- Exec_abortline = 1;
- }
- }
- }
- if (elast != 0 && Exec_abortline == 0)
- err = fcomm(nextstr, 0);
- Exec_abortline = 0;
- if (Cin_name)
- DeleteFile(Cin_name);
- Cin_name = NULL;
- Cin_ispipe = 0;
- }
- done1:
- mpop_tobase();
- if (freeok)
- free(str);
- --alias_count;
- return ((int)err); /* TRUE = error occured */
- }
-
-
- char *
- exarg(ptr)
- unsigned char **ptr;
- {
- register unsigned char *end;
- register unsigned char *start;
-
- start = end = *ptr;
- while (*end && *end != 0x80 && *end != ';' && *end != '|' && *end != ' ')
- ++end;
- elast = *end;
- *end = '\0';
- *ptr = end + 1;
- return ((char *)start);
- }
-
- static char **Mlist;
-
- mpush_base()
- {
- char *str;
-
- str = malloc(5);
- *(char ***)str = Mlist;
- str[4] = 0;
- Mlist = (char **)str;
- }
-
- char *
- mpush(bytes)
- {
- char *str;
-
- str = malloc(6 + bytes + 2); /* may need extra 2 bytes in do_run() */
- *(char ***)str = Mlist;
- str[4] = 1;
- Mlist = (char **)str;
- return (str + 5);
- }
-
- mpop_tobase()
- {
- register char *next;
- while (Mlist) {
- next = *Mlist;
- if (((char *)Mlist)[4] == 0) {
- free (Mlist);
- Mlist = (char **)next;
- break;
- }
- free (Mlist);
- Mlist = (char **)next;
- }
- }
-
-
- /*
- * Insert 'from' string in front of 'str' while deleting the
- * first entry in 'str'. if freeok is set, then 'str' will be
- * free'd
- */
-
-
-
- char *
- format_insert_string(str, from, freeok)
- char *str;
- char *from;
- int *freeok;
- {
- register char *new1, *new2;
- register unsigned char *strskip;
- int len;
-
- for (strskip = (unsigned char *)str;
- *strskip && *strskip != ' '
- && *strskip != ';' && *strskip != '|'
- && *strskip != 0x80; ++strskip);
- len = strlen(from);
- new1 = malloc((len << 2) + 2);
- preformat(from, new1);
- len = strlen(new1) + strlen(strskip);
- new2 = malloc(len+2);
- strcpy(new2, new1);
- strcat(new2, strskip);
- new2[len+1] = 0;
- free (new1);
- if (*freeok)
- free (str);
- *freeok = 1;
- return (new2);
- }
-
- cmd_stat(str)
- char *str;
- {
- return(Command[find_command(str)].stat);
- }
-
- find_command(str)
- char *str;
- {
- register unsigned 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)
- return (i);
- }
- return (0);
- }
-
- do_help()
- {
- register struct COMMAND *com;
- int i= 0;
-
-
- for (com = &Command[2]; com->func; ++com) {
- printf ("%-12s", com->name);
- if (++i % 6 == 0) printf("\n");
- }
- printf("\n");
- return(0);
- }
-
- char *push_cpy(s)
- char *s;
- {
- return strcpy(mpush(strlen(s)), s);
- }
-