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