1 static char *sccsid = "@(#)files.c 4.9 (Berkeley) 84/03/21"; 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 137 138 TIMETYPE exists(filename) 139 char *filename; 140 { 141 #include <sys/stat.h> 142 struct stat buf; 143 register char *s; 144 TIMETYPE lookarch(); 145 146 for(s = filename ; *s!='\0' && *s!='(' ; ++s) 147 ; 148 149 if(*s == '(') 150 return(lookarch(filename)); 151 152 if (stat(filename, &buf) < 0) 153 return(0); 154 else return(buf.st_mtime); 155 } 156 157 158 TIMETYPE prestime() 159 { 160 TIMETYPE t; 161 time(&t); 162 return(t); 163 } 164 165 166 167 FSTATIC char nbuf[MAXNAMLEN + 1]; 168 FSTATIC char *nbufend = &nbuf[MAXNAMLEN]; 169 170 171 172 struct depblock *srchdir(pat, mkchain, nextdbl) 173 register char *pat; /* pattern to be matched in directory */ 174 int mkchain; /* nonzero if results to be remembered */ 175 struct depblock *nextdbl; /* final value for chain */ 176 { 177 DIR *dirf; 178 register int i; 179 int nread, cldir; 180 char *dirname, *dirpref, *endir, *filepat, *p, temp[100]; 181 char fullname[100], *p1, *p2; 182 struct nameblock *q; 183 struct depblock *thisdbl; 184 struct dirhdr *od; 185 struct pattern *patp; 186 187 struct direct *dptr; 188 189 190 thisdbl = 0; 191 192 if(mkchain == NO) 193 for(patp=firstpat ; patp ; patp = patp->nxtpattern) 194 if(! unequal(pat, patp->patval)) return(0); 195 196 patp = ALLOC(pattern); 197 patp->nxtpattern = firstpat; 198 firstpat = patp; 199 patp->patval = copys(pat); 200 201 endir = 0; 202 203 for(p=pat; *p!='\0'; ++p) 204 if(*p=='/') endir = p; 205 206 if(endir==0) 207 { 208 dirname = "."; 209 dirpref = ""; 210 filepat = pat; 211 } 212 else { 213 dirname = pat; 214 *endir = '\0'; 215 dirpref = concat(dirname, "/", temp); 216 filepat = endir+1; 217 } 218 219 dirf = NULL; 220 cldir = NO; 221 222 for(od = firstod; od; od = od->nxtopendir) 223 if(! unequal(dirname, od->dirn) ) 224 { 225 dirf = od->dirfc; 226 if (dirf != NULL) 227 rewinddir(dirf); /* start over at the beginning */ 228 break; 229 } 230 231 if(dirf == NULL) 232 { 233 dirf = opendir(dirname); 234 if(nopdir >= MAXDIR) 235 cldir = YES; 236 else { 237 ++nopdir; 238 od = ALLOC(dirhdr); 239 od->nxtopendir = firstod; 240 firstod = od; 241 od->dirfc = dirf; 242 od->dirn = copys(dirname); 243 fcntl(dirf->dd_fd, F_SETFD, 1); 244 } 245 } 246 247 if(dirf == NULL) 248 { 249 fprintf(stderr, "Directory %s: ", dirname); 250 fatal("Cannot open"); 251 } 252 253 else for (dptr = readdir(dirf); dptr != NULL; dptr = readdir(dirf)) 254 { 255 p1 = dptr->d_name; 256 p2 = nbuf; 257 while( (p2<nbufend) && (*p2++ = *p1++)!='\0' ) 258 /* void */; 259 if( amatch(nbuf,filepat) ) 260 { 261 concat(dirpref,nbuf,fullname); 262 if( (q=srchname(fullname)) ==0) 263 q = makename(copys(fullname)); 264 if(mkchain) 265 { 266 thisdbl = ALLOC(depblock); 267 thisdbl->nxtdepblock = nextdbl; 268 thisdbl->depname = q; 269 nextdbl = thisdbl; 270 } 271 } 272 } 273 274 if(endir != 0) *endir = '/'; 275 276 if(cldir) { 277 closedir(dirf); 278 dirf = NULL; 279 } 280 return(thisdbl); 281 } 282 283 /* stolen from glob through find */ 284 285 static amatch(s, p) 286 char *s, *p; 287 { 288 register int cc, scc, k; 289 int c, lc; 290 291 scc = *s; 292 lc = 077777; 293 switch (c = *p) { 294 295 case '[': 296 k = 0; 297 while (cc = *++p) { 298 switch (cc) { 299 300 case ']': 301 if (k) 302 return(amatch(++s, ++p)); 303 else 304 return(0); 305 306 case '-': 307 k |= (lc <= scc) & (scc <= (cc=p[1]) ) ; 308 } 309 if (scc==(lc=cc)) k++; 310 } 311 return(0); 312 313 case '?': 314 caseq: 315 if(scc) return(amatch(++s, ++p)); 316 return(0); 317 case '*': 318 return(umatch(s, ++p)); 319 case 0: 320 return(!scc); 321 } 322 if (c==scc) goto caseq; 323 return(0); 324 } 325 326 static umatch(s, p) 327 char *s, *p; 328 { 329 if(*p==0) return(1); 330 while(*s) 331 if (amatch(s++,p)) return(1); 332 return(0); 333 } 334 335 #ifdef METERFILE 336 #include <pwd.h> 337 int meteron = 0; /* default: metering off */ 338 339 meter(file) 340 char *file; 341 { 342 TIMETYPE tvec; 343 char *p, *ctime(); 344 FILE * mout; 345 struct passwd *pwd, *getpwuid(); 346 347 if(file==0 || meteron==0) return; 348 349 pwd = getpwuid(getuid()); 350 351 time(&tvec); 352 353 if( (mout=fopen(file,"a")) != NULL ) 354 { 355 p = ctime(&tvec); 356 p[16] = '\0'; 357 fprintf(mout,"User %s, %s\n",pwd->pw_name,p+4); 358 fclose(mout); 359 } 360 } 361 #endif 362 363 364 /* look inside archives for notations a(b) and a((b)) 365 a(b) is file member b in archive a 366 a((b)) is entry point _b in object archive a 367 */ 368 369 #ifdef ASCARCH 370 # include <ar.h> 371 #else 372 # include <ar.h> 373 #endif 374 #include <a.out.h> 375 376 static long arflen; 377 static long arfdate; 378 static char arfname[16]; 379 FILE *arfd; 380 long int arpos, arlen; 381 382 static struct exec objhead; 383 384 static struct nlist objentry; 385 386 387 TIMETYPE lookarch(filename) 388 char *filename; 389 { 390 char *p, *q, *send, s[MAXNAMLEN + 1]; 391 int i, nc, nsym, objarch; 392 393 for(p = filename; *p!= '(' ; ++p) 394 ; 395 *p = '\0'; 396 openarch(filename); 397 *p++ = '('; 398 399 if(*p == '(') 400 { 401 objarch = YES; 402 nc = 8; 403 ++p; 404 } 405 else 406 { 407 objarch = NO; 408 nc = MAXNAMLEN; 409 } 410 send = s + nc; 411 412 for( q = s ; q<send && *p!='\0' && *p!=')' ; *q++ = *p++ ) 413 ; 414 while(q < send) 415 *q++ = '\0'; 416 while(getarch()) 417 { 418 if(objarch) 419 { 420 getobj(); 421 nsym = objhead.a_syms / sizeof(objentry); 422 for(i = 0; i<nsym ; ++i) 423 { 424 fread( (char *) &objentry, sizeof(objentry),1,arfd); 425 if( (objentry.n_type & N_EXT) 426 && ((objentry.n_type & ~N_EXT) || objentry.n_value) 427 && eqstr(objentry.n_un.n_name,s,nc)) 428 { 429 clarch(); 430 return(arfdate); 431 } 432 } 433 } 434 435 else if( eqstr(arfname, s, nc)) 436 { 437 clarch(); 438 return(arfdate); 439 } 440 } 441 442 clarch(); 443 return( 0L); 444 } 445 446 447 clarch() 448 { 449 fclose( arfd ); 450 } 451 452 453 openarch(f) 454 register char *f; 455 { 456 #ifdef ASCARCH 457 char magic[SARMAG]; 458 #endif 459 int word; 460 #include <sys/stat.h> 461 struct stat buf; 462 463 stat(f, &buf); 464 arlen = buf.st_size; 465 466 arfd = fopen(f, "r"); 467 if(arfd == NULL) 468 fatal1("cannot open %s", f); 469 470 fread( (char *) &word, sizeof(word), 1, arfd); 471 #ifdef ASCARCH 472 fseek(arfd, 0L, 0); 473 fread(magic, SARMAG, 1, arfd); 474 arpos = SARMAG; 475 if( ! eqstr(magic, ARMAG, SARMAG) ) 476 #else 477 arpos = sizeof(word); 478 if(word != ARMAG) 479 #endif 480 fatal1("%s is not an archive", f); 481 482 arflen = 0; 483 } 484 485 486 487 getarch() 488 { 489 struct ar_hdr arhead; 490 long atol(); 491 492 arpos += (arflen + 1) & ~1L; /* round archived file length up to even */ 493 if(arpos >= arlen) 494 return(0); 495 fseek(arfd, arpos, 0); 496 497 fread( (char *) &arhead, sizeof(arhead), 1, arfd); 498 arpos += sizeof(arhead); 499 #ifdef ASCARCH 500 arflen = atol(arhead.ar_size); 501 arfdate = atol(arhead.ar_date); 502 #else 503 arflen = arhead.ar_size; 504 arfdate = arhead.ar_date; 505 #endif 506 strncpy(arfname, arhead.ar_name, sizeof(arhead.ar_name)); 507 return(1); 508 } 509 510 511 getobj() 512 { 513 long int skip; 514 515 fread( (char *) &objhead, sizeof(objhead), 1, arfd); 516 if (N_BADMAG(objhead)) 517 fatal1("%s is not an object module", arfname); 518 skip = objhead.a_text + objhead.a_data; 519 #if defined(vax) || defined(sun) 520 skip += objhead.a_trsize + objhead.a_drsize; 521 #else 522 if(! objhead.a_flag ) 523 skip *= 2; 524 #endif 525 fseek(arfd, skip, 1); 526 } 527 528 529 eqstr(a,b,n) 530 register char *a, *b; 531 int n; 532 { 533 register int i; 534 for(i = 0 ; i < n ; ++i) 535 if(*a++ != *b++) 536 return(NO); 537 return(YES); 538 } 539