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