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