Annotation of coherent/a/usr/bob/korn/eval.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Expansion - quoting, separation, substitution, globbing
        !             3:  */
        !             4: 
        !             5: static char *RCSid = "$Header: /newbits/usr/bin/korn/RCS/eval.c,v 1.2 91/08/01 12:39:55 bin Exp Locker: bin $";
        !             6: 
        !             7: #include <stddef.h>
        !             8: #include <stdio.h>
        !             9: #include <string.h>
        !            10: #include <errno.h>
        !            11: #include <setjmp.h>
        !            12: #include <unistd.h>
        !            13: #include <sys/types.h>
        !            14: #include <dirent.h>
        !            15: #include <pwd.h>
        !            16: #include "sh.h"
        !            17: #include "lex.h"
        !            18: #include "tree.h"
        !            19: #include "table.h"
        !            20: #include "expand.h"
        !            21: 
        !            22: #if COHERENT
        !            23: struct dirent  *readdir();             /* missing from headers */
        !            24: DIR    *opendir();
        !            25: #endif
        !            26: 
        !            27: /*
        !            28:  * string expansion
        !            29:  *
        !            30:  * first pass: quoting, IFS separation, ${} and $() substitution.
        !            31:  * second pass: filename expansion (*?[]~).
        !            32:  */
        !            33: 
        !            34: /* expansion generator state */
        !            35: typedef struct Expand {
        !            36:        /* int  type; */        /* see expand() */
        !            37:        char   *str;            /* string */
        !            38:        union {
        !            39:                char  **strv;   /* string[] */
        !            40:                FILE   *file;   /* file */
        !            41:        } u;                    /* source */
        !            42:        short   split;          /* split "$@"*/
        !            43: } Expand;
        !            44: 
        !            45: #define        XBASE   0               /* scanning original */
        !            46: #define        XSUB    1               /* expanding ${} string */
        !            47: #define        XARGSEP 2               /* ifs0 between "$@" */
        !            48: #define        XARG    3               /* expanding $*, $@ */
        !            49: #define        XCOM    4               /* expanding $() */
        !            50: 
        !            51: static void    expand ARGS((char *, XPtrV *, int));
        !            52: static int     comsub ARGS((Expand *, char *comm));
        !            53: static int     varsub ARGS((Expand *, char *name, int stype));
        !            54: static void    glob ARGS((char *cp, XPtrV *wp));
        !            55: static void    globit ARGS((char *ds, char *dp, char *sp, XPtrV *wp, int check));
        !            56: static char   *tilde ARGS((char *wp));
        !            57: static char   *trimsub ARGS((char *str, char *pat, int how));
        !            58: 
        !            59: int    ifs0 = ' ';             /* todo: first char of $IFS */
        !            60: 
        !            61: /* compile and expand word */
        !            62: char *
        !            63: substitute(cp, f)
        !            64:        char Const *cp;
        !            65:        int f;
        !            66: {
        !            67:        struct source *s, *sold;
        !            68: 
        !            69:        sold = source;
        !            70:        s = pushs(SWSTR);
        !            71:        s->str = (char *) cp;
        !            72:        source = s;
        !            73:        if (yylex(ONEWORD) != LWORD)
        !            74:                errorf("eval:substitute error\n");
        !            75:        source = sold;
        !            76:        return evalstr(yylval.cp, f);
        !            77: }
        !            78: 
        !            79: /*
        !            80:  * expand arg-list
        !            81:  */
        !            82: char **
        !            83: eval(ap, f)
        !            84:        register char **ap;
        !            85: {
        !            86:        XPtrV w;
        !            87: 
        !            88:        if (*ap == NULL)
        !            89:                return ap;
        !            90:        XPinit(w, 32);
        !            91:        XPput(w, NULL);         /* space for shell name */
        !            92:        while (*ap != NULL)
        !            93:                expand(*ap++, &w, f);
        !            94:        XPput(w, NULL);
        !            95:        return (char **) XPclose(w) + 1;
        !            96: }
        !            97: 
        !            98: /*
        !            99:  * expand string
        !           100:  */
        !           101: char *
        !           102: evalstr(cp, f)
        !           103:        register char *cp;
        !           104:        int f;
        !           105: {
        !           106:        XPtrV w;
        !           107: 
        !           108:        XPinit(w, 1);
        !           109:        expand(cp, &w, f);
        !           110:        cp = (XPsize(w) == 0) ? "" : (char*) *XPptrv(w);
        !           111:        XPfree(w);
        !           112:        return cp;
        !           113: }
        !           114: 
        !           115: /* for nested substitution: ${var:=$var2} */
        !           116: typedef struct SubType {
        !           117:        short   type;           /* [=+-?%#] action after expanded word */
        !           118:        short   base;           /* begin position of expanded word */
        !           119:        char   *name;           /* name for ${var=word} */
        !           120: } SubType;
        !           121: 
        !           122: #if 1
        !           123: mypr(cp)
        !           124: char   *cp;
        !           125: {
        !           126:        fprintf(stderr, "%r", &cp);
        !           127: }
        !           128: #endif
        !           129: 
        !           130: static void
        !           131: expand(cp, wp, f)
        !           132:        char *cp;               /* input word */
        !           133:        register XPtrV *wp;     /* output words */
        !           134:        int f;                  /* DO* flags */
        !           135: {
        !           136:        register int c;
        !           137:        register int type = XBASE; /* expansion type */
        !           138:        register int quote = 0; /* quoted */
        !           139:        XString ds;             /* destination string */
        !           140:        register char *dp, *sp; /* dest., source */
        !           141:        int fdo, word, combase; /* second pass flags; have word */
        !           142:        Expand x;               /* expansion variables */
        !           143:        SubType subtype [10];   /* substitution type stack */
        !           144:        register SubType *st = subtype + 10;
        !           145: 
        !           146:        if (cp == NULL)
        !           147:                errorf("eval:expand(NULL)\n");
        !           148:        if (flag[FNOGLOB]) {
        !           149:                f &= ~ DOGLOB;
        !           150:        }
        !           151:        Xinit(ds, dp, 128);     /* init dest. string */
        !           152:        type = XBASE;
        !           153:        sp = cp;
        !           154:        fdo = 0;
        !           155:        word = !(f&DOBLANK);
        !           156: 
        !           157:        while (1) {
        !           158:                Xcheck(ds, dp);
        !           159: 
        !           160:                switch (type) {
        !           161:                  case XBASE:   /* original prefixed string */
        !           162:                        c = *sp++;
        !           163:                        switch (c) {
        !           164:                          case EOS:
        !           165:                                c = 0;
        !           166:                                break;
        !           167:                          case CHAR:
        !           168:                                c = *sp++;
        !           169:                                break;
        !           170:                          case QCHAR:
        !           171:                                quote |= 2; /* temporary quote */
        !           172:                                c = *sp++;
        !           173:                                break;
        !           174:                          case OQUOTE:
        !           175:                                word = quote = 1;
        !           176:                                continue;
        !           177:                          case CQUOTE:
        !           178:                                quote = 0;
        !           179:                                continue;
        !           180:                          case COMSUB:
        !           181:                                type = comsub(&x, sp);
        !           182:                                sp = strchr(sp, 0) + 1;
        !           183:                                combase = Xsavepos(ds, dp);
        !           184:                                continue;
        !           185:                          case OSUBST: /* ${var{:}[=+-?]word} */
        !           186:                                cp = sp;                /* variable */
        !           187:                                sp = strchr(sp, 0) + 1; /* skip variable */
        !           188:                                c = (*sp == CSUBST) ? 0 : *sp++;
        !           189:                                if ((c&0x7F) == '#' || (c&0x7F) == '%')
        !           190:                                        f |= DOPAT;
        !           191:                                type = varsub(&x, cp, c);
        !           192:                                if (type == XBASE) {    /* expand? */
        !           193:                                        if (st == subtype)
        !           194:                                                errorf("ridiculous ${} nesting\n");
        !           195:                                        --st;
        !           196:                                        st->type = c;
        !           197:                                        st->base = Xsavepos(ds, dp);
        !           198:                                        st->name = cp;
        !           199:                                } else
        !           200:                                        /* todo: nested OSUBST/CSUBST */
        !           201:                                        sp = wdscan(sp, CSUBST); /* skip word */
        !           202:                                continue;
        !           203:                          case CSUBST: /* only get here if expanding word */
        !           204:                                *dp = 0;
        !           205:                                if (f&DOGLOB)
        !           206:                                        f &= ~DOPAT;
        !           207:                                switch (st->type&0x7F) {
        !           208:                                  case '#':
        !           209:                                  case '%':
        !           210:                                        *dp = 0;
        !           211:                                        dp = Xrestpos(ds, dp, st->base);
        !           212:                                        x.str = trimsub(x.str, dp, st->type);
        !           213:                                        type = XSUB;
        !           214:                                        continue;
        !           215:                                  case '=':
        !           216: #if 0
        !           217:                                        if ((x.u.vp->flag&RDONLY))
        !           218:                                                errorf("cannot set readonly %s\n", cp);
        !           219: #endif
        !           220:                                        setstr(global(st->name), Xrestpos(ds, dp, st->base));
        !           221:                                        break;
        !           222:                                  case '?':
        !           223:                                        if (dp == Xrestpos(ds, dp, st->base))
        !           224:                                                errorf("missing value for %s\n", cp);
        !           225:                                        else
        !           226:                                                errorf("%s\n", Xrestpos(ds, dp, st->base));
        !           227:                                }
        !           228:                                st++;
        !           229:                                type = XBASE;
        !           230:                                continue;
        !           231:                        }
        !           232:                        break;
        !           233: 
        !           234:                  case XSUB:
        !           235:                        if ((c = *x.str++) == 0) {
        !           236:                                type = XBASE;
        !           237:                                continue;
        !           238:                        }
        !           239:                        break;
        !           240: 
        !           241:                  case XARGSEP:
        !           242:                        type = XARG;
        !           243:                        quote = 1;
        !           244:                  case XARG:
        !           245:                        if ((c = *x.str++) == 0) {
        !           246:                                if ((x.str = *x.u.strv++) == NULL) {
        !           247:                                        type = XBASE;
        !           248:                                        continue;
        !           249:                                } else if (quote && x.split) {
        !           250:                                        /* terminate word for "$@" */
        !           251:                                        type = XARGSEP;
        !           252:                                        quote = 0;
        !           253:                                }
        !           254:                                c = ifs0;
        !           255:                        }
        !           256:                        break;
        !           257: 
        !           258:                  case XCOM:
        !           259:                        c = getc(x.u.file);
        !           260:                        if (quote) {
        !           261:                                if (c == EOF) {
        !           262:                                        cp = Xrestpos(ds, sp, combase);
        !           263:                                        for (dp--; dp >= cp && *dp == '\n'; dp--)
        !           264:                                                ;
        !           265:                                        dp++;
        !           266:                                        fclose(x.u.file);
        !           267:                                        if (x.split)
        !           268:                                                waitlast();
        !           269:                                        type = XBASE;
        !           270:                                        continue;
        !           271:                                }
        !           272:                        } else {        /* this part is probably redundant */
        !           273:                                if (c == EOF || c == '\n') {
        !           274:                                        while ((c = getc(x.u.file)) == '\n')
        !           275:                                                ;
        !           276:                                        if (c == EOF) {
        !           277:                                                fclose(x.u.file);
        !           278:                                                if (x.split)
        !           279:                                                        waitlast();
        !           280:                                                type = XBASE;
        !           281:                                                continue;
        !           282:                                        }
        !           283:                                        ungetc(c, x.u.file);
        !           284:                                        c = ifs0;
        !           285:                                }
        !           286:                        }
        !           287:                        break;
        !           288:                }
        !           289: 
        !           290:                /* check for end of word or IFS separation */
        !           291:                if (c == 0 || !quote && (f&DOBLANK) && ctype(c, C_IFS)) {
        !           292:                        if (word) {
        !           293:                                *dp++ = 0;
        !           294:                                cp = Xclose(ds, dp);
        !           295:                                if (fdo&DOTILDE)
        !           296:                                        cp = tilde(cp);
        !           297:                                if (fdo&DOGLOB)
        !           298:                                        glob(cp, wp);
        !           299:                                else
        !           300:                                        {XPput(*wp, cp);}
        !           301:                                fdo = word = 0;
        !           302:                                if (c != 0)
        !           303:                                        Xinit(ds, dp, 128);
        !           304:                        } else
        !           305:                                ; /* ignore IFS */
        !           306:                        if (c == 0)
        !           307:                                return;
        !           308:                } else {
        !           309:                        /* mark any special second pass chars */
        !           310:                        if (!quote)
        !           311:                                switch (c) {
        !           312:                                  case '*':
        !           313:                                  case '?':
        !           314:                                  case '[':
        !           315:                                        if (f&(DOPAT|DOGLOB)) {
        !           316:                                                fdo |= (f&DOGLOB);
        !           317:                                                *dp++ = MAGIC;
        !           318:                                        }
        !           319:                                        break;
        !           320:                                  case '~':
        !           321:                                        if ((f&DOTILDE) && dp == Xstring(ds, dp) ||
        !           322:                                            !(f&DOBLANK) && 
        !           323:                                            (dp[-1] == '=' || dp[-1] == ':')) {
        !           324:                                                fdo |= DOTILDE;
        !           325:                                                *dp++ = MAGIC;
        !           326:                                        }
        !           327:                                        break;
        !           328:                                }
        !           329:                        else
        !           330:                                quote &= ~2; /* undo temporary */
        !           331: 
        !           332:                        word = 1;
        !           333:                        *dp++ = c; /* save output char */
        !           334:                }
        !           335:        }
        !           336: }
        !           337: 
        !           338: /*
        !           339:  * Prepare to generate the string returned by ${} substitution.
        !           340:  */
        !           341: static int
        !           342: varsub(xp, sp, stype)
        !           343:        register Expand *xp;
        !           344:        register char *sp;
        !           345:        int stype;
        !           346: {
        !           347:        register int c;
        !           348:        int type;
        !           349: 
        !           350:        /* ${#var}, string length or argc */
        !           351:        if (sp[0] == '#' && (c = sp[1]) != 0) {
        !           352:                c = (c == '*' || c == '@') ? e.loc->argc :
        !           353:                        strlen(strval(global(sp+1)));
        !           354:                xp->str = strsave(ulton((unsigned long)c, 10), ATEMP);
        !           355:                return XSUB;
        !           356:        }
        !           357: 
        !           358:        c = sp[0];
        !           359:        if (c == '*' || c == '@') {
        !           360:                if (e.loc->argc == 0) {
        !           361:                        xp->str = null;
        !           362:                        type = XSUB;
        !           363:                } else {
        !           364:                        xp->u.strv = e.loc->argv + 1;
        !           365:                        xp->str = *xp->u.strv++;
        !           366:                        xp->split = c == '@'; /* $@ */
        !           367:                        type = XARG;
        !           368:                }
        !           369:        } else {
        !           370:                xp->str = strval(global(sp));
        !           371:                type = XSUB;
        !           372:        }
        !           373: 
        !           374:        c = stype&0x7F;
        !           375:        /* test the compiler's code generator */
        !           376:        if (c == '%' || c == '#' ||
        !           377:            (((stype&0x80) ? *xp->str=='\0' : xp->str==null) ? /* undef? */
        !           378:             c == '=' || c == '-' || c == '?' : c == '+'))
        !           379:                type = XBASE;   /* expand word instead of variable value */
        !           380:        if (type != XBASE && flag[FNOUNSET] && xp->str == null)
        !           381:                errorf("%s: unset variable\n", sp);
        !           382:        return type;
        !           383: }
        !           384: 
        !           385: /*
        !           386:  * Run the command in $(...) and read its output.
        !           387:  */
        !           388: static int
        !           389: comsub(xp, cp)
        !           390:        register Expand *xp;
        !           391:        char *cp;
        !           392: {
        !           393:        Source *s;
        !           394:        register struct op *t;
        !           395:        FILE *fi;
        !           396: 
        !           397:        s = pushs(SSTRING);
        !           398:        s->str = cp;
        !           399:        t = compile(s);
        !           400: 
        !           401:        if (t != NULL && t->type == TCOM && /* $(<file) */
        !           402:            *t->args == NULL && *t->vars == NULL && t->ioact != NULL) {
        !           403:                register struct ioword *io = *t->ioact;
        !           404: 
        !           405:                if (io->flag != IOREAD)
        !           406:                        errorf("funny $() command\n");
        !           407:                fi = fopen(evalstr(io->name, DOTILDE), "r");
        !           408:                if (fi != NULL)
        !           409:                        fileno(fi) = savefd(fileno(fi));
        !           410:                xp->split = 0;  /* no waitlast() */
        !           411:        } else {
        !           412:                int ofd1, pv[2];
        !           413: 
        !           414:                openpipe(pv);
        !           415:                fi = fdopen(pv[0], "r");
        !           416:                ofd1 = savefd(1);
        !           417:                dup2(pv[1], 1);
        !           418:                close(pv[1]);
        !           419: #if 0
        !           420:                exchild(t, XXCOM|XPIPEO);
        !           421: #else
        !           422:                execute(t, XFORK|XXCOM|XPIPEO);
        !           423: #endif
        !           424:                dup2(ofd1, 1);
        !           425: #if COHERENT
        !           426:                close(ofd1);
        !           427: #endif
        !           428:                xp->split = 1;  /* waitlast() */
        !           429:        }       
        !           430: 
        !           431:        if (fi == NULL)
        !           432:                errorf("cannot open $() input\n");
        !           433:        setvbuf(fi, (char *)NULL, _IOFBF, BUFSIZ);
        !           434:        xp->u.file = fi;
        !           435:        return XCOM;
        !           436: }
        !           437: 
        !           438: /*
        !           439:  * perform #pattern and %pattern substitution in ${}
        !           440:  */
        !           441: 
        !           442: static char *
        !           443: trimsub(str, pat, how)
        !           444:        register char *str;
        !           445:        char *pat;
        !           446:        int how;
        !           447: {
        !           448:        register char *end = strchr(str, 0);
        !           449:        register char *p, c;
        !           450: 
        !           451:        switch (how) {
        !           452:          case '#':             /* shortest at begin */
        !           453:                for (p = str; p <= end; p++) {
        !           454:                        c = *p; *p = '\0';
        !           455:                        if (gmatch(str, pat)) {
        !           456:                                *p = c;
        !           457:                                return p;
        !           458:                        }
        !           459:                        *p = c;
        !           460:                }
        !           461:                break;
        !           462:        case '#'|0x80:          /* longest match at begin */
        !           463:                for (p = end; p >= str; p--) {
        !           464:                        c = *p; *p = '\0';
        !           465:                        if (gmatch(str, pat)) {
        !           466:                                *p = c;
        !           467:                                return p;
        !           468:                        }
        !           469:                        *p = c;
        !           470:                }
        !           471:                break;
        !           472:          case '%':             /* shortest match at end */
        !           473:                for (p = end; p >= str; p--) {
        !           474:                        if (gmatch(p, pat)) {
        !           475:                                *p = '\0';
        !           476:                                return str;
        !           477:                        }
        !           478:                }
        !           479:                break;
        !           480:          case '%'|0x80:        /* longest match at end */
        !           481:                for (p = str; p <= end; p++) {
        !           482:                        if (gmatch(p, pat)) {
        !           483:                                *p = '\0';
        !           484:                                return str;
        !           485:                        }
        !           486:                }
        !           487:                break;
        !           488:        }
        !           489: 
        !           490:        return str;             /* no match, return string */
        !           491: }
        !           492: 
        !           493: /*
        !           494:  * glob
        !           495:  * Name derived from V6's /etc/glob, the program that expanded filenames.
        !           496:  */
        !           497: 
        !           498: static char   *debunk();
        !           499: 
        !           500: static void 
        !           501: glob(cp, wp)
        !           502:        char *cp;
        !           503:        register XPtrV *wp;
        !           504: {
        !           505:        char path [PATH];
        !           506:        register char *sp = cp;
        !           507:        int oldsize;
        !           508: 
        !           509:        oldsize = XPsize(*wp);
        !           510:        globit(path, path, sp, wp, 0);
        !           511: 
        !           512:        if (XPsize(*wp) == oldsize)
        !           513:                {XPput(*wp, debunk(cp));}
        !           514:        else
        !           515:                qsortp(XPptrv(*wp) + oldsize, (size_t)(XPsize(*wp) - oldsize), xstrcmp);
        !           516: }
        !           517: 
        !           518: static void
        !           519: globit(ds, dp, sp, wp, check)
        !           520:        char *ds;               /* dest path */
        !           521:        char *dp;               /* dest end */
        !           522:        char *sp;               /* source path */
        !           523:        register XPtrV *wp;     /* output list */
        !           524:        int check;              /* check dest existence */
        !           525: {
        !           526:        register char *np;      /* next source component */
        !           527:        register char *tsp, *tdp;
        !           528: 
        !           529:        if (sp == NULL) {       /* end of source path */
        !           530:                if (check && access(ds, 0) < 0)
        !           531:                        return;
        !           532:                XPput(*wp, strsave(ds, ATEMP));
        !           533:                return;
        !           534:        }
        !           535: 
        !           536:        if (dp > ds)
        !           537:                *dp++ = '/';
        !           538:        while (*sp == '/')
        !           539:                *dp++ = *sp++;
        !           540:        np = strchr(sp, '/');
        !           541:        if (np != NULL)
        !           542:                *np++ = 0;
        !           543: 
        !           544:        *dp = 0;
        !           545:        if (strchr(sp, MAGIC) == NULL) { /* contains no pattern? */
        !           546:                tdp = dp; tsp = sp;
        !           547:                while ((*tdp++ = *tsp++) != 0)
        !           548:                        ;
        !           549:                --tdp;
        !           550:                globit(ds, tdp, np, wp, check);
        !           551:        } else {
        !           552:                DIR *dirp;
        !           553:                struct dirent *d;
        !           554: 
        !           555:                dirp = opendir(ds);
        !           556:                if (dirp == NULL)
        !           557:                        goto Nodir;
        !           558:                while ((d = readdir(dirp)) != NULL) {
        !           559:                        tsp = d->d_name;
        !           560:                        if (tsp[0] == '.' &&
        !           561:                            (tsp[1] == 0 || tsp[1] == '.' && tsp[2] == 0))
        !           562:                                continue; /* always ignore . and .. */
        !           563:                        if (*tsp == '.' && *sp != '.' || !gmatch(tsp, sp))
        !           564:                                continue;
        !           565: 
        !           566:                        tdp = dp;
        !           567:                        while ((*tdp++ = *tsp++) != 0)
        !           568:                                ;
        !           569:                        --tdp;
        !           570:                        globit(ds, tdp, np, wp, np != NULL);
        !           571:                }
        !           572:                closedir(dirp);
        !           573:          Nodir:;
        !           574:        }
        !           575: 
        !           576:        if (np != NULL)
        !           577:                *--np = '/';
        !           578: }
        !           579: 
        !           580: /* remove MAGIC from string */
        !           581: static char *
        !           582: debunk(cp)
        !           583:        char *cp;
        !           584: {
        !           585:        register unsigned char *dp, *sp;
        !           586: 
        !           587:        for (dp = sp = cp; *sp != 0; sp++)
        !           588:                if (*sp != MAGIC)
        !           589:                        *dp++ = *sp;
        !           590:        *dp = 0;
        !           591:        return cp;
        !           592: }
        !           593: 
        !           594: /*
        !           595:  * tilde expansion
        !           596:  *
        !           597:  * based on a version by Arnold Robbins
        !           598:  */
        !           599: 
        !           600: static char *homedir();
        !           601: 
        !           602: static char *
        !           603: tilde(acp)
        !           604:        char *acp;
        !           605: {
        !           606:        register unsigned int c;
        !           607:        char path[PATH+1];
        !           608:        register unsigned char *cp = acp, *wp = path, *dp;
        !           609:        char userid[16+1];
        !           610: 
        !           611:   Again:
        !           612:        while (1) {
        !           613:                if ((c = *cp++) == 0) {
        !           614:                        *wp = 0;
        !           615:                        afree((Void*)acp, ATEMP);
        !           616:                        return strsave(path, ATEMP);
        !           617:                } else if (c == MAGIC && *cp == '~')
        !           618:                        break;
        !           619:                else
        !           620:                        *wp++ = c;
        !           621:        }
        !           622: 
        !           623:        dp = NULL;      /* no output substitution */
        !           624:        if (cp[1] == 0 || cp[1] == '/' || cp[1] == ':') /* ~ or ~/ */
        !           625:                dp = strval(global("HOME")), cp += 1;
        !           626:        else if (cp[1] == '+' && (cp[2] == '/' || cp[2] == ':' || cp[2] == 0))
        !           627:                dp = strval(global("PWD")), cp += 2;
        !           628:        else if (cp[1] == '-' && (cp[2] == '/' || cp[2] == ':' || cp[2] == 0))
        !           629:                dp = strval(global("OLDPWD")), cp += 2;
        !           630:        else if (letter(cp[1])) {
        !           631:                char *save = cp;
        !           632:                for (dp = userid, cp++; letnum(*cp) && dp < userid+16; )
        !           633:                        *dp++ = *cp++;
        !           634:                *dp = 0;
        !           635:                dp = homedir(userid);
        !           636:                if (dp == NULL)
        !           637:                        cp = save;
        !           638:        }
        !           639:        /* substitute */
        !           640:        if (dp != NULL)
        !           641:                while (*dp != 0)
        !           642:                        *wp++ = *dp++;
        !           643:        goto Again;
        !           644: }
        !           645: 
        !           646: /*
        !           647:  * map userid to user's home directory.
        !           648:  * todo: implement a cache with the "homedirs" table.
        !           649:  * note that 4.3's getpw adds more than 6K to the shell,
        !           650:  * and the YP version probably adds much more.
        !           651:  * we might consider our own version of getpwnam() to keep the size down.
        !           652:  */
        !           653: 
        !           654: static char *
        !           655: homedir(name)
        !           656:        char *name;
        !           657: {
        !           658:        register struct tbl *ap;
        !           659:        register struct passwd *pw;
        !           660: 
        !           661:        ap = tsearch(&homedirs, name, hash(name));
        !           662:        if ((ap != NULL && (ap->flag&ISSET)))
        !           663:                return ap->val.s;
        !           664:        pw = getpwnam(name);
        !           665:        if (pw == NULL)
        !           666:                return NULL;
        !           667:        return pw->pw_dir;
        !           668: }
        !           669: 

unix.superglobalmegacorp.com

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