# 2.11BSD#431 - /usr/src/ucb/rdist/expand.c

##### Functions

    Cat               X
    addpath           X
    amatch            X
    execbrc           X
    expand            X
    expsh             X
    expstr            X
    exptilde          X
    match             X
    matchdir          X
    smatch            X

##### Variables

    eargc             X
    eargv             X
    entp              X
    expany            X
    lastpathp         X
    nleft             X
    path              X
    pathp             X
    sortbase          X
    tilde             X
    tpathp            X
    which             X

##### Macros

    GAVSIZ            X
    LC                X
    RC                X
    sort              X

       1: /*
       2:  * Copyright (c) 1983 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: #if !defined(lint) && defined(DOSCCS)
       8: static char sccsid[] = "@(#)expand.c	5.2.1 (2.11BSD) 1995/05/09";
       9: #endif
      10:
      11: #include "defs.h"
      12:
      13: #define GAVSIZ  NCARGS / 6
      14: #define LC '{'
      15: #define RC '}'
      16:
      17: static char *shchars = "${[*?";
      18:
      19: int which;      /* bit mask of types to expand */
      20: int eargc;      /* expanded arg count */
      21: char    **eargv;    /* expanded arg vectors */
      22: char    *path;
      23: char    *pathp;
      24: char    *lastpathp;
      25: char    *tilde;     /* "~user" if not expanding tilde, else "" */
      26: char    *tpathp;
      27: int nleft;
      28:
      29: int expany;     /* any expansions done? */
      30: char    *entp;
      31: char    **sortbase;
      32:
      33: char    *index();
      34: int argcmp();
      35:
      36: #define sort()  qsort((char *)sortbase, &eargv[eargc] - sortbase, \
      37:               sizeof(*sortbase), argcmp), sortbase = &eargv[eargc]
      38:
      39: /*
      40:  * Take a list of names and expand any macros, etc.
      41:  * wh = E_VARS if expanding variables.
      42:  * wh = E_SHELL if expanding shell characters.
      43:  * wh = E_TILDE if expanding `~'.
      44:  * or any of these or'ed together.
      45:  *
      46:  * Major portions of this were snarfed from csh/sh.glob.c.
      47:  */
      48: struct namelist *
      49: expand(list, wh)
      50:     struct namelist *list;
      51:     int wh;
      52: {
      53:     register struct namelist *nl, *prev;
      54:     register int n;
      55:     char pathbuf[BUFSIZ];
      56:     char *argvbuf[GAVSIZ];
      57:
      58:     if (debug) {
      59:         printf("expand(%x, %d)\nlist = ", list, wh);
      60:         prnames(list);
      61:     }
      62:
      63:     if (wh == 0) {
      64:         register char *cp;
      65:
      66:         for (nl = list; nl != NULL; nl = nl->n_next)
      67:             for (cp = nl->n_name; *cp; cp++)
      68:                 *cp = *cp & TRIM;
      69:         return(list);
      70:     }
      71:
      72:     which = wh;
      73:     path = tpathp = pathp = pathbuf;
      74:     *pathp = '\0';
      75:     lastpathp = &path[sizeof pathbuf - 2];
      76:     tilde = "";
      77:     eargc = 0;
      78:     eargv = sortbase = argvbuf;
      79:     *eargv = 0;
      80:     nleft = NCARGS - 4;
      81:     /*
      82: 	 * Walk the name list and expand names into eargv[];
      83: 	 */
      84:     for (nl = list; nl != NULL; nl = nl->n_next)
      85:         expstr(nl->n_name);
      86:     /*
      87: 	 * Take expanded list of names from eargv[] and build a new list.
      88: 	 */
      89:     list = prev = NULL;
      90:     for (n = 0; n < eargc; n++) {
      91:         nl = makenl(NULL);
      92:         nl->n_name = eargv[n];
      93:         if (prev == NULL)
      94:             list = prev = nl;
      95:         else {
      96:             prev->n_next = nl;
      97:             prev = nl;
      98:         }
      99:     }
     100:     if (debug) {
     101:         printf("expanded list = ");
     102:         prnames(list);
     103:     }
     104:     return(list);
     105: }
     106:
     107: expstr(s)
     108:     char *s;
     109: {
     110:     register char *cp, *cp1;
     111:     register struct namelist *tp;
     112:     char *tail;
     113:     char buf[BUFSIZ];
     114:     int savec, oeargc;
     115:     extern char homedir[];
     116:
     117:     if (s == NULL || *s == '\0')
     118:         return;
     119:
     120:     if ((which & E_VARS) && (cp = index(s, '$')) != NULL) {
     121:         *cp++ = '\0';
     122:         if (*cp == '\0') {
     123:             yyerror("no variable name after '$'");
     124:             return;
     125:         }
     126:         if (*cp == LC) {
     127:             cp++;
     128:             if ((tail = index(cp, RC)) == NULL) {
     129:                 yyerror("unmatched '{'");
     130:                 return;
     131:             }
     132:             *tail++ = savec = '\0';
     133:             if (*cp == '\0') {
     134:                 yyerror("no variable name after '$'");
     135:                 return;
     136:             }
     137:         } else {
     138:             tail = cp + 1;
     139:             savec = *tail;
     140:             *tail = '\0';
     141:         }
     142:         tp = lookup(cp, NULL, 0);
     143:         if (savec != '\0')
     144:             *tail = savec;
     145:         if (tp != NULL) {
     146:             for (; tp != NULL; tp = tp->n_next) {
     147:                 sprintf(buf, "%s%s%s", s, tp->n_name, tail);
     148:                 expstr(buf);
     149:             }
     150:             return;
     151:         }
     152:         sprintf(buf, "%s%s", s, tail);
     153:         expstr(buf);
     154:         return;
     155:     }
     156:     if ((which & ~E_VARS) == 0 || !strcmp(s, "{") || !strcmp(s, "{}")) {
     157:         Cat(s, "");
     158:         sort();
     159:         return;
     160:     }
     161:     if (*s == '~') {
     162:         cp = ++s;
     163:         if (*cp == '\0' || *cp == '/') {
     164:             tilde = "~";
     165:             cp1 = homedir;
     166:         } else {
     167:             tilde = cp1 = buf;
     168:             *cp1++ = '~';
     169:             do
     170:                 *cp1++ = *cp++;
     171:             while (*cp && *cp != '/');
     172:             *cp1 = '\0';
     173:             if (pw == NULL || strcmp(pw->pw_name, buf+1) != 0) {
     174:                 if ((pw = getpwnam(buf+1)) == NULL) {
     175:                     strcat(buf, ": unknown user name");
     176:                     yyerror(buf+1);
     177:                     return;
     178:                 }
     179:             }
     180:             cp1 = pw->pw_dir;
     181:             s = cp;
     182:         }
     183:         for (cp = path; *cp++ = *cp1++; )
     184:             ;
     185:         tpathp = pathp = cp - 1;
     186:     } else {
     187:         tpathp = pathp = path;
     188:         tilde = "";
     189:     }
     190:     *pathp = '\0';
     191:     if (!(which & E_SHELL)) {
     192:         if (which & E_TILDE)
     193:             Cat(path, s);
     194:         else
     195:             Cat(tilde, s);
     196:         sort();
     197:         return;
     198:     }
     199:     oeargc = eargc;
     200:     expany = 0;
     201:     expsh(s);
     202:     if (eargc == oeargc)
     203:         Cat(s, "");     /* "nonomatch" is set */
     204:     sort();
     205: }
     206:
     207: static
     208: argcmp(a1, a2)
     209:     char **a1, **a2;
     210: {
     211:
     212:     return (strcmp(*a1, *a2));
     213: }
     214:
     215: /*
     216:  * If there are any Shell meta characters in the name,
     217:  * expand into a list, after searching directory
     218:  */
     219: expsh(s)
     220:     char *s;
     221: {
     222:     register char *cp;
     223:     register char *spathp, *oldcp;
     224:     struct stat stb;
     225:
     226:     spathp = pathp;
     227:     cp = s;
     228:     while (!any(*cp, shchars)) {
     229:         if (*cp == '\0') {
     230:             if (!expany || stat(path, &stb) >= 0) {
     231:                 if (which & E_TILDE)
     232:                     Cat(path, "");
     233:                 else
     234:                     Cat(tilde, tpathp);
     235:             }
     236:             goto endit;
     237:         }
     238:         addpath(*cp++);
     239:     }
     240:     oldcp = cp;
     241:     while (cp > s && *cp != '/')
     242:         cp--, pathp--;
     243:     if (*cp == '/')
     244:         cp++, pathp++;
     245:     *pathp = '\0';
     246:     if (*oldcp == '{') {
     247:         execbrc(cp, NULL);
     248:         return;
     249:     }
     250:     matchdir(cp);
     251: endit:
     252:     pathp = spathp;
     253:     *pathp = '\0';
     254: }
     255:
     256: matchdir(pattern)
     257:     char *pattern;
     258: {
     259:     struct stat stb;
     260:     register struct direct *dp;
     261:     register DIR *dirp;
     262:
     263:     dirp = opendir(path);
     264:     if (dirp == NULL) {
     265:         if (expany)
     266:             return;
     267:         goto patherr2;
     268:     }
     269:     if (fstat(dirp->dd_fd, &stb) < 0)
     270:         goto patherr1;
     271:     if (!ISDIR(stb.st_mode)) {
     272:         errno = ENOTDIR;
     273:         goto patherr1;
     274:     }
     275:     while ((dp = readdir(dirp)) != NULL)
     276:         if (match(dp->d_name, pattern)) {
     277:             if (which & E_TILDE)
     278:                 Cat(path, dp->d_name);
     279:             else {
     280:                 strcpy(pathp, dp->d_name);
     281:                 Cat(tilde, tpathp);
     282:                 *pathp = '\0';
     283:             }
     284:         }
     285:     closedir(dirp);
     286:     return;
     287:
     288: patherr1:
     289:     closedir(dirp);
     290: patherr2:
     291:     strcat(path, ": ");
     292:     strcat(path, strerror(errno));
     293:     yyerror(path);
     294: }
     295:
     296: execbrc(p, s)
     297:     char *p, *s;
     298: {
     299:     char restbuf[BUFSIZ + 2];
     300:     register char *pe, *pm, *pl;
     301:     int brclev = 0;
     302:     char *lm, savec, *spathp;
     303:
     304:     for (lm = restbuf; *p != '{'; *lm++ = *p++)
     305:         continue;
     306:     for (pe = ++p; *pe; pe++)
     307:         switch (*pe) {
     308:
     309:         case '{':
     310:             brclev++;
     311:             continue;
     312:
     313:         case '}':
     314:             if (brclev == 0)
     315:                 goto pend;
     316:             brclev--;
     317:             continue;
     318:
     319:         case '[':
     320:             for (pe++; *pe && *pe != ']'; pe++)
     321:                 continue;
     322:             if (!*pe)
     323:                 yyerror("Missing ']'");
     324:             continue;
     325:         }
     326: pend:
     327:     if (brclev || !*pe) {
     328:         yyerror("Missing '}'");
     329:         return (0);
     330:     }
     331:     for (pl = pm = p; pm <= pe; pm++)
     332:         switch (*pm & (QUOTE|TRIM)) {
     333:
     334:         case '{':
     335:             brclev++;
     336:             continue;
     337:
     338:         case '}':
     339:             if (brclev) {
     340:                 brclev--;
     341:                 continue;
     342:             }
     343:             goto doit;
     344:
     345:         case ',':
     346:             if (brclev)
     347:                 continue;
     348: doit:
     349:             savec = *pm;
     350:             *pm = 0;
     351:             strcpy(lm, pl);
     352:             strcat(restbuf, pe + 1);
     353:             *pm = savec;
     354:             if (s == 0) {
     355:                 spathp = pathp;
     356:                 expsh(restbuf);
     357:                 pathp = spathp;
     358:                 *pathp = 0;
     359:             } else if (amatch(s, restbuf))
     360:                 return (1);
     361:             sort();
     362:             pl = pm + 1;
     363:             continue;
     364:
     365:         case '[':
     366:             for (pm++; *pm && *pm != ']'; pm++)
     367:                 continue;
     368:             if (!*pm)
     369:                 yyerror("Missing ']'");
     370:             continue;
     371:         }
     372:     return (0);
     373: }
     374:
     375: match(s, p)
     376:     char *s, *p;
     377: {
     378:     register int c;
     379:     register char *sentp;
     380:     char sexpany = expany;
     381:
     382:     if (*s == '.' && *p != '.')
     383:         return (0);
     384:     sentp = entp;
     385:     entp = s;
     386:     c = amatch(s, p);
     387:     entp = sentp;
     388:     expany = sexpany;
     389:     return (c);
     390: }
     391:
     392: amatch(s, p)
     393:     register char *s, *p;
     394: {
     395:     register int scc;
     396:     int ok, lc;
     397:     char *spathp;
     398:     struct stat stb;
     399:     int c, cc;
     400:
     401:     expany = 1;
     402:     for (;;) {
     403:         scc = *s++ & TRIM;
     404:         switch (c = *p++) {
     405:
     406:         case '{':
     407:             return (execbrc(p - 1, s - 1));
     408:
     409:         case '[':
     410:             ok = 0;
     411:             lc = 077777;
     412:             while (cc = *p++) {
     413:                 if (cc == ']') {
     414:                     if (ok)
     415:                         break;
     416:                     return (0);
     417:                 }
     418:                 if (cc == '-') {
     419:                     if (lc <= scc && scc <= *p++)
     420:                         ok++;
     421:                 } else
     422:                     if (scc == (lc = cc))
     423:                         ok++;
     424:             }
     425:             if (cc == 0) {
     426:                 yyerror("Missing ']'");
     427:                 return (0);
     428:             }
     429:             continue;
     430:
     431:         case '*':
     432:             if (!*p)
     433:                 return (1);
     434:             if (*p == '/') {
     435:                 p++;
     436:                 goto slash;
     437:             }
     438:             for (s--; *s; s++)
     439:                 if (amatch(s, p))
     440:                     return (1);
     441:             return (0);
     442:
     443:         case '\0':
     444:             return (scc == '\0');
     445:
     446:         default:
     447:             if ((c & TRIM) != scc)
     448:                 return (0);
     449:             continue;
     450:
     451:         case '?':
     452:             if (scc == '\0')
     453:                 return (0);
     454:             continue;
     455:
     456:         case '/':
     457:             if (scc)
     458:                 return (0);
     459: slash:
     460:             s = entp;
     461:             spathp = pathp;
     462:             while (*s)
     463:                 addpath(*s++);
     464:             addpath('/');
     465:             if (stat(path, &stb) == 0 && ISDIR(stb.st_mode))
     466:                 if (*p == '\0') {
     467:                     if (which & E_TILDE)
     468:                         Cat(path, "");
     469:                     else
     470:                         Cat(tilde, tpathp);
     471:                 } else
     472:                     expsh(p);
     473:             pathp = spathp;
     474:             *pathp = '\0';
     475:             return (0);
     476:         }
     477:     }
     478: }
     479:
     480: smatch(s, p)
     481:     register char *s, *p;
     482: {
     483:     register int scc;
     484:     int ok, lc;
     485:     int c, cc;
     486:
     487:     for (;;) {
     488:         scc = *s++ & TRIM;
     489:         switch (c = *p++) {
     490:
     491:         case '[':
     492:             ok = 0;
     493:             lc = 077777;
     494:             while (cc = *p++) {
     495:                 if (cc == ']') {
     496:                     if (ok)
     497:                         break;
     498:                     return (0);
     499:                 }
     500:                 if (cc == '-') {
     501:                     if (lc <= scc && scc <= *p++)
     502:                         ok++;
     503:                 } else
     504:                     if (scc == (lc = cc))
     505:                         ok++;
     506:             }
     507:             if (cc == 0) {
     508:                 yyerror("Missing ']'");
     509:                 return (0);
     510:             }
     511:             continue;
     512:
     513:         case '*':
     514:             if (!*p)
     515:                 return (1);
     516:             for (s--; *s; s++)
     517:                 if (smatch(s, p))
     518:                     return (1);
     519:             return (0);
     520:
     521:         case '\0':
     522:             return (scc == '\0');
     523:
     524:         default:
     525:             if ((c & TRIM) != scc)
     526:                 return (0);
     527:             continue;
     528:
     529:         case '?':
     530:             if (scc == 0)
     531:                 return (0);
     532:             continue;
     533:
     534:         }
     535:     }
     536: }
     537:
     538: Cat(s1, s2)
     539:     register char *s1, *s2;
     540: {
     541:     int len = strlen(s1) + strlen(s2) + 1;
     542:     register char *s;
     543:
     544:     nleft -= len;
     545:     if (nleft <= 0 || ++eargc >= GAVSIZ)
     546:         yyerror("Arguments too long");
     547:     eargv[eargc] = 0;
     548:     eargv[eargc - 1] = s = malloc(len);
     549:     if (s == NULL)
     550:         fatal("ran out of memory\n");
     551:     while (*s++ = *s1++ & TRIM)
     552:         ;
     553:     s--;
     554:     while (*s++ = *s2++ & TRIM)
     555:         ;
     556: }
     557:
     558: addpath(c)
     559:     char c;
     560: {
     561:
     562:     if (pathp >= lastpathp)
     563:         yyerror("Pathname too long");
     564:     else {
     565:         *pathp++ = c & TRIM;
     566:         *pathp = '\0';
     567:     }
     568: }
     569:
     570: /*
     571:  * Expand file names beginning with `~' into the
     572:  * user's home directory path name. Return a pointer in buf to the
     573:  * part corresponding to `file'.
     574:  */
     575: char *
     576: exptilde(buf, file)
     577:     char buf[];
     578:     char *file;
     579: {
     580:     register char *s1, *s2, *s3;
     581:     extern char homedir[];
     582:
     583:     if (*file != '~') {
     584:         strcpy(buf, file);
     585:         return(buf);
     586:     }
     587:     if (*++file == '\0') {
     588:         s2 = homedir;
     589:         s3 = NULL;
     590:     } else if (*file == '/') {
     591:         s2 = homedir;
     592:         s3 = file;
     593:     } else {
     594:         s3 = file;
     595:         while (*s3 && *s3 != '/')
     596:             s3++;
     597:         if (*s3 == '/')
     598:             *s3 = '\0';
     599:         else
     600:             s3 = NULL;
     601:         if (pw == NULL || strcmp(pw->pw_name, file) != 0) {
     602:             if ((pw = getpwnam(file)) == NULL) {
     603:                 error("%s: unknown user name\n", file);
     604:                 if (s3 != NULL)
     605:                     *s3 = '/';
     606:                 return(NULL);
     607:             }
     608:         }
     609:         if (s3 != NULL)
     610:             *s3 = '/';
     611:         s2 = pw->pw_dir;
     612:     }
     613:     for (s1 = buf; *s1++ = *s2++; )
     614:         ;
     615:     s2 = --s1;
     616:     if (s3 != NULL) {
     617:         s2++;
     618:         while (*s1++ = *s3++)
     619:             ;
     620:     }
     621:     return(s2);
     622: }

