# 2.11BSD#431 - /usr/src/bin/tcsh/sh.func.c

##### Functions

    Setenv            X
    doalias           X
    dobreak           X
    docontin          X
    doecho            X
    doelse            X
    doend             X
    doeval            X
    doexit            X
    doforeach         X
    doglob            X
    dogoto            X
    doif              X
    dolimit           X
    dologin           X
    dologout          X
    donewgrp          X
    donohup           X
    doonintr          X
    dorepeat          X
    dosetenv          X
    dosuspend         X
    doswbrk           X
    doswitch          X
    doumask           X
    dounlimit         X
    dounsetenv        X
    dowhile           X
    dozip             X
    func              X
    isbfunc           X
    prvars            X
    search            X
    srchx             X
    unalias           X
    wfree             X

##### Macros

    RLIMIT_FSIZE      X
    RLIMIT_STACK      X
    RLIM_INFINITY     X
    toset             X

##### struct's

    limits            X

##### typedef's

    RLIM_TYPE         X

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

#### Defined functions

Setenv defined in line 1135; used 12 times

- in line 1037
- in /usr/src/bin/tcsh/sh.dir.c line 150
- in /usr/src/bin/tcsh/sh.func.c line 1037
- in /usr/src/bin/tcsh/sh.proc.c line 1738
- in /usr/src/bin/tcsh/sh.sem.c line 466
- in /usr/src/bin/tcsh/sh.set.c line 146-147(2), 157, 179, 189, 690
- in /usr/src/bin/tcsh/tc.os.c line 938

Unsetenv defined in line 1179; used 1 times

- in line 1129

doagain defined in line 545; used 4 times

- in line 463, 499, 534, 542

doalias defined in line 212; used 1 times

- in /usr/src/bin/tcsh/sh.init.c line 53

dobreak defined in line 396; used 3 times

- in line 559
- in /usr/src/bin/tcsh/sh.func.c line 559
- in /usr/src/bin/tcsh/sh.init.c line 59

docontin defined in line 537; used 1 times

- in /usr/src/bin/tcsh/sh.init.c line 67

doecho defined in line 892; used 2 times

- in /usr/src/bin/tcsh/sh.init.c line 70, 101

doelse defined in line 345; used 1 times

- in /usr/src/bin/tcsh/sh.init.c line 72

doend defined in line 528; used 1 times

- in /usr/src/bin/tcsh/sh.init.c line 73

doeval defined in line 1641; used 2 times

- in /usr/src/bin/tcsh/sh.init.c line 76
- in /usr/src/bin/tcsh/sh.sem.c line 217

doexit defined in line 405; used 1 times

- in /usr/src/bin/tcsh/sh.init.c line 78

doforeach defined in line 425; used 1 times

- in /usr/src/bin/tcsh/sh.init.c line 80

doglob defined in line 899; used 1 times

- in /usr/src/bin/tcsh/sh.init.c line 88

dogoto defined in line 351; used 1 times

- in /usr/src/bin/tcsh/sh.init.c line 89

doif defined in line 291; used 1 times

- in /usr/src/bin/tcsh/sh.init.c line 94

dolimit defined in line 1343; used 1 times

- in /usr/src/bin/tcsh/sh.init.c line 100

dologin defined in line 253; used 1 times

- in /usr/src/bin/tcsh/sh.init.c line 105

dologout defined in line 246; used 1 times

- in /usr/src/bin/tcsh/sh.init.c line 106

donewgrp defined in line 267; used 1 times

- in /usr/src/bin/tcsh/sh.init.c line 112

donohup defined in line 187; used 1 times

- in /usr/src/bin/tcsh/sh.init.c line 115

doonintr defined in line 141; used 1 times

- in /usr/src/bin/tcsh/sh.init.c line 117

dorepeat defined in line 566; used 1 times

- in /usr/src/bin/tcsh/sh.init.c line 124

dosetenv defined in line 1015; used 1 times

- in /usr/src/bin/tcsh/sh.init.c line 130

dosuspend defined in line 1586; used 1 times

- in /usr/src/bin/tcsh/sh.init.c line 144

doswbrk defined in line 605; used 1 times

- in /usr/src/bin/tcsh/sh.init.c line 60

doswitch defined in line 378; used 1 times

- in /usr/src/bin/tcsh/sh.init.c line 145

