Amiga-Request@cs.odu.edu (Amiga Sources/Binaries Moderator) (01/16/90)
Submitted-by: PERUGIA@ICNUCEVM.CNUCE.CNR.IT (Carlo & Cesare) Posting-number: Volume 90, Issue 016 Archive-name: unix/cshell-4.00a/part03 #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of archive 3 (of 4)." # Contents: execom.c # Wrapped by tadguy@xanth on Mon Jan 15 11:28:11 1990 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'execom.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'execom.c'\" else echo shar: Extracting \"'execom.c'\" \(19280 characters\) sed "s/^X//" >'execom.c' <<'END_OF_FILE' X/* X * EXECOM.C X * X * Matthew Dillon, 10 August 1986 X * Finally re-written. X * X * Version 2.07M by Steve Drew 10-Sep-87 X * X * Version 4.00A by Carlo Borreo & Cesare Dieni 13-Jan-90 X * X */ X X#define F_EXACT 0 X#define F_ABBR 1 X X#define ST_COND 0x01 X#define ST_NORED 0x02 X#define ST_NOEXP 0x04 X#define ST_AV 0x08 /* delimit args within a variable */ X Xint has_wild = 0; /* set if any arg has wild card */ X Xstruct COMMAND { X int (*func)(); X short minargs; X short stat; X int val; X char *name; X}; X Xextern char *format_insert_string(); Xextern char *mpush(), *exarg(); X Xextern int do_basename(), do_tackon(); Xextern int do_fltupper(), do_fltlower(); Xextern int do_strleft(), do_strright(), do_strmid(), do_strlen(); Xextern int do_fornum(), do_forline(), do_exec(); Xextern int do_diskchange(), do_stack(), do_fault(), do_path(), do_pri(); Xextern int do_rpn(), do_resident(), do_truerun(), do_aset(), do_howmany(); Xextern int do_open(), do_close(), do_fileslist(), do_htype(); Xextern int do_run(), do_number(), do_assign(), do_join(); Xextern int do_quit(), do_set_var(), do_unset_var(); Xextern int do_echo(), do_source(), do_mv(), do_addbuffers(); Xextern int do_cd(), do_pwd(), do_rm(), do_mkdir(), do_history(); Xextern int do_mem(), do_cat(), do_dir(), do_info(), do_inc(); Xextern int do_foreach(), do_return(), do_if(), do_label(), do_goto(); Xextern int do_input(), do_ver(), do_sleep(), do_help(); Xextern int do_strhead(), do_strtail(), do_relabel(); Xextern int do_copy(), do_date(), do_protect(), do_ps(); Xextern int do_forever(), do_abortline(), do_strings(), do_touch(); Xextern int do_window(), do_search(), do_filenote(), do_rxrec(), do_rxsend(); Xchar *push_cpy(); X Xstatic struct COMMAND Command[] = { Xdo_run, 0, ST_AV, 0, "\001", /* may call do_source */ Xdo_abortline, 0, 0, 0, "abortline", Xdo_addbuffers, 2, 0, 0, "addbuffers", Xdo_set_var, 0, 0, LEVEL_ALIAS, "alias", /* uses avline */ Xdo_aset, 1, 0, 0, "aset", Xdo_assign, 0, 0, 0, "assign", Xdo_basename, 2, 0, 0, "basename", Xdo_cat, 0, 0, 0, "cat", Xdo_cd, 0, 0, 0, "cd", Xdo_close, 0, 0, 0, "close", Xdo_copy, 1, 0, 0, "copy", Xdo_copy, 1, 0, 0, "cp", Xdo_date, 0, 0, 0, "date", Xdo_inc, 1, 0, -1, "dec", Xdo_rm, 0, 0, 0, "delete", Xdo_dir, 0, ST_NOEXP, 0, "dir", Xdo_diskchange, 1, 0, 0, "diskchange", Xdo_echo, 0, 0, 0, "echo", /* uses avline */ Xdo_if, 0, ST_COND, 1, "else", Xdo_if, 0, ST_COND, 2, "endif", Xdo_exec, 1, 0, 0, "exec", Xdo_fault, 1, 0, 0, "fault", Xdo_filenote, 2, 0, 0, "filenote", Xdo_fileslist, 0, 0, 0, "flist", Xdo_fltlower, 0, 0, 0, "fltlower", Xdo_fltupper, 0, 0, 0, "fltupper", Xdo_foreach, 3, ST_NORED, 0, "foreach", Xdo_forever, 1, ST_NORED, 0, "forever", Xdo_forline, 3, ST_NORED, 0, "forline", Xdo_fornum, 4, ST_NORED, 0, "fornum", Xdo_goto, 1, 0, 0, "goto", Xdo_help, 0, 0, 0, "help", Xdo_history, 0, 0, 0, "history", Xdo_howmany, 0, 0, 0, "howmany", Xdo_htype, 1, 0, 0, "htype", Xdo_if, 1, ST_COND|ST_NORED,0, "if", Xdo_inc, 1, 0, 1, "inc", Xdo_info, 0, 0, 0, "info", Xdo_input, 1, 0, 0, "input", Xdo_join, 2, 0, 1, "join", Xdo_label, 1, ST_COND, 0, "label", Xdo_dir, 0, ST_NOEXP, 0, "ls", Xdo_mkdir, 0, 0, 0, "md", Xdo_mem, 0, 0, 0, "mem", Xdo_mkdir, 0, 0, 0, "mkdir", Xdo_mv, 2, 0, 0, "mv", Xdo_open, 3, 0, 0, "open", Xdo_path, 0, 0, 0, "path", Xdo_pri, 2, 0, 0, "pri", Xdo_protect, 2, 0, 0, "protect", Xdo_ps, 0, 0, 0, "ps", Xdo_pwd, 0, 0, 0, "pwd", Xdo_quit, 0, ST_NORED, 0, "quit", Xdo_truerun, 1, ST_NORED, 1, "rback", Xdo_mv, 2, 0, 0, "rename", Xdo_relabel, 2, 0, 0, "relabel", Xdo_resident, 0, 0, 0, "resident", Xdo_return, 0, 0, 0, "return", Xdo_rm, 0, 0, 0, "rm", Xdo_rpn, 0, ST_NOEXP|ST_NORED,0, "rpn", Xdo_rxrec, 1, 0, 0, "rxrec", Xdo_rxsend, 2, 0, 0, "rxsend", Xdo_truerun, 1, ST_NORED, 0, "run", Xdo_search, 2, 0, 0, "search", Xdo_set_var, 0, ST_AV, LEVEL_SET, "set", Xdo_sleep, 0, 0, 0, "sleep", Xdo_source, 0, ST_NORED|ST_AV, 0, "source", /* uses avline */ Xdo_stack, 0, 0, 0, "stack", Xdo_strhead, 3, 0, 0, "strhead", Xdo_strings, 1, 0, 0, "strings", Xdo_strleft, 3, 0, 0, "strleft", Xdo_strlen, 2, 0, 0, "strlen", Xdo_strmid, 3, 0, 0, "strmid", Xdo_strright, 3, 0, 0, "strright", Xdo_strtail, 3, 0, 0, "strtail", Xdo_tackon, 3, 0, 0, "tackon", Xdo_touch, 0, 0, 0, "touch", Xdo_cat, 0, 0, 0, "type", Xdo_unset_var, 0, 0, LEVEL_ALIAS, "unalias", Xdo_unset_var, 0, 0, LEVEL_SET , "unset", Xdo_ver, 0, 0, 0, "version", Xdo_window, 0, ST_NOEXP, 0, "window", X'\0', 0, 0, 0, NULL X}; X Xstatic unsigned char elast; /* last end delimeter */ Xstatic char Cin_ispipe, Cout_ispipe; X Xexec_command(base) Xchar *base; X{ Xregister char *scr; Xchar buf[32]; X Xif (!H_stack) { X add_history(base); X sprintf(buf, "%d", H_tail_base + H_len); X set_var(LEVEL_SET, v_histnum, buf); X } Xscr = malloc((strlen(base) << 2) + 2); Xpreformat(base, scr); Xreturn (fcomm(scr, 1) ? -1 : 1); X} X Xisalphanum(c) Xregister char c; X{ Xreturn ( X (c >= '0' && c <= '9') || X (c >= 'a' && c <= 'z') || X (c >= 'A' && c <= 'Z') || X (c == '_') X ); X} X Xpreformat(s, d) Xregister char *s, *d; X{ Xregister int si, di, qm; X Xsi = di = qm = 0; Xwhile (s[si] == ' ' || s[si] == 9) ++si; Xwhile (s[si]) { X if (qm && s[si] != '\"' && s[si] != '\\') { X d[di++] = s[si++] | 0x80; X continue; X } X switch (s[si]) { X case ' ': X case 9: X d[di++] = ' '; X while (s[si] == ' ' || s[si] == 9) ++si; X if (s[si] == 0 || s[si] == '|' || s[si] == ';') --di; X break; X case '*': X case '?': X d[di++] = 0x80; X case '!': X d[di++] = s[si++]; X break; X case '#': X d[di++] = '\0'; X while (s[si]) ++si; X break; X case ';': X case '|': X d[di++] = s[si++]; X while (s[si] == ' ' || s[si] == 9) ++si; X break; X case '\\': X d[di++] = s[++si] | 0x80; X if (s[si]) ++si; X break; X case '\"': X qm = 1 - qm; X ++si; X break; X case '^': X d[di++] = s[++si] & 0x1F; X if (s[si]) ++si; X break; X case '$': /* search end of var name and place false space */ X d[di++] = 0x80; X d[di++] = s[si++]; X while (isalphanum(s[si])) d[di++] = s[si++]; X d[di++] = 0x80; X break; X default: X d[di++] = s[si++]; X break; X } X } Xd[di++]=0; Xd[di]=0; Xif (debug) fprintf (stderr,"PREFORMAT: %d :%s:\n", strlen(d), d); X} X Xextern BPTR extOpen(); X X/* X * process formatted string. ' ' is the delimeter. X * X * 0: check '\0': no more, stop, done. X * 1: check $. if so, extract, format, insert X * 2: check alias. if so, extract, format, insert. goto 1 X * 3: check history or substitution, extract, format, insert. goto 1 X * X * 4: assume first element now internal or disk based command. X * X * 5: extract each ' ' or 0x80 delimited argument and process, placing X * in av[] list (except 0x80 args appended). check in order: X * X * '$' insert string straight X * '>' setup stdout X * '>>' setup stdout flag for append X * '<' setup stdin X * '*' or '?' do directory search and insert as separate args. X * X * ';' 0 '|' end of command. if '|' setup stdout X * -execute command, fix stdin and out (|) sets X * up stdin for next guy. X */ X X Xfcomm(str, freeok) Xregister char *str; X{ X static int alias_count; X int p_alias_count = 0; X char *istr; X char *nextstr; X char *command; X char *pend_alias = NULL; X char err = 0; X has_wild = 0; X X ++alias_count; X X mpush_base(); X if (*str == 0) X goto done1; Xstep1: X if (alias_count == MAXALIAS || ++p_alias_count == MAXALIAS) { X fprintf(stderr,"Alias Loop\n"); X err = 20; X goto done1; X } X/* X if (str[1] == '$') { X if (istr = get_var (LEVEL_SET, str + 2)) X str = format_insert_string(str, istr, &freeok); X } X*/ X istr = NULL; X if (*(unsigned char *)str < 0x80) X istr = get_var (LEVEL_ALIAS, str); /* only if not \command */ X *str &= 0x7F; /* remove \ teltail */ X if (istr) { X if (*istr == '%') { X pend_alias = istr; X } else { X str = format_insert_string(str, istr, &freeok); X goto step1; X } X } X if (*str == '!') { X char *p, c; /* fix to allow !cmd1;!cmd2 */ X for(p = str; *p && *p != ';' ; ++p); X c = *p; X *p = '\0'; X istr = get_history(str); X *p = c; X replace_head(istr); X str = format_insert_string(str, istr, &freeok); X goto step1; X } X nextstr = str; X command = exarg(&nextstr); X if (*command == 0) X goto done0; X if (pend_alias == 0) { X if (cmd_stat(command) & ST_COND) X goto skipgood; X } X if (disable || forward_goto) { X while (elast && elast != ';' && elast != '|') X exarg(&nextstr); X goto done0; X } Xskipgood: X { X register char *arg, *ptr, *scr; X short redir; X short doexpand; X short cont; X short inc; X X ac = 1; X av[0] = command; Xstep5: /* ac = nextac */ X if (!elast || elast == ';' || elast == '|') X goto stepdone; X X av[ac] = '\0'; X cont = 1; X doexpand = redir = inc = 0; X X while (cont && elast) { X int cstat = cmd_stat(command); X X ptr = exarg(&nextstr); X inc = 1; X arg = ""; X cont = (elast == 0x80); X switch (*ptr) { X case '<': X redir = -2; X case '>': X if (cstat & (ST_NORED | ST_COND)) { X /* don't extract */ X redir = 0; /* <> stuff if its */ X arg = ptr; /* external cmd. */ X break; X } X ++redir; X arg = ptr + 1; X if (*arg == '>') { X redir = 2; /* append >> */ X ++arg; X } X cont = 1; X break; X case '$': X /* restore args if from set command or pend_alias */ X if ((arg = get_var(LEVEL_SET, ptr + 1)) != NULL) { X if (cstat & ST_COND) { X char *tp; X tp = push_cpy(arg); X arg = tp; X } X else { X char *pe, sv; X while (pe = index(arg,0xA0)) { X sv = *pe; X *pe = '\0'; X av[ac++] = push_cpy(arg); X *pe = sv; X av[ac] = '\0'; X arg = pe+1; X } X } X } X else X arg = ptr; X break; X case '*': X case '?': X if ((cstat & ST_NOEXP) == 0) X doexpand = 1; X arg = ptr; X break; X default: X arg = ptr; X break; X } X X /* Append arg to av[ac] */ X X for (scr = arg; *scr; ++scr) X *scr &= 0x7F; X if (av[ac]) { X register char *old = av[ac]; X av[ac] = mpush(strlen(arg)+strlen(av[ac])); X strcpy(av[ac], old); X strcat(av[ac], arg); X } else { X av[ac] = push_cpy(arg); X } X if (elast != 0x80) X break; X } X X /* process expansion */ X X if (doexpand) { X char **eav, **ebase; X int eac; X has_wild = 1; X eav = ebase = expand(av[ac], &eac); X inc = 0; X if (eav) { X if (ac + eac + 2 > MAXAV) { X ierror (NULL, 506); X err = 1; X } else { X QuickSort(eav, eac); X for (; eac; --eac, ++eav) X av[ac++] = push_cpy(*eav); X } X free_expand (ebase); X } X } X X /* process redirection */ X X if (redir && !err) { X register char *file = (doexpand) ? av[--ac] : av[ac]; X X if (redir < 0) X Cin_name = file; X else { X Cout_name = file; X Cout_append = (redir == 2); X } X inc = 0; X } X X /* check elast for space */ X X if (inc) { X ++ac; X if (ac + 2 > MAXAV) { X ierror (NULL, 506); X err = 1; /* error condition */ X elast = 0; /* don't process any more arguemnts */ X } X } X if (elast == ' ') X goto step5; X } Xstepdone: X av[ac] = '\0'; X X /* process pipes via files */ X X if (elast == '|' && !err) { X static int which; /* 0 or 1 in case of multiple pipes */ X which = 1 - which; X Cout_name = (which) ? Pipe1 : Pipe2; X Cout_ispipe = 1; X } X X X if (err) X goto done0; X X { X register int i; X char save_elast; X char *compile_av(); X register char *avline; X unsigned char delim = ' '; X X save_elast = elast; X if (pend_alias || (cmd_stat(command) & ST_AV)) X delim = 0xA0; X avline = compile_av(av,((pend_alias) ? 1 : 0), ac, delim, 0); X X if (pend_alias) { /* special % alias */ X register char *ptr, *scr; X for (ptr = pend_alias; *ptr && *ptr != ' '; ++ptr); X set_var (LEVEL_SET, pend_alias + 1, avline); X free (avline); X X scr = malloc((strlen(ptr) << 2) + 2); X preformat (ptr, scr); X fcomm (scr, 1); X unset_var (LEVEL_SET, pend_alias + 1); X } else { /* normal command */ X register int ccno; X long oldcin = Myprocess->pr_CIS; X long oldcout = Myprocess->pr_COS; X char *Cin_buf; X struct FileHandle *ci; X long oldbuf; X X fflush(stdout); X ccno = find_command (command); X if ((Command[ccno].stat & (ST_NORED | ST_COND)) == 0) { X if (Cin_name) { X if ((Cin = (long)extOpen(Cin_name,1005L)) == 0L) { X ierror (NULL, 504); X err = 1; X Cin_name = '\0'; X } else { X Myprocess->pr_CIS = _devtab[stdin->_unit].fd = Cin; X ci = (struct FileHandle *)(((long)Cin)<<2); X Cin_buf = (char *)AllocMem(202L, MEMF_PUBLIC); X oldbuf = ci->fh_Buf; X if (ci->fh_Buf == 0) /* fexec expects a CIS buffer */ X ci->fh_Buf = (long)Cin_buf>>2; X } X } X if (Cout_name) { X if (Cout_append && (Cout =(long)extOpen(Cout_name, 1005L)) ) { X Seek(Cout, 0L, 1L); X } else { X Cout = (long)extOpen(Cout_name,1006L); X } X if (Cout == NULL) { X err = 1; X ierror (NULL, 504); X Cout_name = '\0'; X Cout_append = 0; X } else { X Myprocess->pr_COS = _devtab[stdout->_unit].fd = Cout; X } X } X } X if (ac < Command[ccno].minargs + 1) { X ierror (NULL, 500); X err = -1; X } else if (!err) { X i = (*Command[ccno].func)(avline, Command[ccno].val); X if (i < 0) X i = 20; X err = i; X } X free (avline); X if (E_stack == 0 && Lastresult != err) { X Lastresult = err; X seterr(); X } X if ((Command[ccno].stat & (ST_NORED | ST_COND)) == 0) { X if (Cin_name) { X fflush(stdin); X clearerr(stdin); X ci->fh_Buf = oldbuf; X extClose(Cin); X FreeMem(Cin_buf, 202L); X } X if (Cout_name) { X fflush(stdout); X clearerr(stdout); X stdout->_flags &= ~_DIRTY; /* because of nil: device */ X extClose(Cout); X Cout_append = 0; X } X } X Myprocess->pr_CIS = _devtab[stdin->_unit].fd = oldcin; X Myprocess->pr_COS = _devtab[stdout->_unit].fd = oldcout; X } X X if (Cin_ispipe && Cin_name) X DeleteFile(Cin_name); X if (Cout_ispipe) { X Cin_name = Cout_name; /* ok to assign.. static name */ X Cin_ispipe = 1; X } else { X Cin_name = '\0'; X } X Cout_name = '\0'; X Cout_ispipe = 0; X elast = save_elast; X } X mpop_tobase(); /* free arguments */ X mpush_base(); /* push dummy base */ X Xdone0: X { X char *str; X if (err && E_stack == 0) { X str = get_var(LEVEL_SET, v_except); X if (err >= ((str)?atoi(str):1)) { X if (str) { X ++H_stack; X ++E_stack; X exec_command(str); X --E_stack; X --H_stack; X } else { X Exec_abortline = 1; X } X } X } X if (elast != 0 && Exec_abortline == 0) X err = fcomm(nextstr, 0); X Exec_abortline = 0; X if (Cin_name) X DeleteFile(Cin_name); X Cin_name = NULL; X Cin_ispipe = 0; X } Xdone1: X mpop_tobase(); X if (freeok) X free(str); X --alias_count; X return ((int)err); /* TRUE = error occured */ X} X X Xchar * Xexarg(ptr) Xunsigned char **ptr; X{ X register unsigned char *end; X register unsigned char *start; X X start = end = *ptr; X while (*end && *end != 0x80 && *end != ';' && *end != '|' && *end != ' ') X ++end; X elast = *end; X *end = '\0'; X *ptr = end + 1; X return ((char *)start); X} X Xstatic char **Mlist; X Xmpush_base() X{ X char *str; X X str = malloc(5); X *(char ***)str = Mlist; X str[4] = 0; X Mlist = (char **)str; X} X Xchar * Xmpush(bytes) X{ X char *str; X X str = malloc(6 + bytes + 2); /* may need extra 2 bytes in do_run() */ X *(char ***)str = Mlist; X str[4] = 1; X Mlist = (char **)str; X return (str + 5); X} X Xmpop_tobase() X{ X register char *next; X while (Mlist) { X next = *Mlist; X if (((char *)Mlist)[4] == 0) { X free (Mlist); X Mlist = (char **)next; X break; X } X free (Mlist); X Mlist = (char **)next; X } X} X X X/* X * Insert 'from' string in front of 'str' while deleting the X * first entry in 'str'. if freeok is set, then 'str' will be X * free'd X */ X Xchar *format_insert_string(str, from, freeok) Xchar *str; Xchar *from; Xint *freeok; X{ Xregister char *new1, *new2; Xregister unsigned char *strskip; Xint len; X Xfor (strskip = (unsigned char *)str; X *strskip && *strskip != ' ' X && *strskip != ';' && *strskip != '|' X && *strskip != 0x80; ++strskip); Xlen = strlen(from); Xnew1 = malloc((len << 2) + 2); Xpreformat(from, new1); Xlen = strlen(new1) + strlen(strskip); Xnew2 = malloc(len+2); Xstrcpy(new2, new1); Xstrcat(new2, strskip); Xnew2[len+1] = 0; Xfree (new1); Xif (*freeok) free (str); X*freeok = 1; Xreturn new2; X} X Xcmd_stat(str) Xchar *str; X{ Xreturn(Command[find_command(str)].stat); X} X Xfind_command(str) Xchar *str; X{ Xregister unsigned short i; Xint len = strlen(str); X Xfor (i = 0; Command[i].func; ++i) X if ( ! strncmp(str, Command[i].name, len)) return (int)i; Xreturn 0; X} X Xdo_help() X{ Xregister struct COMMAND *com; Xint i=0; X Xfor (com = &Command[1]; com->func; ++com) { X printf ("%-12s", com->name); X if (++i % 6 == 0) printf("\n"); X } Xprintf("\n"); Xreturn 0; X} X Xchar *push_cpy(s) Xchar *s; X{ Xreturn strcpy(mpush(strlen(s)), s); X} END_OF_FILE if test 19280 -ne `wc -c <'execom.c'`; then echo shar: \"'execom.c'\" unpacked with wrong size! fi # end of 'execom.c' fi echo shar: End of archive 3 \(of 4\). cp /dev/null ark3isdone MISSING="" for I in 1 2 3 4 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 4 archives. rm -f ark[1-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0 -- Submissions to comp.sources.amiga and comp.binaries.amiga should be sent to: amiga@cs.odu.edu or amiga@xanth.cs.odu.edu ( obsolescent mailers may need this address ) or ...!uunet!xanth!amiga ( very obsolescent mailers need this address ) Comments, questions, and suggestions s should be addressed to ``amiga-request'' (only use ``amiga'' for submissions) at the above addresses.