#### Defined functions

Cat defined in line 538; used 10 times

- in line 157, 193-195(2), 203, 232-234(2), 278-281(2), 468-470(2)

addpath defined in line 558; used 3 times

- in line 238, 463-464(2)

amatch defined in line 392; used 3 times

- in line 359, 386, 439

argcmp defined in line 207; used 2 times

- in line 34-37(2)

execbrc defined in line 296; used 2 times

- in line 247, 407

expand defined in line 48; used 12 times

- in /usr/src/ucb/rdist/defs.h line 125
- in /usr/src/ucb/rdist/gram.y line 114, 124-129(2), 139-144(2), 342-343(2), 398
- in /usr/src/ucb/rdist/main.c line 233
- in /usr/src/ucb/rdist/server.c line 147-149(2)

expsh defined in line 219; used 3 times

- in line 201, 356, 472

expstr defined in line 107; used 3 times

- in line 85, 148-153(2)

exptilde defined in line 575; used 5 times

- in /usr/src/ucb/rdist/defs.h line 126
- in /usr/src/ucb/rdist/docmd.c line 377
- in /usr/src/ucb/rdist/server.c line 81, 142, 213

match defined in line 375; used 1 times

- in line 276

matchdir defined in line 256; used 1 times

- in line 250

smatch defined in line 480; used 1 times

