home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / alib / d5xx / d512 / csh.lha / Csh / Csh515s.lzh / execom.c < prev    next >
C/C++ Source or Header  |  1991-06-23  |  38KB  |  1,495 lines

  1. /*
  2.  * EXECOM.C
  3.  *
  4.  * Matthew Dillon, 10 August 1986
  5.  * Version 2.07M by Steve Drew 10-Sep-87
  6.  * Version 4.01A by Carlo Borreo & Cesare Dieni 17-Feb-90
  7.  * Version 5.00L by Urban Mueller 17-Feb-91
  8.  *
  9.  */
  10.  
  11. #include "shell.h"
  12.  
  13. #define DEFAULTFRAME 1024
  14. #define Strlen(x)   strlen((char*)x)
  15. #define Strcpy(x,y) strcpy((char*)x,(char*)y)
  16. #define Strcat(x,y) strcat((char*)x,(char*)y)
  17. #define Index(x,y)  ((UBYTE*)index((char*)x,y))
  18.  
  19. typedef struct StackFrame {
  20.     struct StackFrame *next;
  21.     int  bytesleft;
  22.     char *ptr;
  23.     char mem[1];
  24. } FRAME;
  25.  
  26. /* execom.c */
  27. static char *compile_avf(FRAME **frame,char **av,int start,int end,char delim,int quote);
  28. static int   hasspace( char *s );
  29. static void  preformat(char *s, UBYTE *d);
  30. static void  backtrans(UBYTE *str);
  31. static int   fcomm(UBYTE *str,FRAME **frame,char *from );
  32. static UBYTE *exarg(UBYTE **ptr, UBYTE *elast);
  33. static UBYTE *format_insert_string(FRAME **frameptr, UBYTE *str, char *from);
  34. static int   find_command(char *str);
  35. static void  exec_every(void);
  36. static int   checkav( FRAME **frame,int n );
  37. static char  *tempname( int which );
  38. static UBYTE *skipword( UBYTE *strskip );
  39. static int   myfgets( char *buf, FILE *in );
  40.  
  41. static void  newframe( FRAME **frame, int bytes);
  42. static void  *falloc( FRAME **frame, int bytes );
  43. static void  *frealloc( FRAME **frame, char *oldstring, int morebytes );
  44. static void  funalloc( FRAME **frame, int bytes );
  45. static char  *push_cpy( FRAME **frame, void *s);
  46. static void  deleteframe( FRAME *frame);
  47.  
  48. int do_nothing(void);
  49.  
  50. struct COMMAND {
  51.     int (*func)();
  52.     short minargs;
  53.     short stat;
  54.     int val;
  55.     char *name;
  56.     char *options;
  57.     char *usage;
  58. };
  59.  
  60. #define ST_COND   0x01
  61. #define ST_NORED  0x02
  62. #define ST_NOEXP  0x04
  63. #define ST_AV     0x08 /* delimit args within a variable */
  64. #define ST_FUNC   0x10
  65. #define ST_EQUAL  0x20
  66.  
  67. #define COND  ST_COND
  68. #define NORED ST_NORED
  69. #define NOEXP ST_NOEXP
  70. #define AV    ST_AV
  71. #define FUNC  ST_FUNC
  72. #define EQUAL ST_EQUAL
  73.  
  74. #define ALIAS LEVEL_ALIAS
  75. #define SET   LEVEL_SET
  76. #define LOCAL LEVEL_LOCAL
  77.  
  78. #define FIRSTCOMMAND 4
  79. #define COM_EXEC 3
  80.  
  81. struct COMMAND Command[] = {
  82.  do_run,       0,   AV,     0, "\001",       NULL, NULL, /* may call do_source, do_cd */
  83.  do_nothing,   0,    0,     0, "\002",       NULL, NULL, /* dummy for aliases   */
  84.  do_nothing,   0,    0,     0, "\003",       NULL, NULL, /* dummy for aliases with args */
  85.  do_run,       0,NORED|AV,  1, "\004",       NULL, NULL, /* external that needs to be Execute()d */
  86.  do_abortline, 0,    0,     0, "abortline",  NULL, "",
  87.  do_action,    2,    0,     9, "action",     "av", "action file [args]",
  88.  do_addbuffers,2,    0,     0, "addbuffers", NULL, "{drive bufs}",
  89.  do_set_var,   0,    0, ALIAS, "alias",      NULL, "[name [string] ]",/* uses avline */
  90.  do_ascii,     0,    0,     0, "ascii",      "oh", "-oh [string]",
  91.  do_aset,      1,    0,     0, "aset",       NULL, "name value",
  92.  do_assign,    0,    0,     0, "assign",     "lnp",",logical,-lnp {logical physical}",
  93.  do_basename,  2, FUNC,     0, "basename",   NULL, "var path",
  94.  do_cat,       0,    0,     0, "cat",        "n",  "-n [file file...]",
  95.  do_cd,        0,    0,     0, "cd",         "g",  "[path],-g path...path",
  96.  do_class,     0,   AV,     0, "class",      "n",  "-n name {type=param} \"actions\" {action=command}",
  97.  do_close,     0,    0,     0, "close",      NULL, "filenumber",
  98.  do_copy,      1,    0,     0, "copy",       "rudpfm","-dfmpru file file,-ud file...file dir,-ud dir...dir dir",
  99.  do_copy,      1,    0,     0, "cp",         "rudpfm","-dfmpru file file,-ud file...file dir,-ud dir...dir dir",
  100.  do_date,      0,    0,     0, "date",       "sr", "-sr [date/time]",
  101.  do_inc,       1,    0,    -1, "dec",        NULL, "varname [step]",
  102.  do_rm,        0,    0,     0, "delete",     "rpq","-pqr file...file",
  103.  do_dir,       0,NOEXP,     0, "dir",        "sfdcnhltbuikqavopzeg","-abcdefghiklnopqstuv [-z lformat] [path...path]",
  104.  do_diskchange,1,    0,     0, "diskchange", NULL, "drive",
  105.  do_echo,      0,   AV,     0, "echo",       "ne", "-ne string",
  106.  do_if,        0, COND,     1, "else",       NULL, "",
  107.  do_if,        0, COND,     2, "endif",      NULL, "",
  108.  do_error,     1,    0,     0, "error",      NULL, "num",
  109.  do_exec,      1,    0,     0, "exec",       "i",  "-i command",
  110.  do_fault,     1,    0,     0, "fault",      NULL, "error",
  111.  do_filenote,  1,    0,     0, "filenote",   "s",  "file...file note,-s file...file",
  112.  do_fileslist, 0,    0,     0, "flist",      NULL, "",
  113.  do_fltlower,  0,    0,     0, "fltlower",   NULL, "<in >out",
  114.  do_fltupper,  0,    0,     0, "fltupper",   NULL, "<in >out",
  115.  do_foreach,   3,    0,     0, "foreach",    "v",  "-v varname ( string ) command",
  116.  do_forever,   1,    0,     0, "forever",    NULL, "command",
  117.  do_forline,   3,    0,     0, "forline",    NULL, "var filename command",
  118.  do_fornum,    4,    0,     0, "fornum",     "vs", "-vs var n1 n2 command",
  119.  do_getenv,    1, FUNC,     0, "getenv",     NULL, "shellvar envvar",
  120.  do_goto,      1,    0,     0, "goto",       NULL, "label",
  121.  do_head,      1,    0,     0, "head",       NULL, "filename [num]",
  122.  do_help,      0,    0,     0, "help",       NULL, "",
  123.  do_history,   0,    0,     0, "history",    NULL, "[partial_string]",
  124.  do_howmany,   0,    0,     0, "howmany",    NULL, "",
  125.  do_htype,     1,    0,     0, "htype",      "r",  "-r file...file",
  126.  do_if,        1,COND|NORED,0, "if",         "rftmdvon","-n arg cond arg,-n arg,-nf file,-nd dir -nm,-nt file...file,-nr rpn_expr,-no opt args,-v varname",
  127.  do_inc,       1,    0,     1, "inc",        NULL, "varname [step]",
  128.  do_info,      0,    0,     0, "info",       NULL, "[drive...drive]",
  129.  do_input,     1,    0,     0, "input",      "sr", "-rs var...var",
  130.  do_join,      2,    0,     1, "join",       "r",  "-r file...file",
  131.  do_keymap,    1,    0,     0, "keymap",     "n",  "-n number {key=function}",
  132.  do_label,     1, COND,     0, "label",      NULL, "name",
  133.  do_local,     0,    0,     0, "local",      NULL, "[var...var]",
  134.  do_linecnt,   0,    0,     0, "linecnt",    NULL, "<in >out",
  135.  do_dir,       0,NOEXP,     0, "ls",         "sfdcnhltbuikqavopzeg","-abcdefghiklnopqstuv [-z format] [path...path]",
  136.  do_man,       0,    0,     0, "man",        NULL, "command...command",
  137.  do_mkdir,     0,    0,     0, "md",         NULL, "name...name",
  138.  do_mem,       0,    0,     0, "mem",        "cfqsrl","-cflqsr",
  139.  do_menu,      0,    0,     0, "menu",       "n",  "-n [title item...item]",
  140.  do_mkdir,     0,    0,     0, "mkdir",      NULL, "name...name",
  141.  do_mv,        2,    0,     0, "mv",         NULL, "from to,from...from todir",
  142.  do_open,      3,    0,     0, "open",       NULL, "file mode number",
  143.  do_path,      0,    0,     0, "path",       "r",  "-r [dir...dir]",
  144.  do_pri,       2,    0,     0, "pri",        NULL, "clinumber pri,0 pri",
  145.  do_protect,   2,    0,     0, "protect",    NULL, "file...file flags",
  146.  do_ps,        0,    0,     0, "ps",         "le", "-el [commandname...commandname]",
  147.  do_pwd,       0,    0,     0, "pwd",        NULL, "",
  148.  do_qsort,     0,    0,     0, "qsort",      "r",  "-r <in >out",
  149.  do_quit,      0,NORED,     0, "quit",       NULL, "",
  150.  do_truerun,   1,NORED,     1, "rback",      NULL, "command",
  151.  do_mv,        2,    0,     0, "rename",     NULL, "from to,from...from todir",
  152.  do_readfile,  1,    0,     0, "readfile",   NULL, "varname [filename]",
  153.  do_relabel,   2,    0,     0, "relabel",    NULL, "drive name",
  154.  do_resident,  0,    0,     0, "resident",   "ard",",-ard file...file",
  155.  do_return,    0,    0,     0, "return",     NULL, "[n]",
  156.  do_rm,        0,    0,     0, "rm",         "rpq","-pqr file...file",
  157.  do_rpn,       0,NOEXP,     0, "rpn",        NULL, "expression",
  158.  do_rxrec,     0,    0,     0, "rxrec",      NULL, "[portname]",
  159.  do_rxsend,    2,    0,     0, "rxsend",     "rl", "-lc portname string",
  160.  do_truerun,   1,NORED,     0, "run",        NULL, "command",
  161.  do_search,    2,    0,     0, "search",     "rcwneqvbfalo","-abceflnoqrvw file...file string",
  162.  do_set_var,   0,   AV,   SET, "set",        NULL, "[name [string] ]",
  163.  do_setenv,    2,    0,     0, "setenv",     NULL, "var value",
  164.  do_sleep,     0,    0,     0, "sleep",      NULL, "timeout",
  165.  do_split,     1,    0,     0, "split",      NULL, "srcvar dstvar...dstvar",
  166.  do_source,    1,   AV,     0, "source",     NULL, "file", /* uses avline */
  167.  do_stack,     0,    0,     0, "stack",      NULL, "[bytes]",
  168.  do_strhead,   3, FUNC,     0, "strhead",    NULL, "varname breakchar string",
  169.  do_strings,   1,    0,     0, "strings",    "r",  "-r file...file minlength",
  170.  do_strleft,   3, FUNC,     0, "strleft",    NULL, "varname string n",
  171.  do_strlen,    2, FUNC,     0, "strlen",     NULL, "varname string",
  172.  do_strmid,    3, FUNC,     0, "strmid",     NULL, "varname string n1 [n2]",
  173.  do_strright,  3, FUNC,     0, "strright",   NULL, "varname string n",
  174.  do_strtail,   3, FUNC,     0, "strtail",    NULL, "varname breakchar string",
  175.  do_tackon,    3, FUNC,     0, "tackon",     NULL, "var pathname filename",
  176.  do_head,      1,    0,     1, "tail",       NULL, "filename [num]",
  177.  do_tee,       0,    0,     0, "tee",        NULL, "<in >out",
  178.  do_touch,     0,    0,     0, "touch",      NULL, "file...file",
  179.  do_truncate,  0,    0,     0, "truncate",   NULL, "<in >out",
  180.  do_cat,       0,    0,     0, "type",       NULL, "-n [file...file]",
  181.  do_unset_var, 0,    0, ALIAS, "unalias",    NULL, "name...name",
  182.  do_uniq,      0,    0,     0, "uniq",       NULL, "<in >out",
  183.  do_unset_var, 0,    0, LOCAL, "unlocal",    NULL, "var...var",
  184.  do_unset_var, 0,    0,   SET, "unset",      NULL, "name...name",
  185.  do_usage,     0,    0,     0, "usage",      NULL, "[command...command]",
  186.  do_ver,       0,    0,     0, "version",    NULL, "",
  187.  do_waitport,  1,    0,     0, "waitforport",NULL, "portname [seconds]",
  188.  do_whereis,   1,NOEXP,     0, "whereis",    "r",  "-r file [path...path]",
  189.  do_window,    0,NOEXP,     0, "window",     "slfbaq","-slfbaq",
  190.  do_writefile, 1,    0,     0, "writefile",  NULL, "var >out",
  191.  NULL,         0,    0,     0, NULL,         NULL, NULL,
  192. };
  193.  
  194.  
  195. /* do_which,     1,    0,     0, "which",      NULL, "command", */
  196.  
  197. #ifdef isalphanum
  198. char isalph[256];
  199. #endif
  200.  
  201. int
  202. exec_command( char *base )
  203. {
  204.     FRAME *frame=NULL;
  205.     UBYTE *scr;
  206.     char  buf[6];
  207.     int   len, ret;
  208.  
  209.     if (!H_stack && S_histlen>1) {
  210.         add_history(base);
  211.         sprintf(buf, "%d", H_tail_base + H_len);
  212.         set_var(LEVEL_SET, v_histnum, buf);
  213.     }
  214.  
  215.     len=Strlen(base)*3+20;
  216.     newframe( &frame, len+DEFAULTFRAME );
  217.  
  218.     scr = falloc(&frame,len);
  219.     preformat( base,scr );
  220.  
  221.     funalloc( &frame, len-Strlen(scr)-2 );
  222.     ret=fcomm(scr,&frame,NULL);
  223.  
  224.     deleteframe( frame );
  225.  
  226.     return ret;
  227. }
  228.  
  229. #ifndef isalphanum
  230. isalphanum( char c )
  231. {
  232.     return (
  233.         (c >= 'a' && c <= 'z') ||
  234.         (c >= 'A' && c <= 'Z') ||
  235.         (c >= '0' && c <= '9') ||
  236.         (c == '_')
  237.     );
  238. }
  239. #endif
  240.  
  241. #define HOT_GAP    0x80
  242. #define HOT_BLANK  0x81
  243. #define HOT_STAR   0x82
  244. #define HOT_QUES   0x83
  245. #define HOT_EXCL   0x84
  246. #define HOT_SEMI   0x85
  247. #define HOT_PIPE   0x86
  248. #define HOT_DOLLAR 0x87
  249. #define HOT_IN     0x88
  250. #define HOT_OUT    0x89
  251. #define HOT_BSLASH 0x8a
  252. #define HOT_LASTCD 0x8b
  253. #define HOT_BACKG  0x8c
  254. #define HOT_CURLL  0x8d
  255. #define HOT_CURLR  0x8e
  256. #define HOT_CURDIR 0x8f
  257. #define HOT_PARDIR 0x90
  258. #define HOT_BEGOUT 0x91
  259. #define HOT_ENDOUT 0x92
  260. #define HOT_EQUAL  0x93
  261. #define HOT_BEGIN  0x94
  262. #define HOT_APOSTR 0x95
  263.  
  264. USHORT ArgPos[256];
  265.  
  266. void
  267. preformat( char *src, UBYTE *d )
  268. {
  269.     static UBYTE termchar[]={ 0,    '}',       ')',        '`' };
  270.     static UBYTE hotchar []={ 0, HOT_CURLR, HOT_ENDOUT, HOT_APOSTR };
  271.     int qm=0, i, level, curmode, argc=0, beg=1;
  272.     UBYTE mode[100], c, *s=(UBYTE*)src;
  273.  
  274.     while (*s) {
  275.         if (qm ) {
  276.             while( *s && *s != '\"' && *s != '\\')
  277.                 *d++ = *s++;
  278.             if( !*s ) break;
  279.         }
  280.         if( beg ) c=HOT_BEGIN,beg=0; else c=*s;
  281.         switch (c) {
  282.         case ' ':
  283.         case 9:
  284.             *d++ = HOT_BLANK;
  285. argstart:
  286.             while (*s == ' ' || *s == 9) ++s;
  287.             if( *s == '\\' && !argc )    { *d++=HOT_BSLASH; if( *d++=*++s ) ++s; }
  288.             if( *s == '~'  )             { *d++=HOT_LASTCD; s++; }
  289.             else if( *s=='.'&&s[1]=='.') { *d++=HOT_PARDIR; *d++='.'; s+=2; }
  290.             else if( *s=='.' )           { *d++=HOT_CURDIR; s++; }
  291.             else if( argc && (!*s || *s == '|' || *s == ';' || *s=='#')) --d;
  292.             argc++;
  293.             break;
  294.         case '*':
  295.             *d++ = HOT_GAP;
  296.             *d++ = HOT_STAR;
  297.             ++s;
  298.             break;
  299.         case '?':
  300.             *d++ = HOT_GAP;
  301.             *d++ = HOT_QUES;
  302.             ++s;
  303.             break;
  304.         case '!':
  305.             *d++ = HOT_EXCL;
  306.             ++s;
  307.             break;
  308.         case '#':
  309.             *d++ = '\0';
  310.             while (*s) ++s;
  311.             break;
  312.         case HOT_BEGIN:
  313.             argc=0;
  314.             goto argstart;
  315.         case ';':
  316.             *d++= HOT_SEMI, argc=0, s++;
  317.             goto argstart;
  318.         case '|':
  319.             *d++= HOT_PIPE, argc=0, s++;
  320.             goto argstart;
  321.         case '\\':
  322.             if( (i=*++s-'0')>=0 && i<=7 ) {
  323.                 if( *++s>='0' && *s<='7' ) {
  324.                     i= 8*i + *s++-'0';
  325.                     if( *s>='0' && *s<='7' )
  326.                         i= 8*i + *s++-'0';
  327.                 }
  328.                 *d++ = i;
  329.             } else {
  330.                 *d++ = *s;
  331.                 if (*s) ++s;
  332.             }
  333.             break;
  334.         case '\"':
  335.             qm = 1 - qm;
  336.             ++s;
  337.             break;
  338.         case '^':
  339.             *d++ = *++s & 0x1F;
  340.             if (*s) ++s;
  341.             break;
  342.         case '<':
  343.             *d++ = HOT_IN;
  344.             ++s;
  345.             break;
  346.         case '>':
  347.             *d++ = HOT_OUT;
  348.             ++s;
  349.             break;
  350.         case '&':
  351.             *d++ = HOT_BACKG;
  352.             ++s;
  353.             break;
  354.         case '$': /* search end of var name */
  355.             if( s[1]=='(' ) {
  356.                 curmode=2;
  357.                 *d++=HOT_BEGOUT;
  358.                 *d++=*++s;
  359.                 goto brace;
  360.             }
  361.             *d++ = HOT_GAP;
  362.             *d++ = HOT_DOLLAR;
  363.             ++s;
  364.             while (isalphanum(*s)) *d++ = *s++;
  365.             *d++ = HOT_GAP;
  366.             break;
  367.         case '`':
  368.             curmode=3;
  369.             *d++=HOT_APOSTR;
  370.             goto brace;
  371.         case '{':
  372.             curmode=1;
  373.             *d++ = HOT_CURLL;
  374. brace:
  375.             level=0; s++;
  376.             mode[level++]=curmode;
  377.             while( *s && level ) {
  378.                 switch( *s ) {
  379.                 case '\"': *d++=*s++;
  380.                            while( *s && *s!='\"' )
  381.                                if( *s=='\\' ) { *d++=*s++; if( *s ) *d++=*s++; }
  382.                                else *d++=*s++;
  383.                            if( *s ) *d++=*s++;
  384.                            break;
  385.                 case '\\': *d++=*s++; if( *s ) *d++=*s++;
  386.                            break;
  387.                 case '{' : mode[level++]=1; *d++=*s++;
  388.                            break;
  389.                 case '}' :
  390.                 case ')' :
  391.                 case '`' : for( i=level-1; i>=0 && termchar[mode[i]]!=*s;--i ) ;
  392.                            if( i==0 ) *d++=hotchar [mode[i]];
  393.                            else       *d++=*s;
  394.                            if( i>=0 ) level=i;
  395.                            s++;
  396.                            break;
  397.                 default  : *d++=*s++;
  398.                            break;
  399.                 }
  400.             }
  401.             break;
  402.         default:
  403.             *d++ = *s++;
  404.             while( *s>=65 && (*s&31)<=26 )
  405.                 *d++=*s++;
  406.             break;
  407.         }
  408.     }
  409.     *d++=0;
  410.     *d=0;
  411.     if (debug) fprintf (stderr,"PREFORMAT: %d :%s:\n", Strlen(d), d);
  412.     return;
  413. }
  414.  
  415. static void
  416. backtrans( UBYTE *str )
  417. {
  418.     while( *str ) {
  419.         while( *(signed char *)str>0 ) str++;
  420.         if( !*str ) break;
  421.         switch( *str) {
  422.             case HOT_GAP   : *str++=0;    break;
  423.             case HOT_BLANK : *str++=' ';  break;
  424.             case HOT_STAR  : *str++='*';  break;
  425.             case HOT_QUES  : *str++='?';  break;
  426.             case HOT_EXCL  : *str++='!';  break;
  427.             case HOT_SEMI  : *str++=';';  break;
  428.             case HOT_PIPE  : *str++='|';  break;
  429.             case HOT_DOLLAR: *str++='$';  break;
  430.             case HOT_IN    : *str++='<';  break;
  431.             case HOT_OUT   : *str++='>';  break;
  432.             case HOT_BSLASH: *str++='\\'; break;
  433.             case HOT_LASTCD: *str++='~';  break;
  434.             case HOT_BACKG : *str++='&';  break;
  435.             case HOT_CURLL : *str++='{';  break;
  436.             case HOT_CURLR : *str++='}';  break;
  437.             case HOT_CURDIR: *str++='.';  break;
  438.             case HOT_PARDIR: *str++='.';  break;
  439.             case HOT_BEGOUT: *str++='$';  break;
  440.             case HOT_ENDOUT: *str++=')';  break;
  441.             case HOT_EQUAL : *str++='=';  break;
  442.             case HOT_APOSTR: *str++='`';  break;
  443.             default        : str++;       break;
  444.         }
  445.     }
  446. }
  447.  
  448. /*
  449.  * process formatted string.  ' ' is the delimeter.
  450.  *
  451.  *    0: check '\0': no more, stop, done.
  452.  *    1: check $.     if so, extract, format, insert
  453.  *    2: check alias. if so, extract, format, insert. goto 1
  454.  *    3: check history or substitution, extract, format, insert. goto 1
  455.  *
  456.  *    4: assume first element now internal or disk based command.
  457.  *
  458.  *    5: extract each ' ' or 0x80 delimited argument and process, placing
  459.  *       in av[] list (except 0x80 args appended).  check in order:
  460.  *
  461.  *             '$'         insert string straight
  462.  *             '>'         setup stdout
  463.  *             '>>'        setup stdout flag for append
  464.  *             '<'         setup stdin
  465.  *             '*' or '?'  do directory search and insert as separate args.
  466.  *
  467.  *             ';' 0 '|'   end of command.  if '|' setup stdout
  468.  *                          -execute command, fix stdin and out (|) sets
  469.  *                           up stdin for next guy.
  470.  */
  471.  
  472. int  alias_count;
  473. int  has_wild;                 /* set if any arg has wild card */
  474. char *LastCommand;
  475.  
  476. #define MAXACDEF 32
  477.  
  478. int
  479. fcomm( UBYTE *str, FRAME **frameptr, char *from )
  480. {
  481.     UBYTE *nextstr, elast;
  482.     char *pend_alias, *command;
  483.     char cout_ispipe=0, cin_ispipe=0, cout_append=0;
  484.     char backg, firstrun, override, block, nobuiltin;
  485.     char *cin_name=NULL, *cout_name=NULL;
  486.     char **oldav=av;
  487.     int  oldac=ac, oldmax=max_ac, err, ccno, cstat;
  488.  
  489.     max_ac= MAXACDEF;
  490.     av=(char **)falloc( frameptr, max_ac*sizeof(char *));
  491.     ac=0;
  492.  
  493.     if (++alias_count >= MAXALIAS) {           /* Recursion getting too deep? */
  494.         fprintf(stderr,"Alias Loop\n");
  495.         err = 20;
  496.         goto done1;
  497.     }
  498.  
  499. nextcommand:
  500.     command   = NULL;
  501.     pend_alias= NULL;
  502.     err       = 0;
  503.     has_wild  = 0;
  504.     firstrun  = 1;
  505.     ccno=cstat= 0;
  506.     elast     = 1;
  507.     block     = 0;
  508.     nobuiltin = 0;
  509.  
  510.     if (*str == 0)
  511.         goto done1;
  512.  
  513.     if ( *str == HOT_EXCL) {
  514.         UBYTE *p, c;
  515.         char *istr;                       /* fix to allow !cmd1;!cmd2 */
  516.         for(p = str; *p && *p != HOT_SEMI ; ++p);
  517.         c = *p;
  518.         *p = 0;
  519.         if( str[1]==HOT_EXCL ) str[1]='!';
  520.         istr = get_history((char *)str,1,0);
  521.         *p = c;
  522.         replace_head(istr);
  523.         str = format_insert_string( frameptr, str, istr );
  524.     }
  525.  
  526.     /*******************************************************
  527.      * Part one of the parser:
  528.      * The argument line is generated as an array of strings
  529.      */
  530.  
  531.     nextstr = str;
  532.     ac = 0;
  533.     do {              /* outer loop: each pass typically generates one av[ac] */
  534.         UBYTE *ptr, *arg;
  535.         signed char redir, doexpand, cont, inc;
  536.  
  537.         av[ac] = NULL;
  538.         cont = 1;
  539.         doexpand = redir = inc = 0;
  540.  
  541.         while (cont && elast) {       /* inner loop: adds one piece to av[ac] */
  542.             ptr = exarg(&nextstr,&elast);
  543.             inc = 1;
  544.             cont = (elast == 0x80);
  545.             switch ((UBYTE)*ptr) {           /* arg must be set in every case */
  546.             case HOT_IN:
  547.                 redir = -2;
  548.             case HOT_OUT:
  549.                 if (cstat & (ST_NORED | ST_COND)) {     /* don't extract   */
  550.                     redir = 0;                          /* <> stuff if its */
  551.                     arg = ptr;                          /* external cmd.   */
  552.                     break;
  553.                 }
  554.                 ++redir;
  555.                 arg = ptr + 1;
  556.                 if (*arg == HOT_OUT) {
  557.                     redir = 2;        /* append >> */
  558.                     ++arg;
  559.                 }
  560.                 cont = 1;
  561.                 break;
  562.             case HOT_DOLLAR:
  563.                 /* restore args if from set command or pend_alias */
  564.                 if ((arg = get_var(LEVEL_SET, ptr + 1))) {
  565.                     UBYTE *pe, sv;
  566.                     while (pe = Index(arg,0xA0)) {
  567.                         sv = *pe;
  568.                         *pe = '\0';
  569.                         checkav(frameptr,1);
  570.  
  571.                         if (av[ac]) {
  572.                             av[ac] = frealloc( frameptr,av[ac],Strlen(arg));
  573.                             Strcat(av[ac++], arg);
  574.                         } else
  575.                             av[ac++] = push_cpy(frameptr,arg);
  576.  
  577.                         *pe = sv;
  578.                         av[ac] = NULL;
  579.                         arg = pe+1;
  580.                     }
  581.                 } else
  582.                     arg = ptr;
  583.                 break;
  584.             case HOT_LASTCD:
  585.                 if ((!ptr[1] || ptr[1]=='/')&&(arg=get_var(LEVEL_SET, v_lcd))) {
  586.                     if( ptr[1] ) {
  587.                         Strcpy(Buf,arg);
  588.                         Strcat(Buf,ptr+1);
  589.                         arg=(UBYTE*)Buf;
  590.                     } 
  591.                 } else
  592.                     arg = ptr;
  593.                 break;
  594.             case HOT_CURDIR:
  595.                 arg=ptr;
  596.                 if( !ptr[1] && elast!=0x80 || ptr[1]=='/' ) {
  597.                     if( ac==0 ) nobuiltin=1;
  598.                     arg= ptr[1]=='/' ? ptr+2 : ptr+1;
  599.                 }
  600.                 break;
  601.             case HOT_PARDIR:
  602.                 arg=ptr;
  603.                 if( !ptr[2] && elast!=0x80 || ptr[2]=='/' )
  604.                     arg= ptr[2]=='/' ? ptr+2 : "/";
  605.                 break;
  606.  
  607.             case HOT_STAR:
  608.             case HOT_QUES:
  609.                 if( !(cstat & ST_NOEXP) && !(pend_alias && *pend_alias=='*'))
  610.                     if( ac!=1 || av[1]&&*av[1] || *ptr!=HOT_QUES || ptr[1] )
  611.                         doexpand = 1;
  612.                 arg = ptr;
  613.                 break;
  614.             default:
  615.                 arg = ptr;
  616.                 break;
  617.             }
  618.  
  619.             /* Append arg to av[ac] */
  620.  
  621.             if (av[ac]) {
  622.                 av[ac] = frealloc( frameptr,av[ac],Strlen(arg));
  623.                 Strcat(av[ac], arg);
  624.             } else
  625.                 av[ac] = push_cpy(frameptr,arg);
  626.  
  627.             if (elast != 0x80)
  628.                 break;
  629.         }
  630.  
  631.         /* one argument is now complete */
  632.  
  633.         backg   = *av[ac] && (UBYTE)av[ac][Strlen(av[ac])-1]==HOT_BACKG;
  634.         override= (UBYTE)*av[ac] == HOT_BSLASH;
  635.  
  636.         if( firstrun && (UBYTE)*av[0] == HOT_CURLL ) {
  637.             char *end;
  638.             av[0]++;
  639.             if( end=index(av[0],HOT_CURLR)) *end=0;
  640.             block=1;
  641.         }
  642.  
  643.         if( (UBYTE)*av[ac]==HOT_BEGOUT || (UBYTE)*av[ac]==HOT_APOSTR ) {
  644.             BPTR cout, oldcout= Myprocess->pr_COS;
  645.             FILE *in;
  646.             UBYTE *t;
  647.             int  apo;
  648.  
  649.             apo= (UBYTE)*av[ac]==HOT_APOSTR;
  650.             inc=0;
  651.             if( t=Index(av[ac]+1, apo ? HOT_APOSTR : HOT_ENDOUT ))
  652.                 *t=0;
  653.  
  654.             if(!(cout = Open(tempname(2),MODE_NEWFILE))) {
  655.                 err= 20;
  656.                 ierror (NULL, 504);
  657.             } else {
  658.                 Myprocess->pr_COS = DEVTAB(stdout) = cout;
  659.                 execute(av[ac]+2-apo);
  660.                 fflush(stdout);
  661.                 Close(cout);
  662.  
  663.                 if(!(in=fopen(tempname(2),"r"))) {
  664.                     err= 1;
  665.                     ierror (NULL, 504);
  666.                 } else {
  667.                     while( myfgets(Buf,in)) {
  668.                         char *str=Buf, *get, quote=0;
  669.                         if( apo ) {
  670.                             while( *str==' ' ) str++;
  671.                             for( get=str; *get; ) {
  672.                                 if( *get=='\"' )
  673.                                     quote=1-quote, get++;
  674.                                 else if( *get==' ' && !quote ) {
  675.                                     *get++=0;
  676.                                     checkav(frameptr,1);
  677.                                     while( *get==' ' ) get++;
  678.                                     if( !*get ) break;
  679.                                     av[ac++]=push_cpy(frameptr,str);
  680.                                     str=get;
  681.                                 } else 
  682.                                     get++;
  683.                             }
  684.                             av[ac++]= push_cpy(frameptr,str);
  685.                         } else 
  686.                             av[ac++]= push_cpy(frameptr,(UBYTE*)Buf);
  687.                         checkav( frameptr, 1 );
  688.                     }
  689.                     fclose(in);
  690.                     DeleteFile(tempname(2));
  691.                 }
  692.             }
  693.  
  694.             Myprocess->pr_COS = DEVTAB(stdout) = oldcout;
  695.         }
  696.  
  697.         backtrans( (UBYTE *)av[ac] );
  698.  
  699.         if (doexpand) {                                  /* process expansion */
  700.             char **eav, **ebase;
  701.             int eac;
  702.             has_wild = 1;
  703.             eav = ebase = expand(av[ac], &eac);
  704.             inc = 0;
  705.             if (eav) {
  706.                 if( checkav( frameptr, eac ) ) {
  707.                     ierror (NULL, 506);
  708.                     err = 1;
  709.                 } else {
  710.                     QuickSort(eav, eac);
  711.                     for (; eac; --eac, ++eav)
  712.                         av[ac++] = push_cpy(frameptr,*eav);
  713.                 }
  714.                 free_expand (ebase);
  715.             }
  716.         } else if( av[ac][0]==')' ) {
  717.             int i;
  718.             UBYTE *pe, sv;
  719.             for( i=ac-1; i>0; i-- )
  720.                 if( *av[i]=='@' )
  721.                     break;
  722.             if( i>0 && av[i][Strlen(av[i])-1]=='(' ) {
  723.                 extern int exec_fn_err;
  724.                 char *avi=av[i], *last=av[ac];
  725.                 av[i]=v_value; av[ac]=NULL;
  726.                 arg=(UBYTE*)exec_function( avi+1, av+i, ac-i );
  727.                 av[i]=avi;     av[ac]=last;
  728.                 inc=0;
  729.                 if( exec_fn_err<0 )
  730.                     ac++;
  731.                 else if( exec_fn_err>0 || !arg )
  732.                     ac=i, av[ac]=NULL;
  733.                 else {
  734.                     ac=i;
  735.                     while (pe = Index(arg,0xA0)) {
  736.                         sv = *pe;
  737.                         *pe = '\0';
  738.                         checkav( frameptr, 1 );
  739.                         av[ac++] = push_cpy(frameptr,arg);
  740.                         *pe = sv;
  741.                         arg= pe+1;
  742.                     }
  743.                     av[ac] = falloc(frameptr,Strlen(arg)+Strlen(last+1)+4);
  744.                     Strcpy(av[ac],arg);
  745.                     Strcat(av[ac++], last+1 );
  746.                 }
  747.             }
  748.         }
  749.  
  750.         /*******************************
  751.          * special handling of first arg
  752.          */
  753.  
  754.         if( firstrun ) {                     /* we just found out the command */
  755.             firstrun=0;
  756.             command=av[0];
  757.  
  758.             if (*command == 0)
  759.                 goto done0;
  760.  
  761.             if( block )
  762.                 pend_alias=command;
  763.             else if ( override )
  764.                 memmove( command, command+1, Strlen(command));
  765.             else {
  766.                 pend_alias=get_var(LEVEL_ALIAS,command);  /* if not \command */
  767.                 if( pend_alias && pend_alias==from )
  768.                     pend_alias=NULL;
  769.             }
  770.  
  771.             if( pend_alias )
  772.                 ccno= *pend_alias=='%' || *pend_alias=='*' ? 2 : 1;
  773.             else 
  774.                 ccno= nobuiltin ? 0 : find_command(command);
  775.             cstat=Command[ccno].stat;
  776.  
  777.             if ( !(cstat & ST_COND) && (disable || forward_goto) ) {
  778.                 while (elast && elast != HOT_SEMI && elast != HOT_PIPE)
  779.                     exarg(&nextstr,&elast);
  780.                 goto done0;
  781.             }
  782.         }
  783.  
  784.         if (redir && !err) {                            /* store redirection  */
  785.             char *file = (doexpand) ? av[--ac] : av[ac];
  786.  
  787.             if (redir < 0)
  788.                 cin_name = file;
  789.             else {
  790.                 cout_name = file;
  791.                 cout_append = (redir == 2);
  792.             }
  793.             inc = 0;
  794.         }
  795.  
  796.         if (inc) {                                   /* check elast for space */
  797.             ++ac;
  798.             if( checkav(frameptr,1) ) {
  799.                 ierror (NULL, 506);
  800.                 err = 1;                                   /* error condition */
  801.                 elast = 0;                /* don't process any more arguemnts */
  802.             }
  803.         }
  804.     } while( elast==HOT_BLANK );
  805.     av[ac] = NULL;
  806.  
  807.  
  808.     /******************************************************************
  809.      * Part two:
  810.      * The argument line is processed (pipes, commands, recursive calls
  811.      */
  812.  
  813.     /* process pipes via files */
  814.  
  815.     if (elast == HOT_PIPE && !err) {
  816.         static int which;             /* 0 or 1 in case of multiple pipes */
  817.         which = 1 - which;
  818.         cout_name = tempname( which );
  819.         cout_ispipe = 1;
  820.     }
  821.  
  822.  
  823.     if (err)
  824.         goto done0;
  825.  
  826.     {
  827.         char *avline;
  828.         char delim = ' ';
  829.         BPTR  oldcin  = Myprocess->pr_CIS, cin=NULL;
  830.         BPTR  oldcout = Myprocess->pr_COS, cout=NULL;
  831.         char *cin_buf=NULL;
  832.         struct FileHandle *ci=NULL;
  833.         long oldbuf=NULL;
  834.  
  835.         if( backg ) {
  836.             char *larg=av[ac-1];
  837.             memmove( av+1, av, ac*sizeof(*av));
  838.             command=av[0]=push_cpy( frameptr, (UBYTE*)o_rback);
  839.             ccno=find_command(command);
  840.             cstat=Command[ccno].stat;
  841.             if( Strlen(larg)>1 )
  842.                 larg[Strlen(larg)-1]=0, ac++;
  843.         }
  844.         if( ccno==2 || (cstat & ST_AV))            /* alias with argument */
  845.             delim = 0xA0;
  846.         avline = compile_avf(frameptr,av,(pend_alias?1:0), ac, delim, ccno==1);
  847.  
  848.         fflush(stdout);
  849.         LastCommand=command;
  850.         if ( !(cstat & (ST_NORED | ST_COND))) { /* redirection not disabled */
  851.             if (cin_name) {
  852.                 if (!(cin = extOpen(cin_name,MODE_OLDFILE))) {
  853.                     ierror (NULL, 504);
  854.                     err = 20;
  855.                     cin_name = NULL;
  856.                 } else {
  857.                     Myprocess->pr_CIS = DEVTAB(stdin) = cin;
  858.                     ci = (struct FileHandle *)(cin<<2);
  859.                     cin_buf = SAllocMem(202L, MEMF_PUBLIC);
  860.                     oldbuf = ci->fh_Buf;
  861.                     if (ci->fh_Buf == 0) /* fexec expects a CIS buffer */
  862.                         ci->fh_Buf = (long)cin_buf>>2;
  863.                 }
  864.             }
  865.             if (cout_name) {
  866.                 if (cout_append && (cout =extOpen(cout_name,1005L))) {
  867.                     Seek(cout, 0L, OFFSET_END );
  868.                 } else {
  869.                     cout = extOpen(cout_name,MODE_NEWFILE);
  870.                 }
  871.                 if (cout == NULL) {
  872.                     err = 20;
  873.                     ierror (NULL, 504);
  874.                     cout_name = NULL;
  875.                     cout_append = 0;
  876.                 } else {
  877.                     Myprocess->pr_COS = DEVTAB(stdout) = cout;
  878.                 }
  879.             }
  880.         }
  881.  
  882.         if( Verbose&VERBOSE_ALIAS ) {
  883.             if( Verbose&VERBOSE_HILITE ) fprintf(stderr,"%s",o_hilite);
  884.             if( pend_alias )
  885.                 fprintf(stderr,"%-*s%s %s\n",alias_count,">",av[0],avline);
  886.             else 
  887.                 fprintf(stderr,"%-*s%s\n",alias_count,">",avline);
  888.             if( Verbose&VERBOSE_HILITE ) fprintf(stderr,"%s",o_lolite);
  889.         }
  890.  
  891.         if( pend_alias ) {
  892.             UBYTE *scr;
  893.             FRAME *subframe=NULL;
  894.  
  895.             if( ccno==2 ) {                         /* has arguments */
  896.                 char *ptr=pend_alias, *val=avline;
  897.                 int clen;
  898.  
  899.                 clen=Strlen(ptr)*2+20;
  900.                 newframe( &subframe, clen+DEFAULTFRAME );
  901.                 push_locals( (ROOT *)falloc( &subframe, sizeof(ROOT) ));
  902.                 do {                                       /* set all args    */
  903.                     char *varname, *gap=NULL;
  904.                     for( varname= ++ptr; *ptr && *ptr!=' ' && *ptr!='%'; ++ptr);
  905.                     if( *ptr=='%' && (gap=index(val,0xA0 )) ) *gap=0;
  906.                     set_var( LEVEL_LOCAL, varname, val );
  907.                     val= gap ? gap+1 : "";
  908.                 } while( *ptr=='%' );
  909.                 scr = falloc(&subframe,clen);
  910.                 preformat (ptr, scr);
  911.             } else {
  912.                 char *scr2;
  913.                 int  clen=Strlen(pend_alias)+Strlen(avline)+20;
  914.  
  915.                 newframe( &subframe,3*clen+DEFAULTFRAME );
  916.                 push_locals( (ROOT *)falloc( &subframe, sizeof(ROOT) ));
  917.                 scr2= falloc( &subframe,clen );
  918.                 sprintf(scr2,"%s %s",pend_alias,avline);
  919.                 scr = falloc( &subframe, 2*clen );
  920.                 preformat( scr2,scr);
  921.             }
  922.             fcomm (scr,&subframe,pend_alias );
  923.             pop_locals();
  924.             deleteframe(subframe);
  925.         } else {
  926.             if (ac < Command[ccno].minargs + 1) {
  927.                 show_usage( NULL );
  928.                 err = 20;
  929.                 if (E_stack == 0 )
  930.                     seterr(err);
  931.             } else if (!err) {
  932.                 int (*func)(char*,int)=Command[ccno].func, i;
  933.                 get_opt( av, &ac, ccno );
  934.                 i=0;
  935.                 if( ccno>0 && ac==2 && !strcmp(av[1],"?") )
  936.                     show_usage(avline);
  937.                 else 
  938.                     i = (*func)(avline, Command[ccno].val); /*  do the call */ 
  939.                 if (i < 0)
  940.                     i = 20;
  941.                 err = i;
  942.                 if (E_stack == 0 )
  943.                     seterr(err);
  944.                 fflush(stderr);
  945.             }
  946.         }
  947.         if (!(cstat & (ST_NORED | ST_COND))) {
  948.             if (cin_name) {
  949.                 ci->fh_Buf = oldbuf;
  950.                 fflush(stdin);
  951.                 clearerr(stdin);
  952.                 RESETIO( stdin );
  953.                 extClose(cin);
  954.                 FreeMem(cin_buf, 202L);
  955.             }
  956.             if (cout_name) {
  957.                 fflush(stdout);
  958.                 clearerr(stdout);
  959. #ifdef AZTEC_C
  960.                 stdout->_flags &= ~_IODIRTY;    /* because of nil: device */
  961. #endif
  962.                 extClose(cout);
  963.                 cout_append = 0;
  964.             }
  965.         }
  966.         Myprocess->pr_CIS = DEVTAB(stdin)  = oldcin;
  967.         Myprocess->pr_COS = DEVTAB(stdout) = oldcout;
  968.  
  969.         if (cin_ispipe && cin_name)
  970.             DeleteFile(cin_name);
  971.         if (cout_ispipe) {
  972.             cin_name = cout_name;         /* ok to assign.. static name */
  973.             cin_ispipe = 1;
  974.         } else {
  975.             cin_name = NULL;
  976.         }
  977.         cout_name = NULL;
  978.         cout_ispipe = 0;
  979.     }
  980.  
  981. done0:
  982.     {
  983.         char *exc;
  984.         if (err && E_stack==0) {
  985.             exc = get_var(LEVEL_SET, v_except);
  986.             if (err >= ((exc)?atoi(exc):1)) {
  987.                 if (exc) {
  988.                     ++H_stack, ++E_stack;
  989.                     a0tospace(exc);
  990.                     exec_command(exc);
  991.                     --E_stack, --H_stack;
  992.                 } else {
  993.                     Exec_abortline = 1;
  994.                 }
  995.             }
  996.             seterr(err);
  997.         }
  998.         if (elast != 0 && Exec_abortline == 0) {
  999.             memmove( str, nextstr, Strlen(nextstr)+1 );
  1000.             goto nextcommand;
  1001.         }
  1002.         Exec_abortline = 0;
  1003.         if (cin_name)
  1004.             DeleteFile(cin_name);
  1005.     }
  1006. done1:
  1007.  
  1008.     av=oldav; ac=oldac; max_ac=oldmax;
  1009.     --alias_count;
  1010.     return err;                      /* TRUE = error occured    */
  1011. }
  1012.  
  1013.  
  1014. static UBYTE *
  1015. exarg(UBYTE **ptr, UBYTE *elast)
  1016. {
  1017.     UBYTE *end, *start;
  1018.  
  1019.     start = end = *ptr;
  1020.     while ( *(signed char *)end>0 || *end && *end != 0x80 &&
  1021.              *end != HOT_SEMI &&  *end != HOT_PIPE && *end != HOT_BLANK)
  1022.         ++end;
  1023.     *elast = *end;
  1024.     *end = '\0';
  1025.     *ptr = end + 1;
  1026.     return start;
  1027. }
  1028.  
  1029.  
  1030. static void
  1031. newframe(FRAME **frameptr, int bytes)
  1032. {
  1033.     FRAME *new;
  1034.  
  1035.     new=salloc( bytes + 4 + sizeof(FRAME) );
  1036.     new->next= *frameptr;
  1037.  
  1038.     new->bytesleft = bytes;
  1039.     new->ptr       = new->mem;
  1040.     *frameptr=new;
  1041. }
  1042.  
  1043. static void *
  1044. falloc( FRAME **frameptr, int bytes )
  1045. {
  1046.     char *mem,inc;
  1047.  
  1048.     bytes+=2;                                    /* 2 extra bytes for do_run  */
  1049.  
  1050.     if( (*frameptr)->bytesleft <= bytes )
  1051.         newframe( frameptr, bytes+DEFAULTFRAME );
  1052.  
  1053.     inc=4-((long)(*frameptr)->ptr&3);  /* 1 extra byte and longword alignment */
  1054.     mem=(*frameptr)->ptr+inc;
  1055.     (*frameptr)->bytesleft-=bytes+inc;
  1056.     (*frameptr)->ptr      +=bytes+inc;
  1057.     return mem;
  1058. }
  1059.  
  1060. static void *
  1061. frealloc( FRAME **frameptr, char *oldstring, int morebytes )
  1062. {
  1063.     char *mem=oldstring;
  1064.  
  1065.     if( (*frameptr)->bytesleft <= morebytes ) {
  1066.         int oldlen=(*frameptr)->ptr-oldstring;
  1067.         newframe( frameptr, oldlen+morebytes+DEFAULTFRAME );
  1068.         mem= (*frameptr)->ptr;
  1069.         strcpy((*frameptr)->ptr,oldstring);
  1070.         oldlen+=morebytes;
  1071.         (*frameptr)->ptr      +=oldlen;
  1072.         (*frameptr)->bytesleft-=oldlen;
  1073.     }
  1074.     (*frameptr)->bytesleft-=morebytes;
  1075.     (*frameptr)->ptr      +=morebytes;
  1076.     return mem;
  1077. }
  1078.  
  1079. static void
  1080. funalloc( FRAME **frameptr, int bytes )
  1081. {
  1082.     (*frameptr)->bytesleft+=bytes;
  1083.     (*frameptr)->ptr      -=bytes;
  1084. }
  1085.  
  1086.  
  1087.  
  1088. void
  1089. deleteframe(FRAME *frame)
  1090. {
  1091.     FRAME *nxt;
  1092.  
  1093.     for( ; frame; frame=nxt ) {
  1094.         nxt=frame->next;
  1095.         free(frame);
  1096.     }
  1097. }
  1098.  
  1099. /*
  1100.  * Insert 'from' string in front of 'str' while deleting the
  1101.  * first entry in 'str'.  if freeok is set, then 'str' will be
  1102.  * free'd
  1103.  */
  1104.  
  1105. static UBYTE *
  1106. format_insert_string(FRAME **frameptr, UBYTE *str, char *from)
  1107. {
  1108.     UBYTE *new, *strskip;
  1109.     int len;
  1110.  
  1111.     strskip=skipword( str );
  1112.     len = Strlen(from)*3+20;
  1113.     new = falloc( frameptr, len);
  1114.     preformat(from, new);
  1115.     funalloc( frameptr, len -Strlen(new)  - 2 );
  1116.     frealloc( frameptr, (char*)new, Strlen(strskip)+2);
  1117.     strcat((char*)new, (char*)strskip);
  1118.     new[Strlen(new)+1] = 0;
  1119.     return new;
  1120. }
  1121.  
  1122. static UBYTE *
  1123. skipword( UBYTE *strskip )
  1124. {
  1125.     for ( ; *(signed char *)strskip>0
  1126.         || *strskip && *strskip != HOT_BLANK 
  1127.         && *strskip != HOT_SEMI && *strskip != HOT_PIPE
  1128.         && *strskip != 0x80; ++strskip);
  1129.     return strskip;
  1130. }
  1131.  
  1132. char *
  1133. find_internal( char *str )
  1134. {
  1135.     return Command[find_command(str)].name;
  1136. }
  1137.  
  1138. static int
  1139. find_command( char *str )
  1140. {
  1141.     int i, len = Strlen(str);
  1142.     struct COMMAND *com;
  1143.     char c=*str;
  1144.  
  1145.     if( o_abbrev!=2 )
  1146.         for( com=Command, i=0; com->func; com++, i++ )
  1147.             if ( c==*com->name && !strncmp(str, com->name, len))
  1148.                 if(o_abbrev || len==Strlen(com->name))
  1149.                     return i;
  1150.     if( !Strcmp(BaseName(str),"Execute") || !Strcmp(BaseName(str),"Run"))
  1151.         return COM_EXEC;
  1152.  
  1153.     return 0;
  1154. }
  1155.  
  1156. int exec_fn_err;
  1157.  
  1158. extern struct FUNCTION {
  1159.     short id, minargs, maxargs;
  1160.     char *name;
  1161. } Function[];
  1162.  
  1163.  
  1164. char *gotfunc( int i, char **fav, int fac );
  1165.  
  1166. char *
  1167. exec_function( char *str, char **fav, int fac)
  1168. {
  1169.     int len=Strlen(str)-1, i;
  1170.  
  1171.     exec_fn_err=0;
  1172.     for (i = 0; Command[i].func; ++i)
  1173.         if ( Command[i].stat&ST_FUNC && !strncmp(str,Command[i].name,len)) {
  1174.             if( fac<Command[i].minargs ) {
  1175.                 exec_fn_err=20;
  1176.                 return NULL;
  1177.             } else {
  1178.                 int (*func)( void )=Command[i].func;
  1179.                 char **oldav=av;
  1180.                 int  oldac=ac;
  1181.                 av=fav-1, ac=fac+1;
  1182.                 exec_fn_err=(*func)();
  1183.                 av=oldav, ac=oldac;
  1184.                 return get_var( LEVEL_SET, fav[0] );
  1185.             }
  1186.         }
  1187.     for (i = 0; Function[i].id; ++i)
  1188.         if ( len==Strlen(Function[i].name)&&!strncmp(str,Function[i].name,len))
  1189.             return gotfunc( i,fav,fac );
  1190.  
  1191.     exec_fn_err=-1;
  1192.     return NULL;
  1193. }
  1194.  
  1195. int
  1196. echofunc(void)
  1197. {
  1198.     int  i;
  1199.     char *str;
  1200.  
  1201.     if( !strlen(av[0]) ) return -1;
  1202.     exec_fn_err=0;
  1203.     for (i = 0; Function[i].id; ++i)
  1204.         if ( !strcmp(av[0],Function[i].name)) {
  1205.             if(str=gotfunc( i,av,ac ))
  1206.                 printf("%s\n",str);
  1207.             return exec_fn_err;
  1208.         }
  1209.     return -1;
  1210. }
  1211.  
  1212.  
  1213. char *
  1214. gotfunc( int i, char **fav, int fac )
  1215. {
  1216.     fac--; fav++;
  1217.     if( fac<Function[i].minargs ) {
  1218.         fprintf( stderr, "Not enough arguments for @%s\n",
  1219.                           Function[i].name );
  1220.         exec_fn_err=20;
  1221.         return NULL;
  1222.     } else if( fac>Function[i].maxargs ) {
  1223.         if( ac > Function[i].maxargs )
  1224.             fprintf( stderr, "Too many arguments for @%s\n",
  1225.                               Function[i].name );
  1226.         exec_fn_err=20;
  1227.         return NULL;
  1228.     } else {
  1229.         exec_fn_err=dofunc( Function[i].id, fav, fac);
  1230.         return exec_fn_err ? NULL : get_var( LEVEL_SET, v_value );
  1231.     }
  1232.     return NULL;
  1233. }
  1234.  
  1235.  
  1236.  
  1237. do_help()
  1238. {
  1239.     struct COMMAND *com;
  1240.     int i=0;
  1241.  
  1242.     for (com = &Command[FIRSTCOMMAND]; com->func; ++com) {
  1243.         printf ("%-12s", com->name);
  1244.         if (++i % 6 == 0) printf("\n");
  1245.     }
  1246.     printf("\n\nUse   man <command>   for more information\n");
  1247.     return 0;
  1248. }
  1249.  
  1250. do_nothing()
  1251. {
  1252.     return 0;
  1253. }
  1254.  
  1255. static char *
  1256. push_cpy(FRAME **frameptr, void *s)
  1257. {
  1258.     return strcpy(falloc(frameptr,Strlen(s)+1), s);
  1259. }
  1260.  
  1261. void
  1262. exec_every(void)
  1263. {
  1264.     char *str = get_var(LEVEL_SET, v_every);
  1265.  
  1266.     if (str) {
  1267.         ++H_stack, ++E_stack;
  1268.         a0tospace( str );
  1269.         exec_command(str);
  1270.         --E_stack, --H_stack;
  1271.     }
  1272. }
  1273.  
  1274. char *
  1275. a0tospace( char *str )
  1276. {
  1277.     char *get=str, *put=str;
  1278.  
  1279.     while( *get )
  1280.         if( (UBYTE)*get==0xA0 )
  1281.             *put++=' ', get++;
  1282.         else 
  1283.             *put++=*get++;
  1284.     return str;
  1285. }
  1286.  
  1287. void
  1288. show_usage( char *str )
  1289. {
  1290.     int ccno, first=0, err=0;
  1291.     char *get, *put, buf[300];
  1292.  
  1293.     if( !str )
  1294.         str=LastCommand, err=1;
  1295.     for( put=str; *put && (*put&127)!=32; put++ ) ;
  1296.     *put=0;
  1297.  
  1298.     put=buf;
  1299.     ccno = find_command (str);
  1300.     if( get= Command[ccno].usage ) {
  1301.         do {
  1302.             put+=sprintf(put, first++?"       %s ":"Usage: %s ",
  1303.                          Command[ccno].name );
  1304.             if( *get=='-' ) {
  1305.                 *put++='['; *put++='-';
  1306.                 get++;
  1307.                 while( *get && *get!=' ' && *get!=',' )
  1308.                     *put++=*get++;
  1309.                 *put++=']';
  1310.             }
  1311.             while( *get && *get!=','  )
  1312.                 *put++=*get++;
  1313.             *put++='\n';
  1314.         } while( *get++ );
  1315.         *put=0;
  1316.         fprintf( err ? stderr : stdout, "%s", buf );
  1317.     }
  1318. }
  1319.  
  1320. int
  1321. execute( char *str )
  1322. {
  1323.     ULONG toptions=options;
  1324.     int   ret, oldac=ac, oldmax=max_ac;
  1325.     char  **oldav=av;
  1326.  
  1327.     if( !str ) return -1;
  1328.  
  1329.     ++H_stack;
  1330.     ret=exec_command(str);
  1331.     --H_stack;
  1332.  
  1333.     av=oldav; max_ac=oldmax; ac=oldac;
  1334.     options=toptions;
  1335.  
  1336.     return ret;
  1337. }
  1338.  
  1339. do_exec( char *str )
  1340. {
  1341.     if( !options ) 
  1342.         return execute( next_word( str ) );
  1343.     execute( next_word(next_word( str )));
  1344.     return 0;
  1345. }
  1346.  
  1347. static int
  1348. checkav( FRAME **frameptr, int n )
  1349. {
  1350.     char **tmp;
  1351.     int newac;
  1352.  
  1353.     if( ac+n+10>=max_ac ) {
  1354.         newac=max_ac+n+40;
  1355.         tmp=(char **)falloc(frameptr,newac*sizeof(char *));
  1356.         memcpy(tmp,av,max_ac*sizeof(char *));
  1357.         av=tmp; max_ac=newac;
  1358.     }
  1359.     return 0;
  1360. }
  1361.  
  1362. /*    Parse the options specified in sw[]
  1363.     Setting a bit in global variable options
  1364.     for each one found
  1365. */
  1366.  
  1367. int
  1368. get_opt( char **av, int *ac, int ccno )
  1369. {
  1370.     static char opts[2];
  1371.     char **get=av+1,**put=av+1, *c, *s, *str;
  1372.     int i=1, l, usage=0, nac;
  1373.     long oldopts, origopts=options;
  1374.  
  1375.     options=0;
  1376.     if( !ccno )
  1377.         return 0;
  1378.     if( ccno>0 )
  1379.         str=Command[ccno].options;
  1380.     else 
  1381.         str=opts, opts[0]=-ccno;
  1382.  
  1383.     for( ; i<*ac && *av[i]=='-'; i++, get++ ) {
  1384.         if( !*(c=*get+1) )
  1385.             goto stop;
  1386.         oldopts=options;
  1387.         for ( ; *c ; c++) {
  1388.             if( *c<'a' || *c>'z' ) 
  1389.                 { options=oldopts; goto stop; }
  1390.             for( l=0, s=str; *s && *s != *c; ++s )
  1391.                 ++l;
  1392.             if ( *s )
  1393.                 options |= (1 << l);
  1394.             else if( !usage ) {
  1395.                 usage=1;
  1396.                 if( ccno>0 )
  1397.                     show_usage(NULL);
  1398.             }
  1399.         }
  1400.     }
  1401. stop:
  1402.     if( ccno>0 ) {
  1403.         for( nac=1; i<*ac; i++ )
  1404.             *put++=*get++, nac++;
  1405.         *put=NULL;
  1406.         *ac=nac;
  1407.     } else {
  1408.         i=options;
  1409.         options=origopts;
  1410.         return i;
  1411.     }
  1412.     return 0;
  1413. }
  1414.  
  1415. #if 0
  1416. USHORT Options[160];
  1417.  
  1418. int
  1419. do_options()
  1420. {
  1421.     for( i=1; i<ac; i+=2 ) {
  1422.         if( ac-i<=1 )
  1423.             { ierror( av[i], 500 ); return 20; }
  1424.         if( *av[i+1]!='-' )
  1425.             { ierror( av[i+1], 500 ); return 20; }
  1426.         options=0;
  1427.         parseopts( av[i+1]+1 );
  1428.     }
  1429. }
  1430. #endif
  1431.  
  1432. extern char *MyMem;
  1433. static char Pipe[3][32];
  1434.  
  1435. char *
  1436. tempname( int which )
  1437. {
  1438.     sprintf(Pipe[which],"%spipe%c%d_%lx",o_pipe,'A'+which,alias_count,MyMem);
  1439.     return Pipe[which];
  1440. }
  1441.  
  1442. int
  1443. hasspace( char *s )
  1444. {
  1445.     if( !*s )
  1446.         return 1;
  1447.     for ( ; *s; s++)
  1448.         if (ISSPACE(*s) || *s==';') return 1;
  1449.     return 0;
  1450. }
  1451.  
  1452. char *
  1453. compile_avf(FRAME **framep,char **av, int start, int end, char delim, int quote)
  1454. {
  1455.     char *cstr, *p;
  1456.     int len, i;
  1457.  
  1458.     len = 3;
  1459.     for (i = start; i < end; ++i) len += Strlen(av[i]) + 3;
  1460.     if( framep )
  1461.         p = cstr = falloc(framep,len);
  1462.     else 
  1463.         p = cstr = salloc(len);
  1464.     *cstr = '\0';
  1465.     for (i = start; i < end; ++i) {
  1466.         if (debug) fprintf (stderr, "AV[%2d] :%s:\n", i, av[i]);
  1467.         if (quote && hasspace(av[i]))
  1468.             p += sprintf(p, "\"%s\"", av[i]);
  1469.         else
  1470.             p += sprintf(p, "%s",     av[i]);
  1471.         if (i+1 < end) *p++=delim;
  1472.     }
  1473.     *p='\0';
  1474.     return cstr;
  1475. }
  1476.  
  1477. char *
  1478. compile_av(char **av, int start, int end, char delim, int quote)
  1479. {
  1480.     return compile_avf(NULL,av, start, end, delim, quote);
  1481. }
  1482.  
  1483. static int
  1484. myfgets( char *buf, FILE *in )
  1485. {
  1486.     int l;
  1487.     char *ret;
  1488.     if( ret=fgets(buf,253,in) ) {
  1489.         l=Strlen(buf);
  1490.         if( buf[l-1]=='\n' )
  1491.             buf[l-1]=0;
  1492.     }
  1493.     return ret!=NULL && !dobreak();
  1494. }
  1495.