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