doumask defined in line 1203; used 1 times

- in /usr/src/bin/tcsh/sh.init.c line 148

dounlimit defined in line 1526; used 1 times

- in /usr/src/bin/tcsh/sh.init.c line 154

dounsetenv defined in line 1074; used 1 times

- in /usr/src/bin/tcsh/sh.init.c line 156

dowhile defined in line 466; used 1 times

- in /usr/src/bin/tcsh/sh.init.c line 168

dozip defined in line 200; used 6 times

- in line 77
- in /usr/src/bin/tcsh/sh.func.c line 77
- in /usr/src/bin/tcsh/sh.init.c line 64-68(2), 74-75(2)

findlim defined in line 1323; used 3 times

- in line 1299, 1361, 1548

func defined in line 124; used 11 times

- in /usr/src/bin/tcsh/sh.sem.c line 509
- in /usr/src/bin/tcsh/tc.bind.c line 462, 480, 689, 796, 803, 809, 816-826(3), 925

getval defined in line 1371; used 2 times

- in line 1300, 1366

getword defined in line 751; used 5 times

- in line 672, 681, 715, 733, 747

isbfunc defined in line 71; used 1 times

- in /usr/src/bin/tcsh/sh.sem.c line 190

islogin defined in line 281; used 2 times

- in line 249, 257

isrchx defined in line 635; used 1 times

- in line 668

keyword defined in line 842; used 1 times

- in line 793

limtail defined in line 1473; used 8 times

- in line 1301, 1421-1431(3), 1437, 1446, 1454-1458(2)

plim defined in line 1486; used 3 times

- in line 1302, 1358-1363(2)

preread defined in line 508; used 2 times

- in line 462, 498

prvars defined in line 206; used 2 times

- in /usr/src/bin/tcsh/sh.set.c line 78, 255

rcsid defined in line 40; never used
reexecute defined in line 331; used 2 times

- in line 322, 593

restrict_limit defined in line 1306; used 4 times

- in line 1377, 1401, 1414, 1467

search defined in line 652; used 16 times

- in line 313, 348, 365-370(2), 392, 518, 608, 864
- in /usr/src/bin/tcsh/sh.func.c line 313, 348, 365-370(2), 392, 518, 608, 864

setlim defined in line 1554; used 4 times

- in line 1303, 1367, 1541, 1549

srchx defined in line 611; used 3 times

- in line 673
- in /usr/src/bin/tcsh/sh.func.c line 673
- in /usr/src/bin/tcsh/sh.parse.c line 495

toend defined in line 860; used 2 times

- in line 400, 505

unalias defined in line 238; used 1 times

- in /usr/src/bin/tcsh/sh.init.c line 149

wfree defined in line 872; used 5 times

- in line 375, 869
- in /usr/src/bin/tcsh/sh.func.c line 375, 869
- in /usr/src/bin/tcsh/sh.lex.c line 1588

xecho defined in line 907; used 2 times

- in line 896, 903

#### Defined variables

Sgoal defined in line 649; used 2 times

- in line 663, 826

Stype defined in line 648; used 2 times

- in line 662, 810

gv defined in line 1640; used 6 times

- in line 1673, 1680, 1687, 1726-1729(3)

limits defined in line 1250; used 3 times

- in line 1330, 1357, 1540

zlast defined in line 59; used 4 times

- in line 362, 460, 493, 669

#### Defined struct's

limits defined in line 1245; used 18 times

- in line 1299(2), 1323-1329(6), 1347(2), 1373(2), 1488(2), 1530(2), 1556(2)

#### Defined typedef's

RLIM_TYPE defined in line 1225; used 17 times

- in line 1228, 1240, 1300, 1306, 1371, 1558-1348(2), 1377, 1401-1403(2), 1413-1416(2), 1467-1469(2), 1495, 1541, 1549

#### Defined macros

RLIMIT_FSIZE defined in line 1231; used 4 times

- in line 1256-1257(2), 1514, 1574

RLIMIT_STACK defined in line 1235; used 2 times

- in line 1264-1265(2)

RLIM_INFINITY defined in line 1230; used 8 times

- in line 1227, 1459, 1506, 1541, 1549, 1567, 1574-1579(2)

toset defined in line 1237; used 1 times

- in line 1576

Last modified: 1991-08-21 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 3914 |