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