1 static char *sccsid = "@(#)files.c 4.16 (Berkeley) 87/11/15"; 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) || 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.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 == NULL) 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(dirfd(dirf), 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 #ifndef pdp11 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 } 649