1: /* static char *sccsid = "@(#)files.c 4.16.1 (2.11BSD) 1/3/94"; */ 2: #include <sys/param.h> 3: #include <fcntl.h> 4: 5: /* UNIX DEPENDENT PROCEDURES */ 6: 7: /* DEFAULT RULES FOR UNIX */ 8: 9: char *builtin[] = 10: { 11: #ifdef pwb 12: ".SUFFIXES : .L .out .a .o .c .f .e .r .y .yr .ye .l .s .z .x .t .h .cl", 13: #else 14: ".SUFFIXES : .out .a .o .c .F .f .e .r .y .yr .ye .l .s .cl .p", 15: #endif 16: "YACC=yacc", 17: "YACCR=yacc -r", 18: "YACCE=yacc -e", 19: "YFLAGS=", 20: "LEX=lex", 21: "LFLAGS=", 22: "CC=cc", 23: #if defined(vax) || defined(sun) || defined(tahoe) 24: "AS=as", 25: #else 26: "AS=as -", 27: #endif 28: "PC=pc", 29: "PFLAGS=", 30: "CFLAGS=", 31: "RC=f77", 32: "RFLAGS=", 33: "FC=f77", 34: "EFLAGS=", 35: "FFLAGS=", 36: "LOADLIBES=", 37: #ifdef pwb 38: "SCOMP=scomp", 39: "SCFLAGS=", 40: "CMDICT=cmdict", 41: "CMFLAGS=", 42: #endif 43: 44: ".c.a :", 45: "\t$(CC) $(CFLAGS) -c $<", 46: "\tar r $@ $*.o", 47: "\trm -f $*.o", 48: 49: ".c.o :", 50: "\t$(CC) $(CFLAGS) -c $<", 51: 52: ".p.o :", 53: "\t$(PC) $(PFLAGS) -c $<", 54: 55: ".cl.o :", 56: "\tclass -c $<", 57: 58: ".e.o .r.o .F.o .f.o :", 59: "\t$(FC) $(RFLAGS) $(EFLAGS) $(FFLAGS) -c $<", 60: 61: ".s.o :", 62: "\t$(AS) -o $@ $<", 63: 64: ".y.o :", 65: "\t$(YACC) $(YFLAGS) $<", 66: "\t$(CC) $(CFLAGS) -c y.tab.c", 67: "\trm y.tab.c", 68: "\tmv y.tab.o $@", 69: 70: ".yr.o:", 71: "\t$(YACCR) $(YFLAGS) $<", 72: "\t$(RC) $(RFLAGS) -c y.tab.r", 73: "\trm y.tab.r", 74: "\tmv y.tab.o $@", 75: 76: ".ye.o :", 77: "\t$(YACCE) $(YFLAGS) $<", 78: "\t$(EC) $(RFLAGS) -c y.tab.e", 79: "\trm y.tab.e", 80: "\tmv y.tab.o $@", 81: 82: ".l.o :", 83: "\t$(LEX) $(LFLAGS) $<", 84: "\t$(CC) $(CFLAGS) -c lex.yy.c", 85: "\trm lex.yy.c", 86: "\tmv lex.yy.o $@", 87: 88: ".y.c :", 89: "\t$(YACC) $(YFLAGS) $<", 90: "\tmv y.tab.c $@", 91: 92: ".l.c :", 93: "\t$(LEX) $(LFLAGS) $<", 94: "\tmv lex.yy.c $@", 95: 96: ".yr.r:", 97: "\t$(YACCR) $(YFLAGS) $<", 98: "\tmv y.tab.r $@", 99: 100: ".ye.e :", 101: "\t$(YACCE) $(YFLAGS) $<", 102: "\tmv y.tab.e $@", 103: 104: #ifdef pwb 105: ".o.L .c.L .t.L:", 106: "\t$(SCOMP) $(SCFLAGS) $<", 107: 108: ".t.o:", 109: "\t$(SCOMP) $(SCFLAGS) -c $<", 110: 111: ".t.c:", 112: "\t$(SCOMP) $(SCFLAGS) -t $<", 113: 114: ".h.z .t.z:", 115: "\t$(CMDICT) $(CMFLAGS) $<", 116: 117: ".h.x .t.x:", 118: "\t$(CMDICT) $(CMFLAGS) -c $<", 119: #endif 120: 121: ".s.out .c.out .o.out :", 122: "\t$(CC) $(CFLAGS) $< $(LOADLIBES) -o $@", 123: 124: ".f.out .F.out .r.out .e.out :", 125: "\t$(FC) $(EFLAGS) $(RFLAGS) $(FFLAGS) $< $(LOADLIBES) -o $@", 126: "\t-rm $*.o", 127: 128: ".y.out :", 129: "\t$(YACC) $(YFLAGS) $<", 130: "\t$(CC) $(CFLAGS) y.tab.c $(LOADLIBES) -ly -o $@", 131: "\trm y.tab.c", 132: 133: ".l.out :", 134: "\t$(LEX) $(LFLAGS) $<", 135: "\t$(CC) $(CFLAGS) lex.yy.c $(LOADLIBES) -ll -o $@", 136: "\trm lex.yy.c", 137: 138: 0 }; 139: 140: #include "defs" 141: #include <sys/stat.h> 142: 143: 144: 145: TIMETYPE 146: exists(pname) 147: struct nameblock *pname; 148: { 149: struct stat buf; 150: register char *s, *filename; 151: TIMETYPE lookarch(); 152: extern char *findfl(); 153: 154: filename = pname->namep; 155: 156: for(s = filename ; *s!='\0' && *s!='(' ; ++s) 157: ; 158: 159: if(*s == '(') 160: return(lookarch(filename)); 161: 162: if (stat(filename, &buf) < 0) 163: { 164: s = findfl(filename); 165: if(s != (char *)-1) 166: { 167: pname->alias = copys(s); 168: if(stat(pname->alias, &buf) == 0) 169: return(buf.st_mtime); 170: } 171: return(0); 172: } 173: else return(buf.st_mtime); 174: } 175: 176: 177: TIMETYPE prestime() 178: { 179: TIMETYPE t; 180: time(&t); 181: return(t); 182: } 183: 184: 185: 186: FSTATIC char nbuf[MAXNAMLEN + 1]; 187: FSTATIC char *nbufend = &nbuf[MAXNAMLEN]; 188: 189: 190: 191: struct depblock *srchdir(pat, mkchain, nextdbl) 192: register char *pat; /* pattern to be matched in directory */ 193: int mkchain; /* nonzero if results to be remembered */ 194: struct depblock *nextdbl; /* final value for chain */ 195: { 196: register DIR *dirf; 197: int cldir; 198: char *dirname, *dirpref, *endir, *filepat, *p, temp[MAXPATHLEN]; 199: char fullname[MAXPATHLEN], *p1, *p2; 200: struct nameblock *q; 201: struct depblock *thisdbl; 202: struct dirhdr *od; 203: struct pattern *patp; 204: struct varblock *cp, *varptr(); 205: char *path, pth[MAXPATHLEN], *strcpy(); 206: struct direct *dptr; 207: 208: 209: thisdbl = 0; 210: 211: if(mkchain == NO) 212: for(patp=firstpat ; patp ; patp = patp->nxtpattern) 213: if(! unequal(pat, patp->patval)) return(0); 214: 215: patp = ALLOC(pattern); 216: patp->nxtpattern = firstpat; 217: firstpat = patp; 218: patp->patval = copys(pat); 219: 220: endir = 0; 221: 222: for(p=pat; *p!='\0'; ++p) 223: if(*p=='/') endir = p; 224: 225: if(endir==0) 226: { 227: dirpref = ""; 228: filepat = pat; 229: cp = varptr("VPATH"); 230: if (cp->varval == NULL) path = "."; 231: else { 232: path = pth; 233: *path = '\0'; 234: /* 235: * expand VPATH; this is almost surely not the place to do 236: * this, but I have no intention whatsoever of attempting 237: * to understand this code. 238: */ 239: if (strncmp(cp->varval, ".:", 2) != 0) { 240: strcpy(pth,".:"); 241: subst(cp->varval, pth + 2); 242: } 243: else 244: subst(cp->varval, pth); 245: } 246: } 247: else { 248: *endir = '\0'; 249: path = strcpy(pth, pat); 250: dirpref = concat(pat, "/", temp); 251: filepat = endir+1; 252: } 253: 254: while (*path) { /* Loop thru each VPATH directory */ 255: dirname = path; 256: for (; *path; path++) 257: if (*path == ':') { 258: *path++ = '\0'; 259: break; 260: } 261: 262: dirf = NULL; 263: cldir = NO; 264: 265: for(od = firstod; od; od = od->nxtopendir) 266: if(! unequal(dirname, od->dirn) ) 267: { 268: dirf = od->dirfc; 269: if (dirf != NULL) 270: rewinddir(dirf); /* start over at the beginning */ 271: break; 272: } 273: 274: if(dirf == NULL) 275: { 276: dirf = opendir(dirname); 277: if(nopdir >= MAXDIR) 278: cldir = YES; 279: else { 280: ++nopdir; 281: od = ALLOC(dirhdr); 282: od->nxtopendir = firstod; 283: firstod = od; 284: od->dirfc = dirf; 285: od->dirn = copys(dirname); 286: fcntl(dirf->dd_fd, F_SETFD, 1); 287: } 288: } 289: 290: if(dirf == NULL) 291: { 292: fprintf(stderr, "Directory %s: ", dirname); 293: fatal("Cannot open"); 294: } 295: 296: else for (dptr = readdir(dirf); dptr != NULL; dptr = readdir(dirf)) 297: { 298: p1 = dptr->d_name; 299: p2 = nbuf; 300: while( (p2<nbufend) && (*p2++ = *p1++)!='\0' ) 301: /* void */; 302: if( amatch(nbuf,filepat) ) 303: { 304: concat(dirpref,nbuf,fullname); 305: if( (q=srchname(fullname)) ==0) 306: q = makename(copys(fullname)); 307: if(mkchain) 308: { 309: thisdbl = ALLOC(depblock); 310: thisdbl->nxtdepblock = nextdbl; 311: thisdbl->depname = q; 312: nextdbl = thisdbl; 313: } 314: } 315: } 316: 317: if(endir != 0) *endir = '/'; 318: 319: if(cldir) { 320: closedir(dirf); 321: dirf = NULL; 322: } 323: } /* End of VPATH loop */ 324: return(thisdbl); 325: } 326: 327: /* stolen from glob through find */ 328: 329: static amatch(s, p) 330: char *s, *p; 331: { 332: register int cc, scc, k; 333: int c, lc; 334: 335: scc = *s; 336: lc = 077777; 337: switch (c = *p) { 338: 339: case '[': 340: k = 0; 341: while (cc = *++p) { 342: switch (cc) { 343: 344: case ']': 345: if (k) 346: return(amatch(++s, ++p)); 347: else 348: return(0); 349: 350: case '-': 351: k |= (lc <= scc) & (scc <= (cc=p[1]) ) ; 352: } 353: if (scc==(lc=cc)) k++; 354: } 355: return(0); 356: 357: case '?': 358: caseq: 359: if(scc) return(amatch(++s, ++p)); 360: return(0); 361: case '*': 362: return(umatch(s, ++p)); 363: case 0: 364: return(!scc); 365: } 366: if (c==scc) goto caseq; 367: return(0); 368: } 369: 370: static umatch(s, p) 371: char *s, *p; 372: { 373: if(*p==0) return(1); 374: while(*s) 375: if (amatch(s++,p)) return(1); 376: return(0); 377: } 378: 379: #ifdef METERFILE 380: #include <pwd.h> 381: int meteron = 0; /* default: metering off */ 382: 383: meter(file) 384: char *file; 385: { 386: TIMETYPE tvec; 387: char *p, *ctime(); 388: FILE * mout; 389: struct passwd *pwd, *getpwuid(); 390: 391: if(file==0 || meteron==0) return; 392: 393: pwd = getpwuid(getuid()); 394: 395: time(&tvec); 396: 397: if( (mout=fopen(file,"a")) != NULL ) 398: { 399: p = ctime(&tvec); 400: p[16] = '\0'; 401: fprintf(mout,"User %s, %s\n",pwd->pw_name,p+4); 402: fclose(mout); 403: } 404: } 405: #endif 406: 407: 408: /* look inside archive for notation a(b) 409: a(b) is file member b in archive a 410: */ 411: 412: #include <ar.h> 413: #include "archive.h" /* from 'ar's directory */ 414: 415: char arfile[MAXPATHLEN]; 416: CHDR chdr; 417: char *arfname = chdr.name; 418: FILE *arfd; 419: off_t arpos; 420: 421: TIMETYPE lookarch(filename) 422: char *filename; 423: { 424: char *p, *q, *send, s[MAXNAMLEN + 1]; 425: 426: for (p = filename; *p!= '(' ; ++p) 427: ; 428: *p = '\0'; 429: strcpy(arfile, filename); 430: openarch(filename); 431: *p++ = '('; 432: 433: send = s + sizeof(s); 434: 435: for( q = s; q < send && *p!='\0' && *p!=')' ; *q++ = *p++) 436: ; 437: *q++ = '\0'; 438: while (getarch()) 439: { 440: if (!strcmp(arfname, s)) 441: { 442: clarch(); 443: return(chdr.date); 444: } 445: arpos += (chdr.size + (chdr.size + chdr.lname & 1)); 446: arpos += sizeof (struct ar_hdr); 447: } 448: strcpy(chdr.name, s); 449: clarch(); 450: return(0L); 451: } 452: 453: 454: clarch() 455: { 456: if (arfd) 457: fclose( arfd ); 458: } 459: 460: 461: openarch(f) 462: register char *f; 463: { 464: char magic[SARMAG]; 465: 466: arfd = fopen(f, "r"); 467: if (arfd == NULL) 468: return; 469: 470: fseek(arfd, 0L, 0); 471: fread(magic, SARMAG, 1, arfd); 472: arpos = SARMAG; 473: if (strncmp(magic, ARMAG, SARMAG)) 474: fatal1("%s is not an archive", f); 475: } 476: 477: /* 478: * "borrowed" from 'ld' because we didn't want to drag in everything 479: * from 'ar'. The error checking was also ripped out, basically if any 480: * of the criteria for being an archive are not met then a -1 is returned 481: * and the rest of 'make' figures out what to do (bails out). 482: */ 483: 484: typedef struct ar_hdr HDR; 485: extern long strtol(); 486: 487: /* Convert ar header field to an integer. */ 488: #define AR_ATOI(from, to, len, base) { \ 489: bcopy(from, buf, len); \ 490: buf[len] = '\0'; \ 491: to = strtol(buf, (char **)NULL, base); \ 492: } 493: 494: getarch() 495: { 496: char hb[sizeof(HDR) + 1]; /* real header */ 497: struct ar_hdr arhead; 498: register HDR *hdr; 499: register int len; 500: int nr; 501: register char *p; 502: char buf[20]; 503: 504: if (!arfd) 505: return(0); 506: fseek(arfd, arpos, 0); 507: 508: nr = fread(hb, 1, sizeof(HDR), arfd); 509: if (nr != sizeof(HDR)) 510: return(0); 511: 512: hdr = (HDR *)hb; 513: if (strncmp(hdr->ar_fmag, ARFMAG, sizeof(ARFMAG) - 1)) 514: return(0); 515: 516: /* Convert the header into the internal format. */ 517: #define DECIMAL 10 518: #define OCTAL 8 519: 520: AR_ATOI(hdr->ar_date, chdr.date, sizeof(hdr->ar_date), DECIMAL); 521: AR_ATOI(hdr->ar_uid, chdr.uid, sizeof(hdr->ar_uid), DECIMAL); 522: AR_ATOI(hdr->ar_gid, chdr.gid, sizeof(hdr->ar_gid), DECIMAL); 523: AR_ATOI(hdr->ar_mode, chdr.mode, sizeof(hdr->ar_mode), OCTAL); 524: AR_ATOI(hdr->ar_size, chdr.size, sizeof(hdr->ar_size), DECIMAL); 525: 526: /* Leading spaces should never happen. */ 527: if (hdr->ar_name[0] == ' ') 528: return(-1); 529: 530: /* 531: * Long name support. Set the "real" size of the file, and the 532: * long name flag/size. 533: */ 534: if (!bcmp(hdr->ar_name, AR_EFMT1, sizeof(AR_EFMT1) - 1)) { 535: chdr.lname = len = atoi(hdr->ar_name + sizeof(AR_EFMT1) - 1); 536: if (len <= 0 || len > MAXNAMLEN) 537: return(-1); 538: nr = fread(chdr.name, 1, (size_t)len, arfd); 539: if (nr != len) 540: return(0); 541: chdr.name[len] = 0; 542: chdr.size -= len; 543: } else { 544: chdr.lname = 0; 545: bcopy(hdr->ar_name, chdr.name, sizeof(hdr->ar_name)); 546: 547: /* Strip trailing spaces, null terminate. */ 548: for (p = chdr.name + sizeof(hdr->ar_name) - 1; *p == ' '; --p); 549: *++p = '\0'; 550: } 551: return(1); 552: } 553: 554: /* 555: * findfl(name) (like execvp, but does path search and finds files) 556: */ 557: static char fname[128]; 558: 559: char *execat(); 560: 561: char *findfl(name) 562: register char *name; 563: { 564: register char *p; 565: struct varblock *cp, *varptr(); 566: struct stat buf; 567: 568: for (p = name; *p; p++) 569: if(*p == '/') return(name); 570: 571: cp = varptr("VPATH"); 572: if(cp->varval == NULL || *cp->varval == 0) 573: p = ":"; 574: else 575: p = cp->varval; 576: 577: do 578: { 579: p = execat(p, name, fname); 580: if(stat(fname,&buf) >= 0) 581: return(fname); 582: } while (p); 583: return((char *)-1); 584: } 585: 586: char *execat(s1, s2, si) 587: register char *s1, *s2; 588: char *si; 589: { 590: register char *s; 591: 592: s = si; 593: while (*s1 && *s1 != ':' && *s1 != '-') 594: *s++ = *s1++; 595: if (si != s) 596: *s++ = '/'; 597: while (*s2) 598: *s++ = *s2++; 599: *s = '\0'; 600: return(*s1? ++s1: 0); 601: } 602: 603: 604: /* copy s to d, changing file names to file aliases */ 605: fixname(s, d) 606: char *s, *d; 607: { 608: register char *r, *q; 609: struct nameblock *pn; 610: char name[MAXPATHLEN]; 611: 612: while (*s) { 613: if (isspace(*s)) *d++ = *s++; 614: else { 615: r = name; 616: while (*s) { 617: if (isspace(*s)) break; 618: *r++ = *s++; 619: } 620: *r = '\0'; 621: 622: if (((pn = srchname(name)) != 0) && (pn->alias)) 623: q = pn->alias; 624: else q = name; 625: 626: while (*q) *d++ = *q++; 627: } 628: } 629: *d = '\0'; 630: }