- in line 517

#### Defined variables

eargc defined in line 20; used 9 times

- in line 36-37(2), 77, 90, 199-202(2), 545-548(3)

eargv defined in line 21; used 7 times

- in line 36-37(2), 78-79(2), 92, 547-548(2)

entp defined in line 30; used 4 times

- in line 384-387(3), 460

expany defined in line 29; used 6 times

- in line 200, 230, 265, 380, 388, 401

lastpathp defined in line 24; used 2 times

- in line 75, 562

nleft defined in line 27; used 3 times

- in line 80, 544-545(2)

path defined in line 22; used 14 times

- in line 73-75(2), 183-187(2), 193, 230-232(2), 263, 278, 291-293(3), 465-468(2)

pathp defined in line 23; used 22 times

- in line 73-74(2), 185-190(3), 226, 242-245(3), 252-253(2), 280-282(2), 355-358(3), 461, 473-474(2), 562-566(3)

sccsid defined in line 8; never used
shchars defined in line 17; used 1 times

- in line 228

sortbase defined in line 31; used 5 times

- in line 36-37(4), 78

tilde defined in line 25; used 8 times

- in line 76, 164-167(2), 188, 195, 234, 281, 470

tpathp defined in line 26; used 6 times

- in line 73, 185-187(2), 234, 281, 470

which defined in line 19; used 8 times

- in line 72, 120, 156, 191-192(2), 231, 277, 467

#### Defined macros

GAVSIZ defined in line 13; used 2 times

- in line 56, 545

LC defined in line 14; used 1 times

- in line 126

RC defined in line 15; used 1 times

- in line 128

sort defined in line 36; used 4 times

- in line 158, 196, 204, 361

Last modified: 1995-05-10 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 2434 |