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