1 /* POSIX DEPENDENT PROCEDURES */
2 #include "defs.h"
3 #include <sys/stat.h>
4 #include <ar.h>
5
6 #define NAMESPERBLOCK 32
7
8 /* DEFAULT RULES FOR POSIX */
9
10 char *dfltmacro[] =
11 {
12 ".SUFFIXES : .o .c .y .l .a .sh .f",
13 "MAKE=make",
14 "AR=ar",
15 "ARFLAGS=rv",
16 "YACC=yacc",
17 "YFLAGS=",
18 "LEX=lex",
19 "LFLAGS=",
20 "LDFLAGS=",
21 "CC=c89",
22 "CFLAGS=-O",
23 "FC=fort77",
24 "FFLAGS=-O 1",
25 0 };
26
27 char *dfltpat[] =
28 {
29 "%.o : %.c",
30 "\t$(CC) $(CFLAGS) -c $<",
31
32 "%.o : %.y",
33 "\t$(YACC) $(YFLAGS) $<",
34 "\t$(CC) $(CFLAGS) -c y.tab.c",
35 "\trm y.tab.c",
36 "\tmv y.tab.o $@",
37
38 "%.o : %.l",
39 "\t$(LEX) $(LFLAGS) $<",
40 "\t$(CC) $(CFLAGS) -c lex.yy.c",
41 "\trm lex.yy.c",
42 "\tmv lex.yy.o $@",
43
44 "%.c : %.y",
45 "\t$(YACC) $(YFLAGS) $<",
46 "\tmv y.tab.c $@",
47
48 "%.c : %.l",
49 "\t$(LEX) $(LFLAGS) $<",
50 "\tmv lex.yy.c $@",
51
52 "% : %.o",
53 "\t$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $<",
54
55 "% : %.c",
56 "\t$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $<",
57
58 0 };
59
60
61
62 char *dfltsuff[] =
63 {
64 ".SUFFIXES : .o .c .y .l .a .sh .f",
65 ".c.o :",
66 "\t$(CC) $(CFLAGS) -c $<",
67
68 ".f.o :",
69 "\t$(FC) $(FFLAGS) -c $<",
70
71 ".y.o :",
72 "\t$(YACC) $(YFLAGS) $<",
73 "\t$(CC) $(CFLAGS) -c y.tab.c",
74 "\trm -f y.tab.c",
75 "\tmv y.tab.o $@",
76
77 ".l.o :",
78 "\t$(LEX) $(LFLAGS) $<",
79 "\t$(CC) $(CFLAGS) -c lex.yy.c",
80 "\trm -f 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 ".c.a:",
92 "\t$(CC) -c $(CFLAGS) $<",
93 "\t$(AR) $(ARFLAGS) $@ $*.o",
94 "\trm -f $*.o",
95
96 ".f.a:",
97 "\t$(FC) -c $(FFLAGS) $<",
98 "\t$(AR) $(ARFLAGS) $@ $*.o",
99 "\trm -f $*.o",
100
101 ".c:",
102 "\t$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $<",
103
104 ".f:",
105 "\t$(FC) $(FFLAGS) $(LDFLAGS) -o $@ $<",
106
107 ".sh:",
108 "\tcp $< $@",
109 "\tchmod a+x $@",
110
111 0 };
112
113
114 static struct dirhd *opdir(char *, int);
115 static void cldir(struct dirhd *, int);
116 static int amatch(char *, char *);
117 static int umatch(char *, char *);
118 static void clarch(void);
119 static int openarch(char *);
120 static int getarch(void);
121
122 time_t
exists(char * filename)123 exists(char *filename)
124 {
125 struct stat buf;
126 char *s;
127
128 for(s = filename ; *s!='\0' && *s!='(' && *s!=')' ; ++s)
129 ;
130
131 if(*s != '\0')
132 return lookarch(filename);
133
134 if(stat(filename,&buf) < 0)
135 return 0;
136 else return buf.st_mtime;
137 }
138
139
140 time_t
prestime(void)141 prestime(void)
142 {
143 time_t t;
144 time(&t);
145 return t;
146 }
147
148 static char nmtemp[MAXNAMLEN+1]; /* guarantees a null after the name */
149 static char *tempend = nmtemp + MAXNAMLEN;
150
151
152
153 depblkp
srchdir(char * pat,int mkchain,depblkp nextdbl)154 srchdir(char *pat, int mkchain, depblkp nextdbl)
155 {
156 DIR *dirf;
157 struct dirhd *dirptr;
158 char *dirname, *dirpref, *endir, *filepat, *p, temp[100];
159 char fullname[100];
160 nameblkp q;
161 depblkp thisdbl;
162 struct pattern *patp;
163
164 struct dirent *dptr;
165
166 thisdbl = 0;
167
168 if(mkchain == NO)
169 for(patp=firstpat ; patp ; patp = patp->nxtpattern)
170 if(equal(pat, patp->patval)) return 0;
171
172 patp = ALLOC(pattern);
173 patp->nxtpattern = firstpat;
174 firstpat = patp;
175 patp->patval = copys(pat);
176
177 endir = 0;
178
179 for(p=pat; *p!='\0'; ++p)
180 if(*p=='/') endir = p;
181
182 if(endir==0)
183 {
184 dirname = ".";
185 dirpref = "";
186 filepat = pat;
187 }
188 else {
189 dirname = pat;
190 *endir = '\0';
191 dirpref = concat(dirname, "/", temp);
192 filepat = endir+1;
193 }
194
195 dirptr = opdir(dirname,YES);
196 dirf = dirptr->dirfc;
197
198 for( dptr = readdir(dirf) ; dptr ; dptr = readdir(dirf) )
199 {
200 char *p1, *p2;
201 p1 = dptr->d_name;
202 p2 = nmtemp;
203 while( (p2<tempend) && (*p2++ = *p1++)!='\0')
204 ;
205 if( amatch(nmtemp,filepat) )
206 {
207 concat(dirpref,nmtemp,fullname);
208 if( (q=srchname(fullname)) ==0)
209 q = makename(copys(fullname));
210 if(mkchain)
211 {
212 thisdbl = ALLOC(depblock);
213 thisdbl->nxtdepblock = nextdbl;
214 thisdbl->depname = q;
215 nextdbl = thisdbl;
216 }
217 }
218 }
219
220
221 if(endir)
222 *endir = '/';
223
224 cldir(dirptr, YES);
225
226 return thisdbl;
227 }
228
229 static struct dirhd *
opdir(char * dirname,int stopifbad)230 opdir(char *dirname, int stopifbad)
231 {
232 struct dirhd *od;
233
234 for(od = firstod; od; od = od->nxtdirhd)
235 if(equal(dirname, od->dirn) )
236 break;
237
238 if(od == NULL)
239 {
240 ++nopdir;
241 od = ALLOC(dirhd);
242 od->nxtdirhd = firstod;
243 firstod = od;
244 od->dirn = copys(dirname);
245 }
246
247 if(od->dirfc==NULL && (od->dirfc = opendir(dirname)) == NULL && stopifbad)
248 {
249 fprintf(stderr, "Directory %s: ", dirname);
250 fatal("Cannot open");
251 }
252
253 return od;
254 }
255
256
257 static void
cldir(struct dirhd * dp,int used)258 cldir(struct dirhd *dp, int used)
259 {
260 if(nopdir >= MAXDIR)
261 {
262 closedir(dp->dirfc);
263 dp->dirfc = NULL;
264 }
265 else if(used)
266 rewinddir(dp->dirfc); /* start over at the beginning */
267 }
268
269 /* stolen from glob through find */
270
271 static int
amatch(char * s,char * p)272 amatch(char *s, char *p)
273 {
274 int cc, scc, k;
275 int c, lc;
276
277 scc = *s;
278 lc = 077777;
279 switch (c = *p) {
280
281 case '[':
282 k = 0;
283 while (cc = *++p) {
284 switch (cc) {
285
286 case ']':
287 if (k)
288 return amatch(++s, ++p);
289 else
290 return 0;
291
292 case '-':
293 k |= (lc <= scc) & (scc <= (cc=p[1]) ) ;
294 }
295 if (scc==(lc=cc)) k++;
296 }
297 return 0;
298
299 case '?':
300 caseq:
301 if(scc) return amatch(++s, ++p);
302 return 0;
303 case '*':
304 return umatch(s, ++p);
305 case 0:
306 return !scc;
307 }
308 if (c==scc) goto caseq;
309 return 0;
310 }
311
312 static int
umatch(char * s,char * p)313 umatch(char *s, char *p)
314 {
315 if(*p==0) return 1;
316 while(*s)
317 if (amatch(s++,p)) return 1;
318 return 0;
319 }
320
321 #ifdef METERFILE
322 #include <pwd.h>
323 int meteron = 0; /* default: metering off */
324
meter(char * file)325 extern void meter(char *file)
326 {
327 time_t tvec;
328 char *p;
329 FILE * mout;
330 struct passwd *pwd;
331
332 if(file==0 || meteron==0) return;
333
334 pwd = getpwuid(getuid());
335
336 time(&tvec);
337
338 if( mout = fopen(file,"a") )
339 {
340 p = ctime(&tvec);
341 p[16] = '\0';
342 fprintf(mout, "User %s, %s\n", pwd->pw_name, p+4);
343 fclose(mout);
344 }
345 }
346 #endif
347
348
349 /* look inside archives for notation a(b)
350 a(b) is file member b in archive a
351 */
352
353 static long arflen;
354 static long arfdate;
355 static char arfname[16];
356 FILE *arfd;
357 long int arpos, arlen;
358
359 time_t
lookarch(char * filename)360 lookarch(char *filename)
361 {
362 char *p, *q, *send, s[15], pad;
363 int i, nc, nsym;
364
365 for(p = filename; *p!= '(' ; ++p)
366 ;
367
368 *p = '\0';
369 if( ! openarch(filename) )
370 {
371 *p = '(';
372 return 0L;
373 }
374 *p++ = '(';
375 nc = 14;
376 pad = ' ';
377
378 send = s + nc;
379 for( q = s ; q<send && *p!='\0' && *p!=')' ; *q++ = *p++ )
380 ;
381 if(p[0]==')' && p[1]!='\0') /* forbid stuff after the paren */
382 {
383 clarch();
384 return 0L;
385 }
386 while(q < send)
387 *q++ = pad;
388 while(getarch())
389 {
390 if( !strncmp(arfname, s, nc))
391 {
392 clarch();
393 /*TEMP fprintf(stderr, "found archive member %14s, time=%d\n", s, arfdate); */
394 return arfdate;
395 }
396 }
397
398 clarch();
399 return 0L;
400 }
401
402 static void
clarch(void)403 clarch(void)
404 {
405 fclose( arfd );
406 }
407
408 static int
openarch(char * f)409 openarch(char *f)
410 {
411 char magic[SARMAG];
412 int word;
413 struct stat buf;
414 nameblkp p;
415
416 stat(f, &buf);
417 arlen = buf.st_size;
418
419 arfd = fopen(f, "r");
420 if(arfd == NULL)
421 return NO;
422 /* fatal1("cannot open %s", f); */
423
424 fread( (char *) &word, sizeof(word), 1, arfd);
425
426 fseek(arfd, 0L, 0);
427 fread(magic, SARMAG, 1, arfd);
428 arpos = SARMAG;
429 if( strncmp(magic, ARMAG, SARMAG) )
430 fatal1("%s is not an archive", f);
431
432 if( !(p = srchname(f)) )
433 p = makename( copys(f) );
434 p->isarch = YES;
435 arflen = 0;
436 return YES;
437 }
438
439
440 static int
getarch(void)441 getarch(void)
442 {
443 struct ar_hdr arhead;
444
445 arpos += (arflen + 1) & ~1L; /* round archived file length up to even */
446 if(arpos >= arlen)
447 return 0;
448 fseek(arfd, arpos, 0);
449
450 fread( (char *) &arhead, sizeof(arhead), 1, arfd);
451 arpos += sizeof(arhead);
452 arflen = atol(arhead.ar_size);
453 arfdate = atol(arhead.ar_date);
454 strncpy(arfname, arhead.ar_name, sizeof(arhead.ar_name));
455 return 1;
456 }
457
458 /* find the directory containing name.
459 read it into the hash table if it hasn't been used before or if
460 if might have changed since last reference
461 */
462
463 void
dirsrch(char * name)464 dirsrch(char *name)
465 {
466 DIR *dirf;
467 struct dirhd *dirp;
468 time_t dirt, objt;
469 int dirused, hasparen;
470 char *dirname, *lastslash;
471 char *fullname, *filepart, *fileend, *s;
472 struct dirent *dptr;
473
474 lastslash = NULL;
475 hasparen = NO;
476
477 for(s=name; *s; ++s)
478 if(*s == '/')
479 lastslash = s;
480 else if(*s=='(' || *s==')')
481 hasparen = YES;
482
483 if(hasparen)
484 {
485 if(objt = lookarch(name))
486 makename(name)->modtime = objt;
487 return;
488 }
489
490 if(lastslash)
491 {
492 dirname = name;
493 *lastslash = '\0';
494 }
495 else
496 dirname = ".";
497
498 dirused = NO;
499 dirp = opdir(dirname, NO);
500 dirf = dirp->dirfc;
501 if(dirp->dirok || !dirf)
502 goto ret;
503 dirt = exists(dirname);
504 if(dirp->dirtime == dirt)
505 goto ret;
506
507 dirp->dirok = YES;
508 dirp->dirtime = dirt;
509 dirused = YES;
510
511 /* allocate buffer to hold full file name */
512 if(lastslash)
513 {
514 fullname = (char *) ckalloc(strlen(dirname)+MAXNAMLEN+2);
515 concat(dirname, "/", fullname);
516 filepart = fullname + strlen(fullname);
517 }
518 else
519 filepart = fullname = (char *) ckalloc(MAXNAMLEN+1);
520
521
522 fileend = filepart + MAXNAMLEN;
523 *fileend = '\0';
524 for(dptr = readdir(dirf) ; dptr ; dptr = readdir(dirf) )
525 {
526 char *p1, *p2;
527 p1 = dptr->d_name;
528 p2 = filepart;
529 while( (p2<fileend) && (*p2++ = *p1++)!='\0')
530 ;
531 if( ! srchname(fullname) )
532 (void) makename(copys(fullname));
533 }
534
535 free(fullname);
536
537 ret:
538 cldir(dirp, dirused);
539 if(lastslash)
540 *lastslash = '/';
541 }
542
543
544
545 void
baddirs(void)546 baddirs(void)
547 {
548 struct dirhd *od;
549
550 for(od = firstod; od; od = od->nxtdirhd)
551 od->dirok = NO;
552 }
553