home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / bin / csh / func.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-02-05  |  29.4 KB  |  1,497 lines

  1. /*-
  2.  * Copyright (c) 1980, 1991 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  */
  33.  
  34. #ifndef lint
  35. static char sccsid[] = "@(#)func.c    5.34 (Berkeley) 2/5/92";
  36. #endif /* not lint */
  37.  
  38. #include <sys/types.h>
  39. #include <sys/stat.h>
  40. #include <signal.h>
  41. #include <locale.h>
  42. #include <stdlib.h>
  43. #include <string.h>
  44. #include <unistd.h>
  45. #if __STDC__
  46. # include <stdarg.h>
  47. #else
  48. # include <varargs.h>
  49. #endif
  50.  
  51. #include "csh.h"
  52. #include "extern.h"
  53. #include "pathnames.h"
  54.  
  55. extern char **environ;
  56.  
  57. static int zlast = -1;
  58. static void    islogin __P((void));
  59. static void    reexecute __P((struct command *));
  60. static void    preread __P((void));
  61. static void    doagain __P((void));
  62. static void    search __P((int, int, Char *));
  63. static int    getword __P((Char *));
  64. static int    keyword __P((Char *));
  65. static void    toend __P((void));
  66. static void    xecho __P((int, Char **));
  67. static void    Unsetenv __P((Char *));
  68.  
  69. struct biltins *
  70. isbfunc(t)
  71.     struct command *t;
  72. {
  73.     register Char *cp = t->t_dcom[0];
  74.     register struct biltins *bp, *bp1, *bp2;
  75.     static struct biltins label = {"", dozip, 0, 0};
  76.     static struct biltins foregnd = {"%job", dofg1, 0, 0};
  77.     static struct biltins backgnd = {"%job &", dobg1, 0, 0};
  78.  
  79.     if (lastchr(cp) == ':') {
  80.     label.bname = short2str(cp);
  81.     return (&label);
  82.     }
  83.     if (*cp == '%') {
  84.     if (t->t_dflg & F_AMPERSAND) {
  85.         t->t_dflg &= ~F_AMPERSAND;
  86.         backgnd.bname = short2str(cp);
  87.         return (&backgnd);
  88.     }
  89.     foregnd.bname = short2str(cp);
  90.     return (&foregnd);
  91.     }
  92.     /*
  93.      * Binary search Bp1 is the beginning of the current search range. Bp2 is
  94.      * one past the end.
  95.      */
  96.     for (bp1 = bfunc, bp2 = bfunc + nbfunc; bp1 < bp2;) {
  97.     register i;
  98.  
  99.     bp = bp1 + ((bp2 - bp1) >> 1);
  100.     if ((i = *cp - *bp->bname) == 0 &&
  101.         (i = Strcmp(cp, str2short(bp->bname))) == 0)
  102.         return bp;
  103.     if (i < 0)
  104.         bp2 = bp;
  105.     else
  106.         bp1 = bp + 1;
  107.     }
  108.     return (0);
  109. }
  110.  
  111. void
  112. func(t, bp)
  113.     register struct command *t;
  114.     register struct biltins *bp;
  115. {
  116.     int     i;
  117.  
  118.     xechoit(t->t_dcom);
  119.     setname(bp->bname);
  120.     i = blklen(t->t_dcom) - 1;
  121.     if (i < bp->minargs)
  122.     stderror(ERR_NAME | ERR_TOOFEW);
  123.     if (i > bp->maxargs)
  124.     stderror(ERR_NAME | ERR_TOOMANY);
  125.     (*bp->bfunct) (t->t_dcom, t);
  126. }
  127.  
  128. void
  129. /*ARGSUSED*/
  130. doonintr(v, t)
  131.     Char **v;
  132.     struct command *t;
  133. {
  134.     register Char *cp;
  135.     register Char *vv = v[1];
  136.  
  137.     if (parintr == SIG_IGN)
  138.     return;
  139.     if (setintr && intty)
  140.     stderror(ERR_NAME | ERR_TERMINAL);
  141.     cp = gointr;
  142.     gointr = 0;
  143.     xfree((ptr_t) cp);
  144.     if (vv == 0) {
  145.     if (setintr)
  146.         (void) sigblock(sigmask(SIGINT));
  147.     else
  148.         (void) signal(SIGINT, SIG_DFL);
  149.     gointr = 0;
  150.     }
  151.     else if (eq((vv = strip(vv)), STRminus)) {
  152.     (void) signal(SIGINT, SIG_IGN);
  153.     gointr = Strsave(STRminus);
  154.     }
  155.     else {
  156.     gointr = Strsave(vv);
  157.     (void) signal(SIGINT, pintr);
  158.     }
  159. }
  160.  
  161. void
  162. /*ARGSUSED*/
  163. donohup(v, t)
  164.     Char **v;
  165.     struct command *t;
  166. {
  167.     if (intty)
  168.     stderror(ERR_NAME | ERR_TERMINAL);
  169.     if (setintr == 0) {
  170.     (void) signal(SIGHUP, SIG_IGN);
  171.     }
  172. }
  173.  
  174. void
  175. /*ARGSUSED*/
  176. dozip(v, t)
  177.     Char **v;
  178.     struct command *t;
  179. {
  180.     ;
  181. }
  182.  
  183. void
  184. prvars()
  185. {
  186.     plist(&shvhed);
  187. }
  188.  
  189. void
  190. /*ARGSUSED*/
  191. doalias(v, t)
  192.     Char **v;
  193.     struct command *t;
  194. {
  195.     register struct varent *vp;
  196.     register Char *p;
  197.  
  198.     v++;
  199.     p = *v++;
  200.     if (p == 0)
  201.     plist(&aliases);
  202.     else if (*v == 0) {
  203.     vp = adrof1(strip(p), &aliases);
  204.     if (vp) {
  205.         blkpr(cshout, vp->vec);
  206.         fputc('\n', cshout);
  207.     }
  208.     }
  209.     else {
  210.     if (eq(p, STRalias) || eq(p, STRunalias)) {
  211.         setname(vis_str(p));
  212.         stderror(ERR_NAME | ERR_DANGER);
  213.     }
  214.     set1(strip(p), saveblk(v), &aliases);
  215.     }
  216. }
  217.  
  218. void
  219. /*ARGSUSED*/
  220. unalias(v, t)
  221.     Char **v;
  222.     struct command *t;
  223. {
  224.     unset1(v, &aliases);
  225. }
  226.  
  227. void
  228. /*ARGSUSED*/
  229. dologout(v, t)
  230.     Char **v;
  231.     struct command *t;
  232. {
  233.     islogin();
  234.     goodbye();
  235. }
  236.  
  237. void
  238. /*ARGSUSED*/
  239. dologin(v, t)
  240.     Char **v;
  241.     struct command *t;
  242. {
  243.     islogin();
  244.     rechist();
  245.     (void) signal(SIGTERM, parterm);
  246.     (void) execl(_PATH_LOGIN, "login", short2str(v[1]), NULL);
  247.     untty();
  248.     xexit(1);
  249. }
  250.  
  251. static void
  252. islogin()
  253. {
  254.     if (chkstop == 0 && setintr)
  255.     panystop(0);
  256.     if (loginsh)
  257.     return;
  258.     stderror(ERR_NOTLOGIN);
  259. }
  260.  
  261. void
  262. doif(v, kp)
  263.     Char  **v;
  264.     struct command *kp;
  265. {
  266.     register int i;
  267.     register Char **vv;
  268.  
  269.     v++;
  270.     i = expr(&v);
  271.     vv = v;
  272.     if (*vv == NULL)
  273.     stderror(ERR_NAME | ERR_EMPTYIF);
  274.     if (eq(*vv, STRthen)) {
  275.     if (*++vv)
  276.         stderror(ERR_NAME | ERR_IMPRTHEN);
  277.     setname(vis_str(STRthen));
  278.     /*
  279.      * If expression was zero, then scan to else, otherwise just fall into
  280.      * following code.
  281.      */
  282.     if (!i)
  283.         search(T_IF, 0, NULL);
  284.     return;
  285.     }
  286.     /*
  287.      * Simple command attached to this if. Left shift the node in this tree,
  288.      * munging it so we can reexecute it.
  289.      */
  290.     if (i) {
  291.     lshift(kp->t_dcom, vv - kp->t_dcom);
  292.     reexecute(kp);
  293.     donefds();
  294.     }
  295. }
  296.  
  297. /*
  298.  * Reexecute a command, being careful not
  299.  * to redo i/o redirection, which is already set up.
  300.  */
  301. static void
  302. reexecute(kp)
  303.     register struct command *kp;
  304. {
  305.     kp->t_dflg &= F_SAVE;
  306.     kp->t_dflg |= F_REPEAT;
  307.     /*
  308.      * If tty is still ours to arbitrate, arbitrate it; otherwise dont even set
  309.      * pgrp's as the jobs would then have no way to get the tty (we can't give
  310.      * it to them, and our parent wouldn't know their pgrp, etc.
  311.      */
  312.     execute(kp, (tpgrp > 0 ? tpgrp : -1), NULL, NULL);
  313. }
  314.  
  315. void
  316. /*ARGSUSED*/
  317. doelse(v, t)
  318.     Char **v;
  319.     struct command *t;
  320. {
  321.     search(T_ELSE, 0, NULL);
  322. }
  323.  
  324. void
  325. /*ARGSUSED*/
  326. dogoto(v, t)
  327.     Char **v;
  328.     struct command *t;
  329. {
  330.     Char   *lp;
  331.  
  332.     gotolab(lp = globone(v[1], G_ERROR));
  333.     xfree((ptr_t) lp);
  334. }
  335.  
  336. void
  337. gotolab(lab)
  338.     Char *lab;
  339. {
  340.     register struct whyle *wp;
  341.     /*
  342.      * While we still can, locate any unknown ends of existing loops. This
  343.      * obscure code is the WORST result of the fact that we don't really parse.
  344.      */
  345.     zlast = T_GOTO;
  346.     for (wp = whyles; wp; wp = wp->w_next)
  347.     if (wp->w_end.type == F_SEEK && wp->w_end.f_seek == 0) {
  348.         search(T_BREAK, 0, NULL);
  349.         btell(&wp->w_end);
  350.     }
  351.     else
  352.         bseek(&wp->w_end);
  353.     search(T_GOTO, 0, lab);
  354.     /*
  355.      * Eliminate loops which were exited.
  356.      */
  357.     wfree();
  358. }
  359.  
  360. void
  361. /*ARGSUSED*/
  362. doswitch(v, t)
  363.     Char **v;
  364.     struct command *t;
  365. {
  366.     register Char *cp, *lp;
  367.  
  368.     v++;
  369.     if (!*v || *(*v++) != '(')
  370.     stderror(ERR_SYNTAX);
  371.     cp = **v == ')' ? STRNULL : *v++;
  372.     if (*(*v++) != ')')
  373.     v--;
  374.     if (*v)
  375.     stderror(ERR_SYNTAX);
  376.     search(T_SWITCH, 0, lp = globone(cp, G_ERROR));
  377.     xfree((ptr_t) lp);
  378. }
  379.  
  380. void
  381. /*ARGSUSED*/
  382. dobreak(v, t)
  383.     Char **v;
  384.     struct command *t;
  385. {
  386.     if (whyles)
  387.     toend();
  388.     else
  389.     stderror(ERR_NAME | ERR_NOTWHILE);
  390. }
  391.  
  392. void
  393. /*ARGSUSED*/
  394. doexit(v, t)
  395.     Char **v;
  396.     struct command *t;
  397. {
  398.     if (chkstop == 0 && (intty || intact) && evalvec == 0)
  399.     panystop(0);
  400.     /*
  401.      * Don't DEMAND parentheses here either.
  402.      */
  403.     v++;
  404.     if (*v) {
  405.     set(STRstatus, putn(expr(&v)));
  406.     if (*v)
  407.         stderror(ERR_NAME | ERR_EXPRESSION);
  408.     }
  409.     btoeof();
  410.     if (intty)
  411.     (void) close(SHIN);
  412. }
  413.  
  414. void
  415. /*ARGSUSED*/
  416. doforeach(v, t)
  417.     Char **v;
  418.     struct command *t;
  419. {
  420.     register Char *cp, *sp;
  421.     register struct whyle *nwp;
  422.  
  423.     v++;
  424.     sp = cp = strip(*v);
  425.     if (!letter(*sp))
  426.     stderror(ERR_NAME | ERR_VARBEGIN);
  427.     while (*cp && alnum(*cp))
  428.     cp++;
  429.     if (*cp)
  430.     stderror(ERR_NAME | ERR_VARALNUM);
  431.     if ((cp - sp) > MAXVARLEN)
  432.     stderror(ERR_NAME | ERR_VARTOOLONG);
  433.     cp = *v++;
  434.     if (v[0][0] != '(' || v[blklen(v) - 1][0] != ')')
  435.     stderror(ERR_NAME | ERR_NOPAREN);
  436.     v++;
  437.     gflag = 0, tglob(v);
  438.     v = globall(v);
  439.     if (v == 0)
  440.     stderror(ERR_NAME | ERR_NOMATCH);
  441.     nwp = (struct whyle *) xcalloc(1, sizeof *nwp);
  442.     nwp->w_fe = nwp->w_fe0 = v;
  443.     gargv = 0;
  444.     btell(&nwp->w_start);
  445.     nwp->w_fename = Strsave(cp);
  446.     nwp->w_next = whyles;
  447.     nwp->w_end.type = F_SEEK;
  448.     whyles = nwp;
  449.     /*
  450.      * Pre-read the loop so as to be more comprehensible to a terminal user.
  451.      */
  452.     zlast = T_FOREACH;
  453.     if (intty)
  454.     preread();
  455.     doagain();
  456. }
  457.  
  458. void
  459. /*ARGSUSED*/
  460. dowhile(v, t)
  461.     Char **v;
  462.     struct command *t;
  463. {
  464.     register int status;
  465.     register bool again = whyles != 0 && SEEKEQ(&whyles->w_start, &lineloc) &&
  466.     whyles->w_fename == 0;
  467.  
  468.     v++;
  469.     /*
  470.      * Implement prereading here also, taking care not to evaluate the
  471.      * expression before the loop has been read up from a terminal.
  472.      */
  473.     if (intty && !again)
  474.     status = !exp0(&v, 1);
  475.     else
  476.     status = !expr(&v);
  477.     if (*v)
  478.     stderror(ERR_NAME | ERR_EXPRESSION);
  479.     if (!again) {
  480.     register struct whyle *nwp =
  481.     (struct whyle *) xcalloc(1, sizeof(*nwp));
  482.  
  483.     nwp->w_start = lineloc;
  484.     nwp->w_end.type = F_SEEK;
  485.     nwp->w_end.f_seek = 0;
  486.     nwp->w_next = whyles;
  487.     whyles = nwp;
  488.     zlast = T_WHILE;
  489.     if (intty) {
  490.         /*
  491.          * The tty preread
  492.          */
  493.         preread();
  494.         doagain();
  495.         return;
  496.     }
  497.     }
  498.     if (status)
  499.     /* We ain't gonna loop no more, no more! */
  500.     toend();
  501. }
  502.  
  503. static void
  504. preread()
  505. {
  506.     whyles->w_end.type = I_SEEK;
  507.     if (setintr)
  508.     (void) sigsetmask(sigblock((sigset_t) 0) & ~sigmask(SIGINT));
  509.  
  510.     search(T_BREAK, 0, NULL);        /* read the expression in */
  511.     if (setintr)
  512.     (void) sigblock(sigmask(SIGINT));
  513.     btell(&whyles->w_end);
  514. }
  515.  
  516. void
  517. /*ARGSUSED*/
  518. doend(v, t)
  519.     Char **v;
  520.     struct command *t;
  521. {
  522.     if (!whyles)
  523.     stderror(ERR_NAME | ERR_NOTWHILE);
  524.     btell(&whyles->w_end);
  525.     doagain();
  526. }
  527.  
  528. void
  529. /*ARGSUSED*/
  530. docontin(v, t)
  531.     Char **v;
  532.     struct command *t;
  533. {
  534.     if (!whyles)
  535.     stderror(ERR_NAME | ERR_NOTWHILE);
  536.     doagain();
  537. }
  538.  
  539. static void
  540. doagain()
  541. {
  542.     /* Repeating a while is simple */
  543.     if (whyles->w_fename == 0) {
  544.     bseek(&whyles->w_start);
  545.     return;
  546.     }
  547.     /*
  548.      * The foreach variable list actually has a spurious word ")" at the end of
  549.      * the w_fe list.  Thus we are at the of the list if one word beyond this
  550.      * is 0.
  551.      */
  552.     if (!whyles->w_fe[1]) {
  553.     dobreak(NULL, NULL);
  554.     return;
  555.     }
  556.     set(whyles->w_fename, Strsave(*whyles->w_fe++));
  557.     bseek(&whyles->w_start);
  558. }
  559.  
  560. void
  561. dorepeat(v, kp)
  562.     Char  **v;
  563.     struct command *kp;
  564. {
  565.     register int i;
  566.     register sigset_t omask = 0;
  567.  
  568.     i = getn(v[1]);
  569.     if (setintr)
  570.     omask = sigblock(sigmask(SIGINT)) & ~sigmask(SIGINT);
  571.     lshift(v, 2);
  572.     while (i > 0) {
  573.     if (setintr)
  574.         (void) sigsetmask(omask);
  575.     reexecute(kp);
  576.     --i;
  577.     }
  578.     donefds();
  579.     if (setintr)
  580.     (void) sigsetmask(omask);
  581. }
  582.  
  583. void
  584. /*ARGSUSED*/
  585. doswbrk(v, t)
  586.     Char **v;
  587.     struct command *t;
  588. {
  589.     search(T_BRKSW, 0, NULL);
  590. }
  591.  
  592. int
  593. srchx(cp)
  594.     register Char *cp;
  595. {
  596.     register struct srch *sp, *sp1, *sp2;
  597.     register i;
  598.  
  599.     /*
  600.      * Binary search Sp1 is the beginning of the current search range. Sp2 is
  601.      * one past the end.
  602.      */
  603.     for (sp1 = srchn, sp2 = srchn + nsrchn; sp1 < sp2;) {
  604.     sp = sp1 + ((sp2 - sp1) >> 1);
  605.     if ((i = *cp - *sp->s_name) == 0 &&
  606.         (i = Strcmp(cp, str2short(sp->s_name))) == 0)
  607.         return sp->s_value;
  608.     if (i < 0)
  609.         sp2 = sp;
  610.     else
  611.         sp1 = sp + 1;
  612.     }
  613.     return (-1);
  614. }
  615.  
  616. static Char Stype;
  617. static Char *Sgoal;
  618.  
  619. /*VARARGS2*/
  620. static void
  621. search(type, level, goal)
  622.     int     type;
  623.     register int level;
  624.     Char   *goal;
  625. {
  626.     Char    wordbuf[BUFSIZ];
  627.     register Char *aword = wordbuf;
  628.     register Char *cp;
  629.  
  630.     Stype = type;
  631.     Sgoal = goal;
  632.     if (type == T_GOTO) {
  633.     struct Ain a;
  634.     a.type = F_SEEK;
  635.     a.f_seek = 0;
  636.     bseek(&a);
  637.     }
  638.     do {
  639.     if (intty && fseekp == feobp && aret == F_SEEK)
  640.         (void) fprintf(cshout, "? "), (void) fflush(cshout);
  641.     aword[0] = 0;
  642.     (void) getword(aword);
  643.     switch (srchx(aword)) {
  644.  
  645.     case T_ELSE:
  646.         if (level == 0 && type == T_IF)
  647.         return;
  648.         break;
  649.  
  650.     case T_IF:
  651.         while (getword(aword))
  652.         continue;
  653.         if ((type == T_IF || type == T_ELSE) &&
  654.         eq(aword, STRthen))
  655.         level++;
  656.         break;
  657.  
  658.     case T_ENDIF:
  659.         if (type == T_IF || type == T_ELSE)
  660.         level--;
  661.         break;
  662.  
  663.     case T_FOREACH:
  664.     case T_WHILE:
  665.         if (type == T_BREAK)
  666.         level++;
  667.         break;
  668.  
  669.     case T_END:
  670.         if (type == T_BREAK)
  671.         level--;
  672.         break;
  673.  
  674.     case T_SWITCH:
  675.         if (type == T_SWITCH || type == T_BRKSW)
  676.         level++;
  677.         break;
  678.  
  679.     case T_ENDSW:
  680.         if (type == T_SWITCH || type == T_BRKSW)
  681.         level--;
  682.         break;
  683.  
  684.     case T_LABEL:
  685.         if (type == T_GOTO && getword(aword) && eq(aword, goal))
  686.         level = -1;
  687.         break;
  688.  
  689.     default:
  690.         if (type != T_GOTO && (type != T_SWITCH || level != 0))
  691.         break;
  692.         if (lastchr(aword) != ':')
  693.         break;
  694.         aword[Strlen(aword) - 1] = 0;
  695.         if (type == T_GOTO && eq(aword, goal) ||
  696.         type == T_SWITCH && eq(aword, STRdefault))
  697.         level = -1;
  698.         break;
  699.  
  700.     case T_CASE:
  701.         if (type != T_SWITCH || level != 0)
  702.         break;
  703.         (void) getword(aword);
  704.         if (lastchr(aword) == ':')
  705.         aword[Strlen(aword) - 1] = 0;
  706.         cp = strip(Dfix1(aword));
  707.         if (Gmatch(goal, cp))
  708.         level = -1;
  709.         xfree((ptr_t) cp);
  710.         break;
  711.  
  712.     case T_DEFAULT:
  713.         if (type == T_SWITCH && level == 0)
  714.         level = -1;
  715.         break;
  716.     }
  717.     (void) getword(NULL);
  718.     } while (level >= 0);
  719. }
  720.  
  721. static int
  722. getword(wp)
  723.     register Char *wp;
  724. {
  725.     register int found = 0;
  726.     register int c, d;
  727.     int     kwd = 0;
  728.     Char   *owp = wp;
  729.  
  730.     c = readc(1);
  731.     d = 0;
  732.     do {
  733.     while (c == ' ' || c == '\t')
  734.         c = readc(1);
  735.     if (c == '#')
  736.         do
  737.         c = readc(1);
  738.         while (c >= 0 && c != '\n');
  739.     if (c < 0)
  740.         goto past;
  741.     if (c == '\n') {
  742.         if (wp)
  743.         break;
  744.         return (0);
  745.     }
  746.     unreadc(c);
  747.     found = 1;
  748.     do {
  749.         c = readc(1);
  750.         if (c == '\\' && (c = readc(1)) == '\n')
  751.         c = ' ';
  752.         if (c == '\'' || c == '"')
  753.         if (d == 0)
  754.             d = c;
  755.         else if (d == c)
  756.             d = 0;
  757.         if (c < 0)
  758.         goto past;
  759.         if (wp) {
  760.         *wp++ = c;
  761.         *wp = 0;    /* end the string b4 test */
  762.         }
  763.     } while ((d || !(kwd = keyword(owp)) && c != ' '
  764.           && c != '\t') && c != '\n');
  765.     } while (wp == 0);
  766.  
  767.     /*
  768.      * if we have read a keyword ( "if", "switch" or "while" ) then we do not
  769.      * need to unreadc the look-ahead char
  770.      */
  771.     if (!kwd) {
  772.     unreadc(c);
  773.     if (found)
  774.         *--wp = 0;
  775.     }
  776.  
  777.     return (found);
  778.  
  779. past:
  780.     switch (Stype) {
  781.  
  782.     case T_IF:
  783.     stderror(ERR_NAME | ERR_NOTFOUND, "then/endif");
  784.  
  785.     case T_ELSE:
  786.     stderror(ERR_NAME | ERR_NOTFOUND, "endif");
  787.  
  788.     case T_BRKSW:
  789.     case T_SWITCH:
  790.     stderror(ERR_NAME | ERR_NOTFOUND, "endsw");
  791.  
  792.     case T_BREAK:
  793.     stderror(ERR_NAME | ERR_NOTFOUND, "end");
  794.  
  795.     case T_GOTO:
  796.     setname(vis_str(Sgoal));
  797.     stderror(ERR_NAME | ERR_NOTFOUND, "label");
  798.     }
  799.     /* NOTREACHED */
  800.     return (0);
  801. }
  802.  
  803. /*
  804.  * keyword(wp) determines if wp is one of the built-n functions if,
  805.  * switch or while. It seems that when an if statement looks like
  806.  * "if(" then getword above sucks in the '(' and so the search routine
  807.  * never finds what it is scanning for. Rather than rewrite doword, I hack
  808.  * in a test to see if the string forms a keyword. Then doword stops
  809.  * and returns the word "if" -strike
  810.  */
  811.  
  812. static int
  813. keyword(wp)
  814.     Char   *wp;
  815. {
  816.     static Char STRif[] = {'i', 'f', '\0'};
  817.     static Char STRwhile[] = {'w', 'h', 'i', 'l', 'e', '\0'};
  818.     static Char STRswitch[] = {'s', 'w', 'i', 't', 'c', 'h', '\0'};
  819.  
  820.     if (!wp)
  821.     return (0);
  822.  
  823.     if ((Strcmp(wp, STRif) == 0) || (Strcmp(wp, STRwhile) == 0)
  824.     || (Strcmp(wp, STRswitch) == 0))
  825.     return (1);
  826.  
  827.     return (0);
  828. }
  829.  
  830. static void
  831. toend()
  832. {
  833.     if (whyles->w_end.type == F_SEEK && whyles->w_end.f_seek == 0) {
  834.     search(T_BREAK, 0, NULL);
  835.     btell(&whyles->w_end);
  836.     whyles->w_end.f_seek--;
  837.     }
  838.     else
  839.     bseek(&whyles->w_end);
  840.     wfree();
  841. }
  842.  
  843. void
  844. wfree()
  845. {
  846.     struct Ain    o;
  847.     struct whyle *nwp;
  848.  
  849.     btell(&o);
  850.  
  851.     for (; whyles; whyles = nwp) {
  852.     register struct whyle *wp = whyles;
  853.     nwp = wp->w_next;
  854.  
  855.     /*
  856.      * We free loops that have different seek types.
  857.      */
  858.     if (wp->w_end.type != I_SEEK && wp->w_start.type == wp->w_end.type &&
  859.         wp->w_start.type == o.type) {
  860.         if (wp->w_end.type == F_SEEK) {
  861.         if (o.f_seek >= wp->w_start.f_seek && 
  862.             (wp->w_end.f_seek == 0 || o.f_seek < wp->w_end.f_seek))
  863.             break;
  864.         }
  865.         else {
  866.         if (o.a_seek >= wp->w_start.a_seek && 
  867.             (wp->w_end.a_seek == 0 || o.a_seek < wp->w_end.a_seek))
  868.             break;
  869.         }
  870.     }
  871.  
  872.     if (wp->w_fe0)
  873.         blkfree(wp->w_fe0);
  874.     if (wp->w_fename)
  875.         xfree((ptr_t) wp->w_fename);
  876.     xfree((ptr_t) wp);
  877.     }
  878. }
  879.  
  880. void
  881. /*ARGSUSED*/
  882. doecho(v, t)
  883.     Char **v;
  884.     struct command *t;
  885. {
  886.     xecho(' ', v);
  887. }
  888.  
  889. void
  890. /*ARGSUSED*/
  891. doglob(v, t)
  892.     Char **v;
  893.     struct command *t;
  894. {
  895.     xecho(0, v);
  896.     (void) fflush(cshout);
  897. }
  898.  
  899. static void
  900. xecho(sep, v)
  901.     int    sep;
  902.     register Char **v;
  903. {
  904.     register Char *cp;
  905.     int     nonl = 0;
  906.  
  907.     if (setintr)
  908.     (void) sigsetmask(sigblock((sigset_t) 0) & ~sigmask(SIGINT));
  909.     v++;
  910.     if (*v == 0)
  911.     return;
  912.     gflag = 0, tglob(v);
  913.     if (gflag) {
  914.     v = globall(v);
  915.     if (v == 0)
  916.         stderror(ERR_NAME | ERR_NOMATCH);
  917.     }
  918.     else {
  919.     v = gargv = saveblk(v);
  920.     trim(v);
  921.     }
  922.     if (sep == ' ' && *v && eq(*v, STRmn))
  923.     nonl++, v++;
  924.     while (cp = *v++) {
  925.     register int c;
  926.  
  927.     while (c = *cp++)
  928.         (void) vis_fputc(c | QUOTE, cshout);
  929.  
  930.     if (*v)
  931.         (void) vis_fputc(sep | QUOTE, cshout);
  932.     }
  933.     if (sep && nonl == 0)
  934.     (void) fputc('\n', cshout);
  935.     else
  936.     (void) fflush(cshout);
  937.     if (setintr)
  938.     (void) sigblock(sigmask(SIGINT));
  939.     if (gargv)
  940.     blkfree(gargv), gargv = 0;
  941. }
  942.  
  943. void
  944. /*ARGSUSED*/
  945. dosetenv(v, t)
  946.     Char **v;
  947.     struct command *t;
  948. {
  949.     Char   *vp, *lp;
  950.  
  951.     v++;
  952.     if ((vp = *v++) == 0) {
  953.     register Char **ep;
  954.  
  955.     if (setintr)
  956.         (void) sigsetmask(sigblock((sigset_t) 0) & ~sigmask(SIGINT));
  957.     for (ep = STR_environ; *ep; ep++)
  958.         (void) fprintf(cshout, "%s\n", vis_str(*ep));
  959.     return;
  960.     }
  961.     if ((lp = *v++) == 0)
  962.     lp = STRNULL;
  963.     Setenv(vp, lp = globone(lp, G_APPEND));
  964.     if (eq(vp, STRPATH)) {
  965.     importpath(lp);
  966.     dohash(NULL, NULL);
  967.     }
  968.     else if (eq(vp, STRLANG) || eq(vp, STRLC_CTYPE)) {
  969. #ifdef NLS
  970.     int     k;
  971.  
  972.     (void) setlocale(LC_ALL, "");
  973.     for (k = 0200; k <= 0377 && !Isprint(k); k++)
  974.         continue;
  975.     AsciiOnly = k > 0377;
  976. #else
  977.     AsciiOnly = 0;
  978. #endif                /* NLS */
  979.     }
  980.     xfree((ptr_t) lp);
  981. }
  982.  
  983. void
  984. /*ARGSUSED*/
  985. dounsetenv(v, t)
  986.     Char **v;
  987.     struct command *t;
  988. {
  989.     Char  **ep, *p, *n;
  990.     int     i, maxi;
  991.     static Char *name = NULL;
  992.  
  993.     if (name)
  994.     xfree((ptr_t) name);
  995.     /*
  996.      * Find the longest environment variable
  997.      */
  998.     for (maxi = 0, ep = STR_environ; *ep; ep++) {
  999.     for (i = 0, p = *ep; *p && *p != '='; p++, i++)
  1000.         continue;
  1001.     if (i > maxi)
  1002.         maxi = i;
  1003.     }
  1004.  
  1005.     name = (Char *) xmalloc((size_t) (maxi + 1) * sizeof(Char));
  1006.  
  1007.     while (++v && *v)
  1008.     for (maxi = 1; maxi;)
  1009.         for (maxi = 0, ep = STR_environ; *ep; ep++) {
  1010.         for (n = name, p = *ep; *p && *p != '='; *n++ = *p++)
  1011.             continue;
  1012.         *n = '\0';
  1013.         if (!Gmatch(name, *v))
  1014.             continue;
  1015.         maxi = 1;
  1016.         if (eq(name, STRLANG) || eq(name, STRLC_CTYPE)) {
  1017. #ifdef NLS
  1018.             int     k;
  1019.  
  1020.             (void) setlocale(LC_ALL, "");
  1021.             for (k = 0200; k <= 0377 && !Isprint(k); k++)
  1022.             continue;
  1023.             AsciiOnly = k > 0377;
  1024. #else
  1025.             AsciiOnly = getenv("LANG") == NULL &&
  1026.             getenv("LC_CTYPE") == NULL;
  1027. #endif                /* NLS */
  1028.         }
  1029.         /*
  1030.          * Delete name, and start again cause the environment changes
  1031.          */
  1032.         Unsetenv(name);
  1033.         break;
  1034.         }
  1035.     xfree((ptr_t) name);
  1036.     name = NULL;
  1037. }
  1038.  
  1039. void
  1040. Setenv(name, val)
  1041.     Char   *name, *val;
  1042. {
  1043.     register Char **ep = STR_environ;
  1044.     register Char *cp, *dp;
  1045.     Char   *blk[2];
  1046.     Char  **oep = ep;
  1047.  
  1048.  
  1049.     for (; *ep; ep++) {
  1050.     for (cp = name, dp = *ep; *cp && *cp == *dp; cp++, dp++)
  1051.         continue;
  1052.     if (*cp != 0 || *dp != '=')
  1053.         continue;
  1054.     cp = Strspl(STRequal, val);
  1055.     xfree((ptr_t) * ep);
  1056.     *ep = strip(Strspl(name, cp));
  1057.     xfree((ptr_t) cp);
  1058.     blkfree((Char **) environ);
  1059.     environ = short2blk(STR_environ);
  1060.     return;
  1061.     }
  1062.     cp = Strspl(name, STRequal);
  1063.     blk[0] = strip(Strspl(cp, val));
  1064.     xfree((ptr_t) cp);
  1065.     blk[1] = 0;
  1066.     STR_environ = blkspl(STR_environ, blk);
  1067.     blkfree((Char **) environ);
  1068.     environ = short2blk(STR_environ);
  1069.     xfree((ptr_t) oep);
  1070. }
  1071.  
  1072. static void
  1073. Unsetenv(name)
  1074.     Char   *name;
  1075. {
  1076.     register Char **ep = STR_environ;
  1077.     register Char *cp, *dp;
  1078.     Char  **oep = ep;
  1079.  
  1080.     for (; *ep; ep++) {
  1081.     for (cp = name, dp = *ep; *cp && *cp == *dp; cp++, dp++)
  1082.         continue;
  1083.     if (*cp != 0 || *dp != '=')
  1084.         continue;
  1085.     cp = *ep;
  1086.     *ep = 0;
  1087.     STR_environ = blkspl(STR_environ, ep + 1);
  1088.     environ = short2blk(STR_environ);
  1089.     *ep = cp;
  1090.     xfree((ptr_t) cp);
  1091.     xfree((ptr_t) oep);
  1092.     return;
  1093.     }
  1094. }
  1095.  
  1096. void
  1097. /*ARGSUSED*/
  1098. doumask(v, t)
  1099.     Char **v;
  1100.     struct command *t;
  1101. {
  1102.     register Char *cp = v[1];
  1103.     register int i;
  1104.  
  1105.     if (cp == 0) {
  1106.     i = umask(0);
  1107.     (void) umask(i);
  1108.     (void) fprintf(cshout, "%o\n", i);
  1109.     return;
  1110.     }
  1111.     i = 0;
  1112.     while (Isdigit(*cp) && *cp != '8' && *cp != '9')
  1113.     i = i * 8 + *cp++ - '0';
  1114.     if (*cp || i < 0 || i > 0777)
  1115.     stderror(ERR_NAME | ERR_MASK);
  1116.     (void) umask(i);
  1117. }
  1118.  
  1119. typedef int RLIM_TYPE;
  1120.  
  1121. static struct limits {
  1122.     int     limconst;
  1123.     char   *limname;
  1124.     int     limdiv;
  1125.     char   *limscale;
  1126. }       limits[] = {
  1127.     RLIMIT_CPU,        "cputime",    1,    "seconds",
  1128.     RLIMIT_FSIZE,    "filesize",    1024,    "kbytes",
  1129.     RLIMIT_DATA,    "datasize",    1024,    "kbytes",
  1130.     RLIMIT_STACK,    "stacksize",    1024,    "kbytes",
  1131.     RLIMIT_CORE,    "coredumpsize", 1024,    "kbytes",
  1132.     RLIMIT_RSS,        "memoryuse",    1024,    "kbytes",
  1133.     RLIMIT_MEMLOCK,    "memorylocked",    1024,    "kbytes",
  1134.     RLIMIT_NPROC,    "maxproc",    1,    "",
  1135.     RLIMIT_OFILE,    "openfiles",    1,    "",
  1136.     -1,            NULL,        0,    NULL
  1137. };
  1138.  
  1139. static struct limits *findlim();
  1140. static RLIM_TYPE getval();
  1141. static void limtail();
  1142. static void plim();
  1143. static int setlim();
  1144.  
  1145. static struct limits *
  1146. findlim(cp)
  1147.     Char   *cp;
  1148. {
  1149.     register struct limits *lp, *res;
  1150.  
  1151.     res = (struct limits *) NULL;
  1152.     for (lp = limits; lp->limconst >= 0; lp++)
  1153.     if (prefix(cp, str2short(lp->limname))) {
  1154.         if (res)
  1155.         stderror(ERR_NAME | ERR_AMBIG);
  1156.         res = lp;
  1157.     }
  1158.     if (res)
  1159.     return (res);
  1160.     stderror(ERR_NAME | ERR_LIMIT);
  1161.     /* NOTREACHED */
  1162.     return (0);
  1163. }
  1164.  
  1165. void
  1166. /*ARGSUSED*/
  1167. dolimit(v, t)
  1168.     Char **v;
  1169.     struct command *t;
  1170. {
  1171.     register struct limits *lp;
  1172.     register RLIM_TYPE limit;
  1173.     char    hard = 0;
  1174.  
  1175.     v++;
  1176.     if (*v && eq(*v, STRmh)) {
  1177.     hard = 1;
  1178.     v++;
  1179.     }
  1180.     if (*v == 0) {
  1181.     for (lp = limits; lp->limconst >= 0; lp++)
  1182.         plim(lp, hard);
  1183.     return;
  1184.     }
  1185.     lp = findlim(v[0]);
  1186.     if (v[1] == 0) {
  1187.     plim(lp, hard);
  1188.     return;
  1189.     }
  1190.     limit = getval(lp, v + 1);
  1191.     if (setlim(lp, hard, limit) < 0)
  1192.     stderror(ERR_SILENT);
  1193. }
  1194.  
  1195. static  RLIM_TYPE
  1196. getval(lp, v)
  1197.     register struct limits *lp;
  1198.     Char  **v;
  1199. {
  1200.     register float f;
  1201.     double  atof();
  1202.     Char   *cp = *v++;
  1203.  
  1204.     f = atof(short2str(cp));
  1205.  
  1206.     while (Isdigit(*cp) || *cp == '.' || *cp == 'e' || *cp == 'E')
  1207.     cp++;
  1208.     if (*cp == 0) {
  1209.     if (*v == 0)
  1210.         return ((RLIM_TYPE) ((f + 0.5) * lp->limdiv));
  1211.     cp = *v;
  1212.     }
  1213.     switch (*cp) {
  1214.     case ':':
  1215.     if (lp->limconst != RLIMIT_CPU)
  1216.         goto badscal;
  1217.     return ((RLIM_TYPE) (f * 60.0 + atof(short2str(cp + 1))));
  1218.     case 'h':
  1219.     if (lp->limconst != RLIMIT_CPU)
  1220.         goto badscal;
  1221.     limtail(cp, "hours");
  1222.     f *= 3600.0;
  1223.     break;
  1224.     case 'm':
  1225.     if (lp->limconst == RLIMIT_CPU) {
  1226.         limtail(cp, "minutes");
  1227.         f *= 60.0;
  1228.         break;
  1229.     }
  1230.     *cp = 'm';
  1231.     limtail(cp, "megabytes");
  1232.     f *= 1024.0 * 1024.0;
  1233.     break;
  1234.     case 's':
  1235.     if (lp->limconst != RLIMIT_CPU)
  1236.         goto badscal;
  1237.     limtail(cp, "seconds");
  1238.     break;
  1239.     case 'M':
  1240.     if (lp->limconst == RLIMIT_CPU)
  1241.         goto badscal;
  1242.     *cp = 'm';
  1243.     limtail(cp, "megabytes");
  1244.     f *= 1024.0 * 1024.0;
  1245.     break;
  1246.     case 'k':
  1247.     if (lp->limconst == RLIMIT_CPU)
  1248.         goto badscal;
  1249.     limtail(cp, "kbytes");
  1250.     f *= 1024.0;
  1251.     break;
  1252.     case 'u':
  1253.     limtail(cp, "unlimited");
  1254.     return (RLIM_INFINITY);
  1255.     default:
  1256. badscal:
  1257.     stderror(ERR_NAME | ERR_SCALEF);
  1258.     }
  1259.     f += 0.5;
  1260.     if (f > (float) 0x7fffffff)
  1261.     return 0x7fffffff;
  1262.     else if (f < (float) 0x80000000)
  1263.     return 0x80000000;
  1264.     else
  1265.     return ((RLIM_TYPE) f);
  1266. }
  1267.  
  1268. static void
  1269. limtail(cp, str)
  1270.     Char   *cp;
  1271.     char   *str;
  1272. {
  1273.     while (*cp && *cp == *str)
  1274.     cp++, str++;
  1275.     if (*cp)
  1276.     stderror(ERR_BADSCALE, str);
  1277. }
  1278.  
  1279.  
  1280. /*ARGSUSED*/
  1281. static void
  1282. plim(lp, hard)
  1283.     register struct limits *lp;
  1284.     Char    hard;
  1285. {
  1286.     struct rlimit rlim;
  1287.     RLIM_TYPE limit;
  1288.  
  1289.     (void) fprintf(cshout, "%s \t", lp->limname);
  1290.  
  1291.     (void) getrlimit(lp->limconst, &rlim);
  1292.     limit = hard ? rlim.rlim_max : rlim.rlim_cur;
  1293.  
  1294.     if (limit == RLIM_INFINITY)
  1295.     (void) fprintf(cshout, "unlimited");
  1296.     else if (lp->limconst == RLIMIT_CPU)
  1297.     psecs((long) limit);
  1298.     else
  1299.     (void) fprintf(cshout, "%ld %s", (long) (limit / lp->limdiv),
  1300.                lp->limscale);
  1301.     (void) fputc('\n', cshout);
  1302. }
  1303.  
  1304. void
  1305. /*ARGSUSED*/
  1306. dounlimit(v, t)
  1307.     Char **v;
  1308.     struct command *t;
  1309. {
  1310.     register struct limits *lp;
  1311.     int     lerr = 0;
  1312.     Char    hard = 0;
  1313.  
  1314.     v++;
  1315.     if (*v && eq(*v, STRmh)) {
  1316.     hard = 1;
  1317.     v++;
  1318.     }
  1319.     if (*v == 0) {
  1320.     for (lp = limits; lp->limconst >= 0; lp++)
  1321.         if (setlim(lp, hard, (RLIM_TYPE) RLIM_INFINITY) < 0)
  1322.         lerr++;
  1323.     if (lerr)
  1324.         stderror(ERR_SILENT);
  1325.     return;
  1326.     }
  1327.     while (*v) {
  1328.     lp = findlim(*v++);
  1329.     if (setlim(lp, hard, (RLIM_TYPE) RLIM_INFINITY) < 0)
  1330.         stderror(ERR_SILENT);
  1331.     }
  1332. }
  1333.  
  1334. static int
  1335. setlim(lp, hard, limit)
  1336.     register struct limits *lp;
  1337.     Char    hard;
  1338.     RLIM_TYPE limit;
  1339. {
  1340.     struct rlimit rlim;
  1341.  
  1342.     (void) getrlimit(lp->limconst, &rlim);
  1343.  
  1344.     if (hard)
  1345.     rlim.rlim_max = limit;
  1346.     else if (limit == RLIM_INFINITY && geteuid() != 0)
  1347.     rlim.rlim_cur = rlim.rlim_max;
  1348.     else
  1349.     rlim.rlim_cur = limit;
  1350.  
  1351.     if (setrlimit(lp->limconst, &rlim) < 0) {
  1352.     (void) fprintf(csherr, "%s: %s: Can't %s%s limit\n", bname, lp->limname,
  1353.                limit == RLIM_INFINITY ? "remove" : "set",
  1354.                hard ? " hard" : "");
  1355.     return (-1);
  1356.     }
  1357.     return (0);
  1358. }
  1359.  
  1360. void
  1361. /*ARGSUSED*/
  1362. dosuspend(v, t)
  1363.     Char **v;
  1364.     struct command *t;
  1365. {
  1366.     int     ctpgrp;
  1367.  
  1368.     void    (*old) ();
  1369.  
  1370.     if (loginsh)
  1371.     stderror(ERR_SUSPLOG);
  1372.     untty();
  1373.  
  1374.     old = signal(SIGTSTP, SIG_DFL);
  1375.     (void) kill(0, SIGTSTP);
  1376.     /* the shell stops here */
  1377.     (void) signal(SIGTSTP, old);
  1378.  
  1379.     if (tpgrp != -1) {
  1380.     ctpgrp = tcgetpgrp(FSHTTY);
  1381.     while  (ctpgrp != opgrp) {
  1382.         old = signal(SIGTTIN, SIG_DFL);
  1383.         (void) kill(0, SIGTTIN);
  1384.         (void) signal(SIGTTIN, old);
  1385.     }
  1386.     (void) setpgid(0, shpgrp);
  1387.     (void) tcsetpgrp(FSHTTY, shpgrp);
  1388.     }
  1389. }
  1390.  
  1391. /* This is the dreaded EVAL built-in.
  1392.  *   If you don't fiddle with file descriptors, and reset didfds,
  1393.  *   this command will either ignore redirection inside or outside
  1394.  *   its aguments, e.g. eval "date >x"  vs.  eval "date" >x
  1395.  *   The stuff here seems to work, but I did it by trial and error rather
  1396.  *   than really knowing what was going on.  If tpgrp is zero, we are
  1397.  *   probably a background eval, e.g. "eval date &", and we want to
  1398.  *   make sure that any processes we start stay in our pgrp.
  1399.  *   This is also the case for "time eval date" -- stay in same pgrp.
  1400.  *   Otherwise, under stty tostop, processes will stop in the wrong
  1401.  *   pgrp, with no way for the shell to get them going again.  -IAN!
  1402.  */
  1403. static Char **gv = NULL;
  1404. void
  1405. /*ARGSUSED*/
  1406. doeval(v, t)
  1407.     Char **v;
  1408.     struct command *t;
  1409. {
  1410.     Char  **oevalvec;
  1411.     Char   *oevalp;
  1412.     int     odidfds;
  1413.     jmp_buf osetexit;
  1414.     int     my_reenter;
  1415.     Char  **savegv = gv;
  1416.     int     saveIN;
  1417.     int     saveOUT;
  1418.     int     saveERR;
  1419.     int     oSHIN;
  1420.     int     oSHOUT;
  1421.     int     oSHERR;
  1422.  
  1423.     oevalvec = evalvec;
  1424.     oevalp = evalp;
  1425.     odidfds = didfds;
  1426.     oSHIN = SHIN;
  1427.     oSHOUT = SHOUT;
  1428.     oSHERR = SHERR;
  1429.  
  1430.     v++;
  1431.     if (*v == 0)
  1432.     return;
  1433.     gflag = 0, tglob(v);
  1434.     if (gflag) {
  1435.     gv = v = globall(v);
  1436.     gargv = 0;
  1437.     if (v == 0)
  1438.         stderror(ERR_NOMATCH);
  1439.     v = copyblk(v);
  1440.     }
  1441.     else {
  1442.     gv = NULL;
  1443.     v = copyblk(v);
  1444.     trim(v);
  1445.     }
  1446.  
  1447.     saveIN = dcopy(SHIN, -1);
  1448.     saveOUT = dcopy(SHOUT, -1);
  1449.     saveERR = dcopy(SHERR, -1);
  1450.  
  1451.     getexit(osetexit);
  1452.  
  1453.     if ((my_reenter = setexit()) == 0) {
  1454.     evalvec = v;
  1455.     evalp = 0;
  1456.     SHIN = dcopy(0, -1);
  1457.     SHOUT = dcopy(1, -1);
  1458.     SHERR = dcopy(2, -1);
  1459.     didfds = 0;
  1460.     process(0);
  1461.     }
  1462.  
  1463.     evalvec = oevalvec;
  1464.     evalp = oevalp;
  1465.     doneinp = 0;
  1466.     didfds = odidfds;
  1467.     (void) close(SHIN);
  1468.     (void) close(SHOUT);
  1469.     (void) close(SHERR);
  1470.     SHIN = dmove(saveIN, oSHIN);
  1471.     SHOUT = dmove(saveOUT, oSHOUT);
  1472.     SHERR = dmove(saveERR, oSHERR);
  1473.     if (gv)
  1474.     blkfree(gv), gv = NULL;
  1475.     resexit(osetexit);
  1476.     gv = savegv;
  1477.     if (my_reenter)
  1478.     stderror(ERR_SILENT);
  1479. }
  1480.  
  1481. void
  1482. /*ARGSUSED*/
  1483. doprintf(v, t)
  1484.     Char **v;
  1485.     struct command *t;
  1486. {
  1487.     char **c;
  1488.     extern int progprintf __P((int, char **));
  1489.     int ret;
  1490.  
  1491.     ret = progprintf(blklen(v), c = short2blk(v));
  1492.  
  1493.     blkfree((Char **) c);
  1494.     if (ret)
  1495.     stderror(ERR_SILENT);
  1496. }
  1497.