xref: /plan9/sys/src/ape/cmd/make/files.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
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