Annotation of 43BSDReno/bin/csh/sh.dol.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1980 Regents of the University of California.
                      3:  * All rights reserved.  The Berkeley Software License Agreement
                      4:  * specifies the terms and conditions for redistribution.
                      5:  */
                      6: 
                      7: #ifndef lint
                      8: static char *sccsid = "@(#)sh.dol.c    5.5 (Berkeley) 1/15/88";
                      9: #endif
                     10: 
                     11: #include "sh.h"
                     12: 
                     13: /*
                     14:  * C shell
                     15:  */
                     16: 
                     17: /*
                     18:  * These routines perform variable substitution and quoting via ' and ".
                     19:  * To this point these constructs have been preserved in the divided
                     20:  * input words.  Here we expand variables and turn quoting via ' and " into
                     21:  * QUOTE bits on characters (which prevent further interpretation).
                     22:  * If the `:q' modifier was applied during history expansion, then
                     23:  * some QUOTEing may have occurred already, so we dont "trim()" here.
                     24:  */
                     25: 
                     26: int    Dpeekc, Dpeekrd;                /* Peeks for DgetC and Dreadc */
                     27: char   *Dcp, **Dvp;                    /* Input vector for Dreadc */
                     28: 
                     29: #define        DEOF    -1
                     30: 
                     31: #define        unDgetC(c)      Dpeekc = c
                     32: 
                     33: #define QUOTES         (_Q|_Q1|_ESC)   /* \ ' " ` */
                     34: 
                     35: /*
                     36:  * The following variables give the information about the current
                     37:  * $ expansion, recording the current word position, the remaining
                     38:  * words within this expansion, the count of remaining words, and the
                     39:  * information about any : modifier which is being applied.
                     40:  */
                     41: char   *dolp;                  /* Remaining chars from this word */
                     42: char   **dolnxt;               /* Further words */
                     43: int    dolcnt;                 /* Count of further words */
                     44: char   dolmod;                 /* : modifier character */
                     45: int    dolmcnt;                /* :gx -> 10000, else 1 */
                     46: 
                     47: /*
                     48:  * Fix up the $ expansions and quotations in the
                     49:  * argument list to command t.
                     50:  */
                     51: Dfix(t)
                     52:        register struct command *t;
                     53: {
                     54:        register char **pp;
                     55:        register char *p;
                     56: 
                     57:        if (noexec)
                     58:                return;
                     59:        /* Note that t_dcom isn't trimmed thus !...:q's aren't lost */
                     60:        for (pp = t->t_dcom; p = *pp++;)
                     61:                while (*p)
                     62:                        if (cmap(*p++, _DOL|QUOTES)) {  /* $, \, ', ", ` */
                     63:                                Dfix2(t->t_dcom);       /* found one */
                     64:                                blkfree(t->t_dcom);
                     65:                                t->t_dcom = gargv;
                     66:                                gargv = 0;
                     67:                                return;
                     68:                        }
                     69: }
                     70: 
                     71: /*
                     72:  * $ substitute one word, for i/o redirection
                     73:  */
                     74: char *
                     75: Dfix1(cp)
                     76:        register char *cp;
                     77: {
                     78:        char *Dv[2];
                     79: 
                     80:        if (noexec)
                     81:                return (0);
                     82:        Dv[0] = cp; Dv[1] = NOSTR;
                     83:        Dfix2(Dv);
                     84:        if (gargc != 1) {
                     85:                setname(cp);
                     86:                bferr("Ambiguous");
                     87:        }
                     88:        cp = savestr(gargv[0]);
                     89:        blkfree(gargv), gargv = 0;
                     90:        return (cp);
                     91: }
                     92: 
                     93: /*
                     94:  * Subroutine to do actual fixing after state initialization.
                     95:  */
                     96: Dfix2(v)
                     97:        char **v;
                     98: {
                     99:        char *agargv[GAVSIZ];
                    100: 
                    101:        ginit(agargv);                  /* Initialize glob's area pointers */
                    102:        Dvp = v; Dcp = "";              /* Setup input vector for Dreadc */
                    103:        unDgetC(0); unDredc(0);         /* Clear out any old peeks (at error) */
                    104:        dolp = 0; dolcnt = 0;           /* Clear out residual $ expands (...) */
                    105:        while (Dword())
                    106:                continue;
                    107:        gargv = copyblk(gargv);
                    108: }
                    109: 
                    110: /*
                    111:  * Get a word.  This routine is analogous to the routine
                    112:  * word() in sh.lex.c for the main lexical input.  One difference
                    113:  * here is that we don't get a newline to terminate our expansion.
                    114:  * Rather, DgetC will return a DEOF when we hit the end-of-input.
                    115:  */
                    116: Dword()
                    117: {
                    118:        register int c, c1;
                    119:        char wbuf[BUFSIZ];
                    120:        register char *wp = wbuf;
                    121:        register int i = BUFSIZ - 4;
                    122:        register bool dolflg;
                    123:        bool sofar = 0;
                    124: 
                    125: loop:
                    126:        c = DgetC(DODOL);
                    127:        switch (c) {
                    128: 
                    129:        case DEOF:
                    130: deof:
                    131:                if (sofar == 0)
                    132:                        return (0);
                    133:                /* finish this word and catch the code above the next time */
                    134:                unDredc(c);
                    135:                /* fall into ... */
                    136: 
                    137:        case '\n':
                    138:                *wp = 0;
                    139:                goto ret;
                    140: 
                    141:        case ' ':
                    142:        case '\t':
                    143:                goto loop;
                    144: 
                    145:        case '`':
                    146:                /* We preserve ` quotations which are done yet later */
                    147:                *wp++ = c, --i;
                    148:        case '\'':
                    149:        case '"':
                    150:                /*
                    151:                 * Note that DgetC never returns a QUOTES character
                    152:                 * from an expansion, so only true input quotes will
                    153:                 * get us here or out.
                    154:                 */
                    155:                c1 = c;
                    156:                dolflg = c1 == '"' ? DODOL : 0;
                    157:                for (;;) {
                    158:                        c = DgetC(dolflg);
                    159:                        if (c == c1)
                    160:                                break;
                    161:                        if (c == '\n' || c == DEOF)
                    162:                                error("Unmatched %c", c1);
                    163:                        if ((c & (QUOTE|TRIM)) == ('\n' | QUOTE))
                    164:                                --wp, ++i;
                    165:                        if (--i <= 0)
                    166:                                goto toochars;
                    167:                        switch (c1) {
                    168: 
                    169:                        case '"':
                    170:                                /*
                    171:                                 * Leave any `s alone for later.
                    172:                                 * Other chars are all quoted, thus `...`
                    173:                                 * can tell it was within "...".
                    174:                                 */
                    175:                                *wp++ = c == '`' ? '`' : c | QUOTE;
                    176:                                break;
                    177: 
                    178:                        case '\'':
                    179:                                /* Prevent all further interpretation */
                    180:                                *wp++ = c | QUOTE;
                    181:                                break;
                    182: 
                    183:                        case '`':
                    184:                                /* Leave all text alone for later */
                    185:                                *wp++ = c;
                    186:                                break;
                    187:                        }
                    188:                }
                    189:                if (c1 == '`')
                    190:                        *wp++ = '`', --i;
                    191:                goto pack;              /* continue the word */
                    192: 
                    193:        case '\\':
                    194:                c = DgetC(0);           /* No $ subst! */
                    195:                if (c == '\n' || c == DEOF)
                    196:                        goto loop;
                    197:                c |= QUOTE;
                    198:                break;
                    199:        }
                    200:        unDgetC(c);
                    201: pack:
                    202:        sofar = 1;
                    203:        /* pack up more characters in this word */
                    204:        for (;;) {
                    205:                c = DgetC(DODOL);
                    206:                if (c == '\\') {
                    207:                        c = DgetC(0);
                    208:                        if (c == DEOF)
                    209:                                goto deof;
                    210:                        if (c == '\n')
                    211:                                c = ' ';
                    212:                        else
                    213:                                c |= QUOTE;
                    214:                }
                    215:                if (c == DEOF)
                    216:                        goto deof;
                    217:                if (cmap(c, _SP|_NL|_Q|_Q1)) {          /* sp \t\n'"` */
                    218:                        unDgetC(c);
                    219:                        if (cmap(c, QUOTES))
                    220:                                goto loop;
                    221:                        *wp++ = 0;
                    222:                        goto ret;
                    223:                }
                    224:                if (--i <= 0)
                    225: toochars:
                    226:                        error("Word too long");
                    227:                *wp++ = c;
                    228:        }
                    229: ret:
                    230:        Gcat("", wbuf);
                    231:        return (1);
                    232: }
                    233: 
                    234: /*
                    235:  * Get a character, performing $ substitution unless flag is 0.
                    236:  * Any QUOTES character which is returned from a $ expansion is
                    237:  * QUOTEd so that it will not be recognized above.
                    238:  */
                    239: DgetC(flag)
                    240:        register int flag;
                    241: {
                    242:        register int c;
                    243: 
                    244: top:
                    245:        if (c = Dpeekc) {
                    246:                Dpeekc = 0;
                    247:                return (c);
                    248:        }
                    249:        if (lap) {
                    250:                c = *lap++ & (QUOTE|TRIM);
                    251:                if (c == 0) {
                    252:                        lap = 0;
                    253:                        goto top;
                    254:                }
                    255: quotspec:
                    256:                if (cmap(c, QUOTES))
                    257:                        return (c | QUOTE);
                    258:                return (c);
                    259:        }
                    260:        if (dolp) {
                    261:                if (c = *dolp++ & (QUOTE|TRIM))
                    262:                        goto quotspec;
                    263:                if (dolcnt > 0) {
                    264:                        setDolp(*dolnxt++);
                    265:                        --dolcnt;
                    266:                        return (' ');
                    267:                }
                    268:                dolp = 0;
                    269:        }
                    270:        if (dolcnt > 0) {
                    271:                setDolp(*dolnxt++);
                    272:                --dolcnt;
                    273:                goto top;
                    274:        }
                    275:        c = Dredc();
                    276:        if (c == '$' && flag) {
                    277:                Dgetdol();
                    278:                goto top;
                    279:        }
                    280:        return (c);
                    281: }
                    282: 
                    283: char   *nulvec[] = { 0 };
                    284: struct varent nulargv = { nulvec, "argv", 0 };
                    285: 
                    286: /*
                    287:  * Handle the multitudinous $ expansion forms.
                    288:  * Ugh.
                    289:  */
                    290: Dgetdol()
                    291: {
                    292:        register char *np;
                    293:        register struct varent *vp;
                    294:        char name[20];
                    295:        int c, sc;
                    296:        int subscr = 0, lwb = 1, upb = 0;
                    297:        bool dimen = 0, bitset = 0;
                    298:        char wbuf[BUFSIZ];
                    299: 
                    300:        dolmod = dolmcnt = 0;
                    301:        c = sc = DgetC(0);
                    302:        if (c == '{')
                    303:                c = DgetC(0);           /* sc is { to take } later */
                    304:        if ((c & TRIM) == '#')
                    305:                dimen++, c = DgetC(0);          /* $# takes dimension */
                    306:        else if (c == '?')
                    307:                bitset++, c = DgetC(0);         /* $? tests existence */
                    308:        switch (c) {
                    309:        
                    310:        case '$':
                    311:                if (dimen || bitset)
                    312:                        goto syntax;            /* No $?$, $#$ */
                    313:                setDolp(doldol);
                    314:                goto eatbrac;
                    315: 
                    316:        case '<'|QUOTE:
                    317:                if (dimen || bitset)
                    318:                        goto syntax;            /* No $?<, $#< */
                    319:                for (np = wbuf; read(OLDSTD, np, 1) == 1; np++) {
                    320:                        if (np >= &wbuf[BUFSIZ-1])
                    321:                                error("$< line too long");
                    322:                        if (*np <= 0 || *np == '\n')
                    323:                                break;
                    324:                }
                    325:                *np = 0;
                    326:                /*
                    327:                 * KLUDGE: dolmod is set here because it will
                    328:                 * cause setDolp to call domod and thus to copy wbuf.
                    329:                 * Otherwise setDolp would use it directly. If we saved
                    330:                 * it ourselves, no one would know when to free it.
                    331:                 * The actual function of the 'q' causes filename
                    332:                 * expansion not to be done on the interpolated value.
                    333:                 */
                    334:                dolmod = 'q';
                    335:                dolmcnt = 10000;
                    336:                setDolp(wbuf);
                    337:                goto eatbrac;
                    338: 
                    339:        case DEOF:
                    340:        case '\n':
                    341:                goto syntax;
                    342: 
                    343:        case '*':
                    344:                (void) strcpy(name, "argv");
                    345:                vp = adrof("argv");
                    346:                subscr = -1;                    /* Prevent eating [...] */
                    347:                break;
                    348: 
                    349:        default:
                    350:                np = name;
                    351:                if (digit(c)) {
                    352:                        if (dimen)
                    353:                                goto syntax;    /* No $#1, e.g. */
                    354:                        subscr = 0;
                    355:                        do {
                    356:                                subscr = subscr * 10 + c - '0';
                    357:                                c = DgetC(0);
                    358:                        } while (digit(c));
                    359:                        unDredc(c);
                    360:                        if (subscr < 0)
                    361:                                goto oob;
                    362:                        if (subscr == 0) {
                    363:                                if (bitset) {
                    364:                                        dolp = file ? "1" : "0";
                    365:                                        goto eatbrac;
                    366:                                }
                    367:                                if (file == 0)
                    368:                                        error("No file for $0");
                    369:                                setDolp(file);
                    370:                                goto eatbrac;
                    371:                        }
                    372:                        if (bitset)
                    373:                                goto syntax;
                    374:                        vp = adrof("argv");
                    375:                        if (vp == 0) {
                    376:                                vp = &nulargv;
                    377:                                goto eatmod;
                    378:                        }
                    379:                        break;
                    380:                }
                    381:                if (!alnum(c))
                    382:                        goto syntax;
                    383:                for (;;) {
                    384:                        *np++ = c;
                    385:                        c = DgetC(0);
                    386:                        if (!alnum(c))
                    387:                                break;
                    388:                        if (np >= &name[sizeof name - 2])
                    389: syntax:
                    390:                                error("Variable syntax");
                    391:                }
                    392:                *np++ = 0;
                    393:                unDredc(c);
                    394:                vp = adrof(name);
                    395:        }
                    396:        if (bitset) {
                    397:                dolp = (vp || getenv(name)) ? "1" : "0";
                    398:                goto eatbrac;
                    399:        }
                    400:        if (vp == 0) {
                    401:                np = getenv(name);
                    402:                if (np) {
                    403:                        addla(np);
                    404:                        goto eatbrac;
                    405:                }
                    406:                udvar(name);
                    407:                /*NOTREACHED*/
                    408:        }
                    409:        c = DgetC(0);
                    410:        upb = blklen(vp->vec);
                    411:        if (dimen == 0 && subscr == 0 && c == '[') {
                    412:                np = name;
                    413:                for (;;) {
                    414:                        c = DgetC(DODOL);       /* Allow $ expand within [ ] */
                    415:                        if (c == ']')
                    416:                                break;
                    417:                        if (c == '\n' || c == DEOF)
                    418:                                goto syntax;
                    419:                        if (np >= &name[sizeof name - 2])
                    420:                                goto syntax;
                    421:                        *np++ = c;
                    422:                }
                    423:                *np = 0, np = name;
                    424:                if (dolp || dolcnt)             /* $ exp must end before ] */
                    425:                        goto syntax;
                    426:                if (!*np)
                    427:                        goto syntax;
                    428:                if (digit(*np)) {
                    429:                        register int i = 0;
                    430: 
                    431:                        while (digit(*np))
                    432:                                i = i * 10 + *np++ - '0';
                    433:                        if ((i < 0 || i > upb) && !any(*np, "-*")) {
                    434: oob:
                    435:                                setname(vp->v_name);
                    436:                                error("Subscript out of range");
                    437:                        }
                    438:                        lwb = i;
                    439:                        if (!*np)
                    440:                                upb = lwb, np = "*";
                    441:                }
                    442:                if (*np == '*')
                    443:                        np++;
                    444:                else if (*np != '-')
                    445:                        goto syntax;
                    446:                else {
                    447:                        register int i = upb;
                    448: 
                    449:                        np++;
                    450:                        if (digit(*np)) {
                    451:                                i = 0;
                    452:                                while (digit(*np))
                    453:                                        i = i * 10 + *np++ - '0';
                    454:                                if (i < 0 || i > upb)
                    455:                                        goto oob;
                    456:                        }
                    457:                        if (i < lwb)
                    458:                                upb = lwb - 1;
                    459:                        else
                    460:                                upb = i;
                    461:                }
                    462:                if (lwb == 0) {
                    463:                        if (upb != 0)
                    464:                                goto oob;
                    465:                        upb = -1;
                    466:                }
                    467:                if (*np)
                    468:                        goto syntax;
                    469:        } else {
                    470:                if (subscr > 0)
                    471:                        if (subscr > upb)
                    472:                                lwb = 1, upb = 0;
                    473:                        else
                    474:                                lwb = upb = subscr;
                    475:                unDredc(c);
                    476:        }
                    477:        if (dimen) {
                    478:                char *cp = putn(upb - lwb + 1);
                    479: 
                    480:                addla(cp);
                    481:                xfree(cp);
                    482:        } else {
                    483: eatmod:
                    484:                c = DgetC(0);
                    485:                if (c == ':') {
                    486:                        c = DgetC(0), dolmcnt = 1;
                    487:                        if (c == 'g')
                    488:                                c = DgetC(0), dolmcnt = 10000;
                    489:                        if (!any(c, "htrqxe"))
                    490:                                error("Bad : mod in $");
                    491:                        dolmod = c;
                    492:                        if (c == 'q')
                    493:                                dolmcnt = 10000;
                    494:                } else
                    495:                        unDredc(c);
                    496:                dolnxt = &vp->vec[lwb - 1];
                    497:                dolcnt = upb - lwb + 1;
                    498:        }
                    499: eatbrac:
                    500:        if (sc == '{') {
                    501:                c = Dredc();
                    502:                if (c != '}')
                    503:                        goto syntax;
                    504:        }
                    505: }
                    506: 
                    507: setDolp(cp)
                    508:        register char *cp;
                    509: {
                    510:        register char *dp;
                    511: 
                    512:        if (dolmod == 0 || dolmcnt == 0) {
                    513:                dolp = cp;
                    514:                return;
                    515:        }
                    516:        dp = domod(cp, dolmod);
                    517:        if (dp) {
                    518:                dolmcnt--;
                    519:                addla(dp);
                    520:                xfree(dp);
                    521:        } else
                    522:                addla(cp);
                    523:        dolp = "";
                    524:        if (err)
                    525:                error(err);
                    526: }
                    527: 
                    528: unDredc(c)
                    529:        int c;
                    530: {
                    531: 
                    532:        Dpeekrd = c;
                    533: }
                    534: 
                    535: Dredc()
                    536: {
                    537:        register int c;
                    538: 
                    539:        if (c = Dpeekrd) {
                    540:                Dpeekrd = 0;
                    541:                return (c);
                    542:        }
                    543:        if (Dcp && (c = *Dcp++))
                    544:                return (c&(QUOTE|TRIM));
                    545:        if (*Dvp == 0) {
                    546:                Dcp = 0;
                    547:                return (DEOF);
                    548:        }
                    549:        Dcp = *Dvp++;
                    550:        return (' ');
                    551: }
                    552: 
                    553: Dtestq(c)
                    554:        register int c;
                    555: {
                    556: 
                    557:        if (cmap(c, QUOTES))
                    558:                gflag = 1;
                    559: }
                    560: 
                    561: /*
                    562:  * Form a shell temporary file (in unit 0) from the words
                    563:  * of the shell input up to EOF or a line the same as "term".
                    564:  * Unit 0 should have been closed before this call.
                    565:  */
                    566: heredoc(term)
                    567:        char *term;
                    568: {
                    569:        register int c;
                    570:        char *Dv[2];
                    571:        char obuf[BUFSIZ], lbuf[BUFSIZ], mbuf[BUFSIZ];
                    572:        int ocnt, lcnt, mcnt;
                    573:        register char *lbp, *obp, *mbp;
                    574:        char **vp;
                    575:        bool quoted;
                    576: 
                    577:        if (creat(shtemp, 0600) < 0)
                    578:                Perror(shtemp);
                    579:        (void) close(0);
                    580:        if (open(shtemp, 2) < 0) {
                    581:                int oerrno = errno;
                    582: 
                    583:                (void) unlink(shtemp);
                    584:                errno = oerrno;
                    585:                Perror(shtemp);
                    586:        }
                    587:        (void) unlink(shtemp);                  /* 0 0 inode! */
                    588:        Dv[0] = term; Dv[1] = NOSTR; gflag = 0;
                    589:        trim(Dv); rscan(Dv, Dtestq); quoted = gflag;
                    590:        ocnt = BUFSIZ; obp = obuf;
                    591:        for (;;) {
                    592:                /*
                    593:                 * Read up a line
                    594:                 */
                    595:                lbp = lbuf; lcnt = BUFSIZ - 4;
                    596:                for (;;) {
                    597:                        c = readc(1);           /* 1 -> Want EOF returns */
                    598:                        if (c < 0 || c == '\n')
                    599:                                break;
                    600:                        if (c &= TRIM) {
                    601:                                *lbp++ = c;
                    602:                                if (--lcnt < 0) {
                    603:                                        setname("<<");
                    604:                                        error("Line overflow");
                    605:                                } 
                    606:                        }
                    607:                }
                    608:                *lbp = 0;
                    609: 
                    610:                /*
                    611:                 * Check for EOF or compare to terminator -- before expansion
                    612:                 */
                    613:                if (c < 0 || eq(lbuf, term)) {
                    614:                        (void) write(0, obuf, BUFSIZ - ocnt);
                    615:                        (void) lseek(0, (off_t)0, 0);
                    616:                        return;
                    617:                }
                    618: 
                    619:                /*
                    620:                 * If term was quoted or -n just pass it on
                    621:                 */
                    622:                if (quoted || noexec) {
                    623:                        *lbp++ = '\n'; *lbp = 0;
                    624:                        for (lbp = lbuf; c = *lbp++;) {
                    625:                                *obp++ = c;
                    626:                                if (--ocnt == 0) {
                    627:                                        (void) write(0, obuf, BUFSIZ);
                    628:                                        obp = obuf; ocnt = BUFSIZ;
                    629:                                }
                    630:                        }
                    631:                        continue;
                    632:                }
                    633: 
                    634:                /*
                    635:                 * Term wasn't quoted so variable and then command
                    636:                 * expand the input line
                    637:                 */
                    638:                Dcp = lbuf; Dvp = Dv + 1; mbp = mbuf; mcnt = BUFSIZ - 4;
                    639:                for (;;) {
                    640:                        c = DgetC(DODOL);
                    641:                        if (c == DEOF)
                    642:                                break;
                    643:                        if ((c &= TRIM) == 0)
                    644:                                continue;
                    645:                        /* \ quotes \ $ ` here */
                    646:                        if (c =='\\') {
                    647:                                c = DgetC(0);
                    648:                                if (!any(c, "$\\`"))
                    649:                                        unDgetC(c | QUOTE), c = '\\';
                    650:                                else
                    651:                                        c |= QUOTE;
                    652:                        }
                    653:                        *mbp++ = c;
                    654:                        if (--mcnt == 0) {
                    655:                                setname("<<");
                    656:                                bferr("Line overflow");
                    657:                        }
                    658:                }
                    659:                *mbp++ = 0;
                    660: 
                    661:                /*
                    662:                 * If any ` in line do command substitution
                    663:                 */
                    664:                mbp = mbuf;
                    665:                if (any('`', mbp)) {
                    666:                        /*
                    667:                         * 1 arg to dobackp causes substitution to be literal.
                    668:                         * Words are broken only at newlines so that all blanks
                    669:                         * and tabs are preserved.  Blank lines (null words)
                    670:                         * are not discarded.
                    671:                         */
                    672:                        vp = dobackp(mbuf, 1);
                    673:                } else
                    674:                        /* Setup trivial vector similar to return of dobackp */
                    675:                        Dv[0] = mbp, Dv[1] = NOSTR, vp = Dv;
                    676: 
                    677:                /*
                    678:                 * Resurrect the words from the command substitution
                    679:                 * each separated by a newline.  Note that the last
                    680:                 * newline of a command substitution will have been
                    681:                 * discarded, but we put a newline after the last word
                    682:                 * because this represents the newline after the last
                    683:                 * input line!
                    684:                 */
                    685:                for (; *vp; vp++) {
                    686:                        for (mbp = *vp; *mbp; mbp++) {
                    687:                                *obp++ = *mbp & TRIM;
                    688:                                if (--ocnt == 0) {
                    689:                                        (void) write(0, obuf, BUFSIZ);
                    690:                                        obp = obuf; ocnt = BUFSIZ;
                    691:                                }
                    692:                        }
                    693:                        *obp++ = '\n';
                    694:                        if (--ocnt == 0) {
                    695:                                (void) write(0, obuf, BUFSIZ);
                    696:                                obp = obuf; ocnt = BUFSIZ;
                    697:                        }
                    698:                }
                    699:                if (pargv)
                    700:                        blkfree(pargv), pargv = 0;
                    701:        }
                    702: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.