|
|
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[] = "@(#)glob.c 5.2 (Berkeley) 3/7/86"; ! 9: #endif not lint ! 10: ! 11: /* ! 12: * C-shell glob for random programs. ! 13: */ ! 14: ! 15: #include <sys/param.h> ! 16: #include <sys/stat.h> ! 17: #include <sys/dir.h> ! 18: ! 19: #include <stdio.h> ! 20: #include <errno.h> ! 21: #include <pwd.h> ! 22: ! 23: #define QUOTE 0200 ! 24: #define TRIM 0177 ! 25: #define eq(a,b) (strcmp(a, b)==0) ! 26: #define GAVSIZ (NCARGS/6) ! 27: #define isdir(d) ((d.st_mode & S_IFMT) == S_IFDIR) ! 28: ! 29: static char **gargv; /* Pointer to the (stack) arglist */ ! 30: static short gargc; /* Number args in gargv */ ! 31: static short gnleft; ! 32: static short gflag; ! 33: static int tglob(); ! 34: char **glob(); ! 35: char *globerr; ! 36: char *home; ! 37: struct passwd *getpwnam(); ! 38: extern int errno; ! 39: static char *strspl(), *strend(); ! 40: char *malloc(), *strcpy(), *strcat(); ! 41: char **copyblk(); ! 42: ! 43: static int globcnt; ! 44: ! 45: char *globchars = "`{[*?"; ! 46: ! 47: static char *gpath, *gpathp, *lastgpathp; ! 48: static int globbed; ! 49: static char *entp; ! 50: static char **sortbas; ! 51: ! 52: char ** ! 53: glob(v) ! 54: register char *v; ! 55: { ! 56: char agpath[BUFSIZ]; ! 57: char *agargv[GAVSIZ]; ! 58: char *vv[2]; ! 59: vv[0] = v; ! 60: vv[1] = 0; ! 61: gflag = 0; ! 62: rscan(vv, tglob); ! 63: if (gflag == 0) ! 64: return (copyblk(vv)); ! 65: ! 66: globerr = 0; ! 67: gpath = agpath; gpathp = gpath; *gpathp = 0; ! 68: lastgpathp = &gpath[sizeof agpath - 2]; ! 69: ginit(agargv); globcnt = 0; ! 70: collect(v); ! 71: if (globcnt == 0 && (gflag&1)) { ! 72: blkfree(gargv), gargv = 0; ! 73: return (0); ! 74: } else ! 75: return (gargv = copyblk(gargv)); ! 76: } ! 77: ! 78: static ! 79: ginit(agargv) ! 80: char **agargv; ! 81: { ! 82: ! 83: agargv[0] = 0; gargv = agargv; sortbas = agargv; gargc = 0; ! 84: gnleft = NCARGS - 4; ! 85: } ! 86: ! 87: static ! 88: collect(as) ! 89: register char *as; ! 90: { ! 91: if (eq(as, "{") || eq(as, "{}")) { ! 92: Gcat(as, ""); ! 93: sort(); ! 94: } else ! 95: acollect(as); ! 96: } ! 97: ! 98: static ! 99: acollect(as) ! 100: register char *as; ! 101: { ! 102: register int ogargc = gargc; ! 103: ! 104: gpathp = gpath; *gpathp = 0; globbed = 0; ! 105: expand(as); ! 106: if (gargc != ogargc) ! 107: sort(); ! 108: } ! 109: ! 110: static ! 111: sort() ! 112: { ! 113: register char **p1, **p2, *c; ! 114: char **Gvp = &gargv[gargc]; ! 115: ! 116: p1 = sortbas; ! 117: while (p1 < Gvp-1) { ! 118: p2 = p1; ! 119: while (++p2 < Gvp) ! 120: if (strcmp(*p1, *p2) > 0) ! 121: c = *p1, *p1 = *p2, *p2 = c; ! 122: p1++; ! 123: } ! 124: sortbas = Gvp; ! 125: } ! 126: ! 127: static ! 128: expand(as) ! 129: char *as; ! 130: { ! 131: register char *cs; ! 132: register char *sgpathp, *oldcs; ! 133: struct stat stb; ! 134: ! 135: sgpathp = gpathp; ! 136: cs = as; ! 137: if (*cs == '~' && gpathp == gpath) { ! 138: addpath('~'); ! 139: for (cs++; letter(*cs) || digit(*cs) || *cs == '-';) ! 140: addpath(*cs++); ! 141: if (!*cs || *cs == '/') { ! 142: if (gpathp != gpath + 1) { ! 143: *gpathp = 0; ! 144: if (gethdir(gpath + 1)) ! 145: globerr = "Unknown user name after ~"; ! 146: (void) strcpy(gpath, gpath + 1); ! 147: } else ! 148: (void) strcpy(gpath, home); ! 149: gpathp = strend(gpath); ! 150: } ! 151: } ! 152: while (!any(*cs, globchars)) { ! 153: if (*cs == 0) { ! 154: if (!globbed) ! 155: Gcat(gpath, ""); ! 156: else if (stat(gpath, &stb) >= 0) { ! 157: Gcat(gpath, ""); ! 158: globcnt++; ! 159: } ! 160: goto endit; ! 161: } ! 162: addpath(*cs++); ! 163: } ! 164: oldcs = cs; ! 165: while (cs > as && *cs != '/') ! 166: cs--, gpathp--; ! 167: if (*cs == '/') ! 168: cs++, gpathp++; ! 169: *gpathp = 0; ! 170: if (*oldcs == '{') { ! 171: (void) execbrc(cs, ((char *)0)); ! 172: return; ! 173: } ! 174: matchdir(cs); ! 175: endit: ! 176: gpathp = sgpathp; ! 177: *gpathp = 0; ! 178: } ! 179: ! 180: static ! 181: matchdir(pattern) ! 182: char *pattern; ! 183: { ! 184: struct stat stb; ! 185: register struct direct *dp; ! 186: DIR *dirp; ! 187: ! 188: dirp = opendir(gpath); ! 189: if (dirp == NULL) { ! 190: if (globbed) ! 191: return; ! 192: goto patherr2; ! 193: } ! 194: if (fstat(dirp->dd_fd, &stb) < 0) ! 195: goto patherr1; ! 196: if (!isdir(stb)) { ! 197: errno = ENOTDIR; ! 198: goto patherr1; ! 199: } ! 200: while ((dp = readdir(dirp)) != NULL) { ! 201: if (dp->d_ino == 0) ! 202: continue; ! 203: if (match(dp->d_name, pattern)) { ! 204: Gcat(gpath, dp->d_name); ! 205: globcnt++; ! 206: } ! 207: } ! 208: closedir(dirp); ! 209: return; ! 210: ! 211: patherr1: ! 212: closedir(dirp); ! 213: patherr2: ! 214: globerr = "Bad directory components"; ! 215: } ! 216: ! 217: static ! 218: execbrc(p, s) ! 219: char *p, *s; ! 220: { ! 221: char restbuf[BUFSIZ + 2]; ! 222: register char *pe, *pm, *pl; ! 223: int brclev = 0; ! 224: char *lm, savec, *sgpathp; ! 225: ! 226: for (lm = restbuf; *p != '{'; *lm++ = *p++) ! 227: continue; ! 228: for (pe = ++p; *pe; pe++) ! 229: switch (*pe) { ! 230: ! 231: case '{': ! 232: brclev++; ! 233: continue; ! 234: ! 235: case '}': ! 236: if (brclev == 0) ! 237: goto pend; ! 238: brclev--; ! 239: continue; ! 240: ! 241: case '[': ! 242: for (pe++; *pe && *pe != ']'; pe++) ! 243: continue; ! 244: continue; ! 245: } ! 246: pend: ! 247: brclev = 0; ! 248: for (pl = pm = p; pm <= pe; pm++) ! 249: switch (*pm & (QUOTE|TRIM)) { ! 250: ! 251: case '{': ! 252: brclev++; ! 253: continue; ! 254: ! 255: case '}': ! 256: if (brclev) { ! 257: brclev--; ! 258: continue; ! 259: } ! 260: goto doit; ! 261: ! 262: case ','|QUOTE: ! 263: case ',': ! 264: if (brclev) ! 265: continue; ! 266: doit: ! 267: savec = *pm; ! 268: *pm = 0; ! 269: (void) strcpy(lm, pl); ! 270: (void) strcat(restbuf, pe + 1); ! 271: *pm = savec; ! 272: if (s == 0) { ! 273: sgpathp = gpathp; ! 274: expand(restbuf); ! 275: gpathp = sgpathp; ! 276: *gpathp = 0; ! 277: } else if (amatch(s, restbuf)) ! 278: return (1); ! 279: sort(); ! 280: pl = pm + 1; ! 281: if (brclev) ! 282: return (0); ! 283: continue; ! 284: ! 285: case '[': ! 286: for (pm++; *pm && *pm != ']'; pm++) ! 287: continue; ! 288: if (!*pm) ! 289: pm--; ! 290: continue; ! 291: } ! 292: if (brclev) ! 293: goto doit; ! 294: return (0); ! 295: } ! 296: ! 297: static ! 298: match(s, p) ! 299: char *s, *p; ! 300: { ! 301: register int c; ! 302: register char *sentp; ! 303: char sglobbed = globbed; ! 304: ! 305: if (*s == '.' && *p != '.') ! 306: return (0); ! 307: sentp = entp; ! 308: entp = s; ! 309: c = amatch(s, p); ! 310: entp = sentp; ! 311: globbed = sglobbed; ! 312: return (c); ! 313: } ! 314: ! 315: static ! 316: amatch(s, p) ! 317: register char *s, *p; ! 318: { ! 319: register int scc; ! 320: int ok, lc; ! 321: char *sgpathp; ! 322: struct stat stb; ! 323: int c, cc; ! 324: ! 325: globbed = 1; ! 326: for (;;) { ! 327: scc = *s++ & TRIM; ! 328: switch (c = *p++) { ! 329: ! 330: case '{': ! 331: return (execbrc(p - 1, s - 1)); ! 332: ! 333: case '[': ! 334: ok = 0; ! 335: lc = 077777; ! 336: while (cc = *p++) { ! 337: if (cc == ']') { ! 338: if (ok) ! 339: break; ! 340: return (0); ! 341: } ! 342: if (cc == '-') { ! 343: if (lc <= scc && scc <= *p++) ! 344: ok++; ! 345: } else ! 346: if (scc == (lc = cc)) ! 347: ok++; ! 348: } ! 349: if (cc == 0) ! 350: if (ok) ! 351: p--; ! 352: else ! 353: return 0; ! 354: continue; ! 355: ! 356: case '*': ! 357: if (!*p) ! 358: return (1); ! 359: if (*p == '/') { ! 360: p++; ! 361: goto slash; ! 362: } ! 363: s--; ! 364: do { ! 365: if (amatch(s, p)) ! 366: return (1); ! 367: } while (*s++); ! 368: return (0); ! 369: ! 370: case 0: ! 371: return (scc == 0); ! 372: ! 373: default: ! 374: if (c != scc) ! 375: return (0); ! 376: continue; ! 377: ! 378: case '?': ! 379: if (scc == 0) ! 380: return (0); ! 381: continue; ! 382: ! 383: case '/': ! 384: if (scc) ! 385: return (0); ! 386: slash: ! 387: s = entp; ! 388: sgpathp = gpathp; ! 389: while (*s) ! 390: addpath(*s++); ! 391: addpath('/'); ! 392: if (stat(gpath, &stb) == 0 && isdir(stb)) ! 393: if (*p == 0) { ! 394: Gcat(gpath, ""); ! 395: globcnt++; ! 396: } else ! 397: expand(p); ! 398: gpathp = sgpathp; ! 399: *gpathp = 0; ! 400: return (0); ! 401: } ! 402: } ! 403: } ! 404: ! 405: static ! 406: Gmatch(s, p) ! 407: register char *s, *p; ! 408: { ! 409: register int scc; ! 410: int ok, lc; ! 411: int c, cc; ! 412: ! 413: for (;;) { ! 414: scc = *s++ & TRIM; ! 415: switch (c = *p++) { ! 416: ! 417: case '[': ! 418: ok = 0; ! 419: lc = 077777; ! 420: while (cc = *p++) { ! 421: if (cc == ']') { ! 422: if (ok) ! 423: break; ! 424: return (0); ! 425: } ! 426: if (cc == '-') { ! 427: if (lc <= scc && scc <= *p++) ! 428: ok++; ! 429: } else ! 430: if (scc == (lc = cc)) ! 431: ok++; ! 432: } ! 433: if (cc == 0) ! 434: if (ok) ! 435: p--; ! 436: else ! 437: return 0; ! 438: continue; ! 439: ! 440: case '*': ! 441: if (!*p) ! 442: return (1); ! 443: for (s--; *s; s++) ! 444: if (Gmatch(s, p)) ! 445: return (1); ! 446: return (0); ! 447: ! 448: case 0: ! 449: return (scc == 0); ! 450: ! 451: default: ! 452: if ((c & TRIM) != scc) ! 453: return (0); ! 454: continue; ! 455: ! 456: case '?': ! 457: if (scc == 0) ! 458: return (0); ! 459: continue; ! 460: ! 461: } ! 462: } ! 463: } ! 464: ! 465: static ! 466: Gcat(s1, s2) ! 467: register char *s1, *s2; ! 468: { ! 469: register int len = strlen(s1) + strlen(s2) + 1; ! 470: ! 471: if (len >= gnleft || gargc >= GAVSIZ - 1) ! 472: globerr = "Arguments too long"; ! 473: else { ! 474: gargc++; ! 475: gnleft -= len; ! 476: gargv[gargc] = 0; ! 477: gargv[gargc - 1] = strspl(s1, s2); ! 478: } ! 479: } ! 480: ! 481: static ! 482: addpath(c) ! 483: char c; ! 484: { ! 485: ! 486: if (gpathp >= lastgpathp) ! 487: globerr = "Pathname too long"; ! 488: else { ! 489: *gpathp++ = c; ! 490: *gpathp = 0; ! 491: } ! 492: } ! 493: ! 494: static ! 495: rscan(t, f) ! 496: register char **t; ! 497: int (*f)(); ! 498: { ! 499: register char *p, c; ! 500: ! 501: while (p = *t++) { ! 502: if (f == tglob) ! 503: if (*p == '~') ! 504: gflag |= 2; ! 505: else if (eq(p, "{") || eq(p, "{}")) ! 506: continue; ! 507: while (c = *p++) ! 508: (*f)(c); ! 509: } ! 510: } ! 511: /* ! 512: static ! 513: scan(t, f) ! 514: register char **t; ! 515: int (*f)(); ! 516: { ! 517: register char *p, c; ! 518: ! 519: while (p = *t++) ! 520: while (c = *p) ! 521: *p++ = (*f)(c); ! 522: } */ ! 523: ! 524: static ! 525: tglob(c) ! 526: register char c; ! 527: { ! 528: ! 529: if (any(c, globchars)) ! 530: gflag |= c == '{' ? 2 : 1; ! 531: return (c); ! 532: } ! 533: /* ! 534: static ! 535: trim(c) ! 536: char c; ! 537: { ! 538: ! 539: return (c & TRIM); ! 540: } */ ! 541: ! 542: ! 543: letter(c) ! 544: register char c; ! 545: { ! 546: ! 547: return (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c == '_'); ! 548: } ! 549: ! 550: digit(c) ! 551: register char c; ! 552: { ! 553: ! 554: return (c >= '0' && c <= '9'); ! 555: } ! 556: ! 557: any(c, s) ! 558: register int c; ! 559: register char *s; ! 560: { ! 561: ! 562: while (*s) ! 563: if (*s++ == c) ! 564: return(1); ! 565: return(0); ! 566: } ! 567: blklen(av) ! 568: register char **av; ! 569: { ! 570: register int i = 0; ! 571: ! 572: while (*av++) ! 573: i++; ! 574: return (i); ! 575: } ! 576: ! 577: char ** ! 578: blkcpy(oav, bv) ! 579: char **oav; ! 580: register char **bv; ! 581: { ! 582: register char **av = oav; ! 583: ! 584: while (*av++ = *bv++) ! 585: continue; ! 586: return (oav); ! 587: } ! 588: ! 589: blkfree(av0) ! 590: char **av0; ! 591: { ! 592: register char **av = av0; ! 593: ! 594: while (*av) ! 595: free(*av++); ! 596: free((char *)av0); ! 597: } ! 598: ! 599: static ! 600: char * ! 601: strspl(cp, dp) ! 602: register char *cp, *dp; ! 603: { ! 604: register char *ep = malloc((unsigned)(strlen(cp) + strlen(dp) + 1)); ! 605: ! 606: if (ep == (char *)0) ! 607: fatal("Out of memory"); ! 608: (void) strcpy(ep, cp); ! 609: (void) strcat(ep, dp); ! 610: return (ep); ! 611: } ! 612: ! 613: char ** ! 614: copyblk(v) ! 615: register char **v; ! 616: { ! 617: register char **nv = (char **)malloc((unsigned)((blklen(v) + 1) * ! 618: sizeof(char **))); ! 619: if (nv == (char **)0) ! 620: fatal("Out of memory"); ! 621: ! 622: return (blkcpy(nv, v)); ! 623: } ! 624: ! 625: static ! 626: char * ! 627: strend(cp) ! 628: register char *cp; ! 629: { ! 630: ! 631: while (*cp) ! 632: cp++; ! 633: return (cp); ! 634: } ! 635: /* ! 636: * Extract a home directory from the password file ! 637: * The argument points to a buffer where the name of the ! 638: * user whose home directory is sought is currently. ! 639: * We write the home directory of the user back there. ! 640: */ ! 641: gethdir(home) ! 642: char *home; ! 643: { ! 644: register struct passwd *pp = getpwnam(home); ! 645: ! 646: if (pp == 0) ! 647: return (1); ! 648: (void) strcpy(home, pp->pw_dir); ! 649: return (0); ! 650: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.