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
exists(pname)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
prestime()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
srchdir(pat,mkchain,nextdbl)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
amatch(s,p)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
umatch(s,p)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
meter(file)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
lookarch(filename)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
clarch()506 clarch()
507 {
508 fclose( arfd );
509 }
510
511
openarch(f)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
getarch()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
getobj()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
eqstr(a,b,n)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
findfl(name)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
execat(s1,s2,si)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 */
fixname(s,d)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