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