home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 182.lha / CShell_v3.0a / execom.c < prev    next >
C/C++ Source or Header  |  1988-04-28  |  19KB  |  746 lines

  1. /*
  2.  * EXECOM.C
  3.  *
  4.  * Matthew Dillon, 10 August 1986
  5.  *    Finally re-written.
  6.  *
  7.  * Version 2.07M by Steve Drew 10-Sep-87
  8.  *
  9.  * Version 3.00A by Carlo Borreo & Cesare Dieni 30-Oct-88
  10.  *
  11.  */
  12.  
  13. extern char *v_histnum, *v_except;
  14.  
  15. #define F_EXACT 0
  16. #define F_ABBR  1
  17.  
  18. #define ST_COND   0x01
  19. #define ST_NORED  0x02
  20. #define ST_NOEXP  0x04
  21. #define ST_AV     0x08 /* delimit args within a variable */
  22.  
  23. int has_wild = 0;                 /* set if any arg has wild card */
  24.  
  25. struct COMMAND {
  26.     int (*func)();
  27.     short minargs;
  28.     short stat;
  29.     int val;
  30.     char *name;
  31. };
  32.  
  33. extern char *format_insert_string();
  34. extern char *mpush(), *exarg();
  35.  
  36. extern int do_diskchange(), do_stack(), do_fault(), do_path(), do_pri();
  37. extern int do_rpn(), do_resident(), do_truerun(), do_aset(), do_howmany();
  38. extern int do_open(), do_close(), do_fileslist(), do_htype();
  39. extern int do_run(), do_number(), do_assign(), do_join();
  40. extern int do_quit(), do_set_var(), do_unset_var();
  41. extern int do_echo(), do_source(), do_mv(), do_addbuffers();
  42. extern int do_cd(), do_pwd(), do_rm(), do_mkdir(), do_history();
  43. extern int do_mem(), do_cat(), do_dir(), do_info(), do_inc();
  44. extern int do_foreach(), do_return(), do_if(), do_label(), do_goto();
  45. extern int do_input(), do_ver(), do_sleep(), do_help();
  46. extern int do_strhead(), do_strtail(), do_relabel();
  47. extern int do_copy(), date(), do_protect(), do_ps();
  48. extern int do_forever(), do_abortline(), do_strings(), do_touch();
  49. extern int do_window(), do_search(), do_filenote();
  50. char *push_cpy();
  51.  
  52. static struct COMMAND Command[] = {
  53. do_run,        0, ST_AV,    0,    "\001",   /* may call do_source */
  54. do_set_var,    0, 0, LEVEL_ALIAS,    "alias",  /* uses avline */
  55. do_abortline,    0, 0,        0,    "abortline",
  56. do_addbuffers,    2, 0,        0,    "addbuffers",
  57. do_aset,    1, 0,        0,    "aset",
  58. do_assign,    0, 0,        0,    "assign",
  59. do_cat,        0, 0,        0,    "cat",
  60. do_cd,        0, 0,        0,    "cd",
  61. do_close,    0, 0,        0,    "close",
  62. do_copy,    1, 0,        0,    "copy",
  63. do_copy,    1, 0,        0,    "cp",
  64. date,        0, 0,        0,    "date",
  65. do_rm,        0, 0,        0,    "delete",
  66. do_dir,        0, ST_NOEXP,    0,    "dir",
  67. do_diskchange,    1, 0,        0,    "diskchange",
  68. do_inc,        1, 0,        -1,    "dec",
  69. do_echo,    0, 0,        0,    "echo", /* uses avline */
  70. do_if,        0, ST_COND,    1,    "else",
  71. do_if,        0, ST_COND,    2,    "endif",
  72. do_fault,    1, 0,        0,    "fault",
  73. do_filenote,    2, 0,        0,    "filenote",
  74. do_fileslist,    0, 0,        0,    "flist",
  75. do_foreach,    3, ST_NORED,    0,    "foreach",
  76. do_forever,    1, ST_NORED,    0,    "forever",
  77. do_goto,    1, 0,        0,    "goto",
  78. do_help,    0, 0,        0,    "help",
  79. do_history,    0, 0,        0,    "history",
  80. do_howmany,    0, 0,        0,    "howmany",
  81. do_htype,    1, 0,        0,    "htype",
  82. do_if,        1, ST_COND|ST_NORED,0,    "if",
  83. do_inc,        1, 0,        1,    "inc",
  84. do_info,    0, 0,        0,    "info",
  85. do_join,    2, 0,        1,    "join",
  86. do_input,    1, 0,        0,    "input",
  87. do_label,    1, ST_COND,    0,    "label",
  88. do_dir,        0, ST_NOEXP,    0,    "ls",
  89. do_mkdir,    0, 0,        0,    "md",
  90. do_mem ,    0, 0,        0,    "mem",
  91. do_mkdir,    0, 0,        0,    "mkdir",
  92. do_mv,        2, 0,        0,    "mv",
  93. do_open,    3, 0,        0,    "open",
  94. do_path,    0, 0,        0,    "path",
  95. do_pri,        2, 0,        0,    "pri",
  96. do_protect,    2, 0,        0,    "protect",
  97. do_ps,        0, 0,        0,    "ps",
  98. do_pwd,        0, 0,        0,    "pwd",
  99. do_quit,    0, ST_NORED,    0,    "quit",
  100. do_truerun,    1, ST_NORED,    1,    "rback",
  101. do_mv,        2, 0,        0,    "rename",
  102. do_relabel,    2, 0,        0,    "relabel",
  103. do_resident,    0, 0,        0,    "resident",
  104. do_return,    0, 0,        0,    "return",
  105. do_rm,        0, 0,        0,    "rm",
  106. do_rpn,        0, ST_NOEXP|ST_NORED,0,    "rpn",
  107. do_truerun,    1, ST_NORED,    0,    "run",
  108. do_search,    2, 0,        0,    "search",
  109. do_set_var,    0, ST_AV, LEVEL_SET,    "set",
  110. do_sleep,    0, 0,        0,    "sleep",
  111. do_source,    0, ST_NORED|ST_AV, 0,    "source", /* uses avline */
  112. do_stack,    0, 0,        0,    "stack",
  113. do_strhead,    3, 0,        0,    "strhead",
  114. do_strings,    1, 0,        0,    "strings",
  115. do_strtail,    3, 0,        0,    "strtail",
  116. do_touch,    0, 0,        0,    "touch",
  117. do_cat,        0, 0,        0,    "type",
  118. do_unset_var,    0, 0, LEVEL_ALIAS,    "unalias",
  119. do_unset_var,    0, 0, LEVEL_SET  ,    "unset",
  120. do_ver,        0, 0,        0,    "version",
  121. do_window,    0, ST_NOEXP,    0,    "window",
  122. '\0',        0, 0,        0,    NULL
  123. };
  124.  
  125. static unsigned char elast;        /* last end delimeter */
  126. static char Cin_ispipe, Cout_ispipe;
  127.  
  128. exec_command(base)
  129. char *base;
  130. {
  131. register char *scr;
  132. char buf[32];
  133.  
  134. if (!H_stack) {
  135.     add_history(base);
  136.     sprintf(buf, "%d", H_tail_base + H_len);
  137.     set_var(LEVEL_SET, v_histnum, buf);
  138.     }
  139. scr = malloc((strlen(base) << 2) + 2);
  140. preformat(base, scr);
  141. return (fcomm(scr, 1) ? -1 : 1);
  142. }
  143.  
  144. isalphanum(c)
  145. register char c;
  146. {
  147. return (
  148.     (c >= '0' && c <= '9') ||
  149.     (c >= 'a' && c <= 'z') ||
  150.     (c >= 'A' && c <= 'Z') ||
  151.     (c == '_')
  152.     );
  153. }
  154.  
  155. preformat(s, d)
  156. register char *s, *d;
  157. {
  158. register int si, di, qm;
  159.  
  160. si = di = qm = 0;
  161. while (s[si] == ' ' || s[si] == 9) ++si;
  162. while (s[si]) {
  163.     if (qm && s[si] != '\"' && s[si] != '\\') {
  164.         d[di++] = s[si++] | 0x80;
  165.         continue;
  166.         }
  167.     switch (s[si]) {
  168.         case ' ':
  169.         case 9:
  170.             d[di++] = ' ';
  171.             while (s[si] == ' ' || s[si] == 9) ++si;
  172.             if (s[si] == 0 || s[si] == '|' || s[si] == ';') --di;
  173.             break;
  174.         case '*':
  175.         case '?':
  176.             d[di++] = 0x80;
  177.         case '!':
  178.             d[di++] = s[si++];
  179.             break;
  180.         case '#':
  181.             d[di++] = '\0';
  182.             while (s[si]) ++si;
  183.             break;
  184.         case ';':
  185.         case '|':
  186.             d[di++] = s[si++];
  187.             while (s[si] == ' ' || s[si] == 9) ++si;
  188.             break;
  189.         case '\\':
  190.             d[di++] = s[++si] | 0x80;
  191.             if (s[si]) ++si;
  192.             break;
  193.         case '\"':
  194.             qm = 1 - qm;
  195.             ++si;
  196.             break;
  197.         case '^':
  198.             d[di++] = s[++si] & 0x1F;
  199.             if (s[si]) ++si;
  200.             break;
  201.         case '$': /* search end of var name and place false space */
  202.             d[di++] = 0x80;
  203.             d[di++] = s[si++];
  204.             while (isalphanum(s[si])) d[di++] = s[si++];
  205.             d[di++] = 0x80;
  206.             break;
  207.         default:
  208.             d[di++] = s[si++];
  209.             break;
  210.         }
  211.     }
  212. d[di++]=0;
  213. d[di]=0;
  214. if (debug) fprintf (stderr,"PREFORMAT: %d :%s:\n", strlen(d), d);
  215. }
  216.  
  217. extern BPTR extOpen();
  218.  
  219. /*
  220.  * process formatted string.  ' ' is the delimeter.
  221.  *
  222.  *    0: check '\0': no more, stop, done.
  223.  *    1: check $.     if so, extract, format, insert
  224.  *    2: check alias. if so, extract, format, insert. goto 1
  225.  *    3: check history or substitution, extract, format, insert. goto 1
  226.  *
  227.  *    4: assume first element now internal or disk based command.
  228.  *
  229.  *    5: extract each ' ' or 0x80 delimited argument and process, placing
  230.  *       in av[] list (except 0x80 args appended).  check in order:
  231.  *
  232.  *             '$'         insert string straight
  233.  *             '>'         setup stdout
  234.  *             '>>'        setup stdout flag for append
  235.  *             '<'         setup stdin
  236.  *             '*' or '?'  do directory search and insert as separate args.
  237.  *
  238.  *             ';' 0 '|'   end of command.  if '|' setup stdout
  239.  *                          -execute command, fix stdin and out (|) sets
  240.  *                           up stdin for next guy.
  241.  */
  242.  
  243.  
  244. fcomm(str, freeok)
  245. register char *str;
  246. {
  247.    static int alias_count;
  248.    int p_alias_count = 0;
  249.    char *istr;
  250.    char *nextstr;
  251.    char *command;
  252.    char *pend_alias = NULL;
  253.    char err = 0;
  254.    has_wild = 0;
  255.  
  256.    ++alias_count;
  257.  
  258.    mpush_base();
  259.    if (*str == 0)
  260.       goto done1;
  261. step1:
  262.    if (alias_count == MAXALIAS || ++p_alias_count == MAXALIAS) {
  263.       fprintf(stderr,"Alias Loop\n");
  264.       err = 20;
  265.       goto done1;
  266.    }
  267. /*
  268.    if (str[1] == '$') {
  269.       if (istr = get_var (LEVEL_SET, str + 2))
  270.          str = format_insert_string(str, istr, &freeok);
  271.    }
  272. */
  273.    istr = NULL;
  274.    if (*(unsigned char *)str < 0x80)
  275.       istr = get_var (LEVEL_ALIAS, str);  /* only if not \command */
  276.    *str &= 0x7F;                          /* remove \ teltail     */
  277.    if (istr) {
  278.       if (*istr == '%') {
  279.          pend_alias = istr;
  280.       } else {
  281.          str = format_insert_string(str, istr, &freeok);
  282.          goto step1;
  283.       }
  284.    }
  285.    if (*str == '!') {
  286.       char *p, c;                     /* fix to allow !cmd1;!cmd2 */
  287.       for(p = str; *p && *p != ';' ; ++p);
  288.       c = *p;
  289.       *p = '\0';
  290.       istr = get_history(str);
  291.       *p = c;
  292.       replace_head(istr);
  293.       str = format_insert_string(str, istr, &freeok);
  294.       goto step1;
  295.    }
  296.    nextstr = str;
  297.    command = exarg(&nextstr);
  298.    if (*command == 0)
  299.       goto done0;
  300.    if (pend_alias == 0) {
  301.       if (cmd_stat(command) & ST_COND)
  302.          goto skipgood;
  303.    }
  304.    if (disable || forward_goto) {
  305.       while (elast && elast != ';' && elast != '|')
  306.          exarg(&nextstr);
  307.       goto done0;
  308.    }
  309. skipgood:
  310.    {
  311.       register char *arg, *ptr, *scr;
  312.       short redir;
  313.       short doexpand;
  314.       short cont;
  315.       short inc;
  316.  
  317.       ac = 1;
  318.       av[0] = command;
  319. step5:                                          /* ac = nextac */
  320.       if (!elast || elast == ';' || elast == '|')
  321.          goto stepdone;
  322.  
  323.       av[ac] = '\0';
  324.       cont = 1;
  325.       doexpand = redir = inc = 0;
  326.  
  327.       while (cont && elast) {
  328.          int cstat = cmd_stat(command);
  329.  
  330.          ptr = exarg(&nextstr);
  331.          inc = 1;
  332.          arg = "";
  333.          cont = (elast == 0x80);
  334.          switch (*ptr) {
  335.          case '<':
  336.             redir = -2;
  337.          case '>':
  338.             if (cstat & (ST_NORED | ST_COND)) {
  339.                                                         /* don't extract   */
  340.                 redir = 0;                              /* <> stuff if its */
  341.                 arg = ptr;                              /* external cmd.   */
  342.                 break;
  343.             }
  344.             ++redir;
  345.             arg = ptr + 1;
  346.             if (*arg == '>') {
  347.                redir = 2;        /* append >> */
  348.                ++arg;
  349.             }
  350.             cont = 1;
  351.             break;
  352.          case '$':
  353.             /* restore args if from set command or pend_alias */
  354.             if ((arg = get_var(LEVEL_SET, ptr + 1)) != NULL) {
  355.                if (cstat & ST_COND) {
  356.                   char *tp;
  357.                   tp = push_cpy(arg);
  358.                   arg = tp;
  359.                }
  360.                else {
  361.                   char *pe, sv, *index();
  362.                   while (pe = index(arg,0xA0)) {
  363.                      sv = *pe;
  364.                      *pe = '\0';
  365.                      av[ac++] = push_cpy(arg);
  366.                      *pe = sv;
  367.                      av[ac] = '\0';
  368.                      arg = pe+1;
  369.                   }
  370.                }
  371.             }
  372.             else
  373.                arg = ptr;
  374.             break;
  375.          case '*':
  376.          case '?':
  377.             if ((cstat & ST_NOEXP) == 0)
  378.                doexpand = 1;
  379.             arg = ptr;
  380.             break;
  381.          default:
  382.             arg = ptr;
  383.             break;
  384.          }
  385.  
  386.          /* Append arg to av[ac] */
  387.  
  388.          for (scr = arg; *scr; ++scr)
  389.             *scr &= 0x7F;
  390.          if (av[ac]) {
  391.             register char *old = av[ac];
  392.             av[ac] = mpush(strlen(arg)+strlen(av[ac]));
  393.             strcpy(av[ac], old);
  394.             strcat(av[ac], arg);
  395.          } else {
  396.             av[ac] = push_cpy(arg);
  397.          }
  398.          if (elast != 0x80)
  399.             break;
  400.       }
  401.  
  402.       /* process expansion */
  403.  
  404.       if (doexpand) {
  405.          char **eav, **ebase;
  406.          int eac;
  407.          has_wild = 1;
  408.          eav = ebase = expand(av[ac], &eac);
  409.          inc = 0;
  410.          if (eav) {
  411.             if (ac + eac + 2 > MAXAV) {
  412.                ierror (NULL, 506);
  413.                err = 1;
  414.             } else {
  415.                QuickSort(eav, eac);
  416.                for (; eac; --eac, ++eav)
  417.                   av[ac++] = push_cpy(*eav);
  418.             }
  419.             free_expand (ebase);
  420.          }
  421.       }
  422.  
  423.       /* process redirection  */
  424.  
  425.       if (redir && !err) {
  426.          register char *file = (doexpand) ? av[--ac] : av[ac];
  427.  
  428.          if (redir < 0)
  429.             Cin_name = file;
  430.          else {
  431.             Cout_name = file;
  432.             Cout_append = (redir == 2);
  433.          }
  434.          inc = 0;
  435.       }
  436.  
  437.       /* check elast for space */
  438.  
  439.       if (inc) {
  440.          ++ac;
  441.          if (ac + 2 > MAXAV) {
  442.             ierror (NULL, 506);
  443.             err = 1;                /* error condition */
  444.             elast = 0;              /* don't process any more arguemnts */
  445.          }
  446.       }
  447.       if (elast == ' ')
  448.          goto step5;
  449.    }
  450. stepdone:
  451.    av[ac] = '\0';
  452.  
  453.    /* process pipes via files */
  454.  
  455.    if (elast == '|' && !err) {
  456.       static int which;             /* 0 or 1 in case of multiple pipes */
  457.       which = 1 - which;
  458.       Cout_name = (which) ? Pipe1 : Pipe2;
  459.       Cout_ispipe = 1;
  460.    }
  461.  
  462.  
  463.    if (err)
  464.       goto done0;
  465.  
  466.    {
  467.       register int i;
  468.       char save_elast;
  469.       char *compile_av();
  470.       register char *avline;
  471.       unsigned char delim = ' ';
  472.  
  473.       save_elast = elast;
  474.       if (pend_alias || (cmd_stat(command) & ST_AV))
  475.          delim = 0xA0;
  476.       avline = compile_av(av,((pend_alias) ? 1 : 0), ac , delim);
  477.  
  478.  
  479.       if (pend_alias) {                               /* special % alias */
  480.          register char *ptr, *scr;
  481.          for (ptr = pend_alias; *ptr && *ptr != ' '; ++ptr);
  482.          set_var (LEVEL_SET, pend_alias + 1, avline);
  483.          free (avline);
  484.  
  485.          scr = malloc((strlen(ptr) << 2) + 2);
  486.          preformat (ptr, scr);
  487.          fcomm (scr, 1);
  488.          unset_var (LEVEL_SET, pend_alias + 1);
  489.       } else {                                        /* normal command  */
  490.          register int ccno;
  491.          long  oldcin  = Myprocess->pr_CIS;
  492.          long  oldcout = Myprocess->pr_COS;
  493.          char *Cin_buf;
  494.          struct FileHandle *ci;
  495.          long oldbuf;
  496.  
  497.          fflush(stdout);
  498.          ccno = find_command (command);
  499.          if ((Command[ccno].stat & (ST_NORED | ST_COND)) == 0) {
  500.             if (Cin_name) {
  501.                if ((Cin = (long)extOpen(Cin_name,1005L)) == 0L) {
  502.                   ierror (NULL, 504);
  503.                   err = 1;
  504.                   Cin_name = '\0';
  505.                } else {
  506.                   Myprocess->pr_CIS = _devtab[stdin->_unit].fd = Cin;
  507.                   ci = (struct FileHandle *)(((long)Cin)<<2);
  508.                   Cin_buf = (char *)AllocMem(202L, MEMF_PUBLIC);
  509.                   oldbuf = ci->fh_Buf;
  510.                   if (ci->fh_Buf == 0) /* fexec expects a CIS buffer */
  511.                      ci->fh_Buf = (long)Cin_buf>>2;
  512.                }
  513.             }
  514.             if (Cout_name) {
  515.                if (Cout_append && (Cout =(long)extOpen(Cout_name, 1005L)) ) {
  516.                      Seek(Cout, 0L, 1L);
  517.                } else {
  518.                   Cout = (long)extOpen(Cout_name,1006L);
  519.                }
  520.                if (Cout == NULL) {
  521.                   err = 1;
  522.                   ierror (NULL, 504);
  523.                   Cout_name = '\0';
  524.                   Cout_append = 0;
  525.                } else {
  526.                   Myprocess->pr_COS = _devtab[stdout->_unit].fd = Cout;
  527.                }
  528.             }
  529.          }
  530.          if (ac < Command[ccno].minargs + 1) {
  531.             ierror (NULL, 500);
  532.             err = -1;
  533.          } else if (!err) {
  534.             i = (*Command[ccno].func)(avline, Command[ccno].val);
  535.             if (i < 0)
  536.                i = 20;
  537.             err = i;
  538.          }
  539.          free (avline);
  540.          if (E_stack == 0 && Lastresult != err) {
  541.             Lastresult = err;
  542.             seterr();
  543.          }
  544.          if ((Command[ccno].stat & (ST_NORED | ST_COND)) == 0) {
  545.             if (Cin_name) {
  546.                fflush(stdin);
  547.                clearerr(stdin);
  548.                ci->fh_Buf = oldbuf;
  549.                extClose(Cin);
  550.                FreeMem(Cin_buf, 202L);
  551.             }
  552.             if (Cout_name) {
  553.                fflush(stdout);
  554.                clearerr(stdout);
  555.                stdout->_flags &= ~_DIRTY;    /* because of nil: device */
  556.                extClose(Cout);
  557.                Cout_append = 0;
  558.             }
  559.          }
  560.          Myprocess->pr_CIS =  _devtab[stdin->_unit].fd  = oldcin;
  561.          Myprocess->pr_COS =  _devtab[stdout->_unit].fd = oldcout;
  562.       }
  563.  
  564.       if (Cin_ispipe && Cin_name)
  565.          DeleteFile(Cin_name);
  566.       if (Cout_ispipe) {
  567.          Cin_name = Cout_name;         /* ok to assign.. static name */
  568.          Cin_ispipe = 1;
  569.       } else {
  570.          Cin_name = '\0';
  571.       }
  572.       Cout_name = '\0';
  573.       Cout_ispipe = 0;
  574.       elast = save_elast;
  575.    }
  576.    mpop_tobase();                      /* free arguments   */
  577.    mpush_base();                       /* push dummy base  */
  578.  
  579. done0:
  580.    {
  581.       char *str;
  582.       if (err && E_stack == 0) {
  583.          str = get_var(LEVEL_SET, v_except);
  584.          if (err >= ((str)?atoi(str):1)) {
  585.             if (str) {
  586.                ++H_stack;
  587.                ++E_stack;
  588.                exec_command(str);
  589.                --E_stack;
  590.                --H_stack;
  591.             } else {
  592.                Exec_abortline = 1;
  593.             }
  594.          }
  595.       }
  596.       if (elast != 0 && Exec_abortline == 0)
  597.          err = fcomm(nextstr, 0);
  598.       Exec_abortline = 0;
  599.       if (Cin_name)
  600.          DeleteFile(Cin_name);
  601.       Cin_name = NULL;
  602.       Cin_ispipe = 0;
  603.    }
  604. done1:
  605.    mpop_tobase();
  606.    if (freeok)
  607.       free(str);
  608.    --alias_count;
  609.    return ((int)err);                  /* TRUE = error occured    */
  610. }
  611.  
  612.  
  613. char *
  614. exarg(ptr)
  615. unsigned char **ptr;
  616. {
  617.    register unsigned char *end;
  618.    register unsigned char *start;
  619.  
  620.    start = end = *ptr;
  621.    while (*end && *end != 0x80 && *end != ';' && *end != '|' && *end != ' ')
  622.       ++end;
  623.    elast = *end;
  624.    *end = '\0';
  625.    *ptr = end + 1;
  626.    return ((char *)start);
  627. }
  628.  
  629. static char **Mlist;
  630.  
  631. mpush_base()
  632. {
  633.    char *str;
  634.  
  635.    str = malloc(5);
  636.    *(char ***)str = Mlist;
  637.    str[4] = 0;
  638.    Mlist = (char **)str;
  639. }
  640.  
  641. char *
  642. mpush(bytes)
  643. {
  644.    char *str;
  645.  
  646.    str = malloc(6 + bytes + 2);   /* may need extra 2 bytes in do_run() */
  647.    *(char ***)str = Mlist;
  648.    str[4] = 1;
  649.    Mlist = (char **)str;
  650.    return (str + 5);
  651. }
  652.  
  653. mpop_tobase()
  654. {
  655.    register char *next;
  656.    while (Mlist) {
  657.       next = *Mlist;
  658.       if (((char *)Mlist)[4] == 0) {
  659.          free (Mlist);
  660.          Mlist = (char **)next;
  661.          break;
  662.       }
  663.       free (Mlist);
  664.       Mlist = (char **)next;
  665.    }
  666. }
  667.  
  668.  
  669. /*
  670.  * Insert 'from' string in front of 'str' while deleting the
  671.  * first entry in 'str'.  if freeok is set, then 'str' will be
  672.  * free'd
  673.  */
  674.  
  675.  
  676.  
  677. char *
  678. format_insert_string(str, from, freeok)
  679. char *str;
  680. char *from;
  681. int *freeok;
  682. {
  683.    register char *new1, *new2;
  684.    register unsigned char *strskip;
  685.    int len;
  686.  
  687.    for (strskip = (unsigned char *)str;
  688.                    *strskip && *strskip != ' ' 
  689.                    && *strskip != ';' && *strskip != '|'
  690.                    && *strskip != 0x80; ++strskip);
  691.    len = strlen(from);
  692.    new1 = malloc((len << 2) + 2);
  693.    preformat(from, new1);
  694.    len = strlen(new1) + strlen(strskip);
  695.    new2 = malloc(len+2);
  696.    strcpy(new2, new1);
  697.    strcat(new2, strskip);
  698.    new2[len+1] = 0;
  699.    free (new1);
  700.    if (*freeok)
  701.       free (str);
  702.    *freeok = 1;
  703.    return (new2);
  704. }
  705.  
  706. cmd_stat(str)
  707. char *str;
  708. {
  709.    return(Command[find_command(str)].stat);
  710. }
  711.  
  712. find_command(str)
  713. char *str;
  714. {
  715.    register unsigned int i;
  716.    int len = strlen(str);
  717.  
  718.    if (*str >= '0'  &&  *str <= '9')
  719.       return (1);
  720.    for (i = 0; Command[i].func; ++i) {
  721.       if (strncmp (str, Command[i].name, len) == 0)
  722.          return (i);
  723.    }
  724.    return (0);
  725. }
  726.  
  727. do_help()
  728. {
  729.    register struct COMMAND *com;
  730.    int i= 0;
  731.  
  732.  
  733.    for (com = &Command[2]; com->func; ++com) {
  734.       printf ("%-12s", com->name);
  735.       if (++i  % 6 == 0) printf("\n");
  736.    }
  737.    printf("\n");
  738.    return(0);
  739. }
  740.  
  741. char *push_cpy(s)
  742. char *s;
  743. {
  744. return strcpy(mpush(strlen(s)), s);
  745. }
  746.