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