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