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