home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / mint / shells / tcshsrc.zoo / tcsh / sh.func.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-04-01  |  38.1 KB  |  1,817 lines

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