xref: /netbsd-src/usr.bin/make/meta.c (revision e89934bbf778a6d6d6894877c4da59d0c7835b0f)
1 /*      $NetBSD: meta.c,v 1.67 2016/08/17 15:52:42 sjg Exp $ */
2 
3 /*
4  * Implement 'meta' mode.
5  * Adapted from John Birrell's patches to FreeBSD make.
6  * --sjg
7  */
8 /*
9  * Copyright (c) 2009-2016, Juniper Networks, Inc.
10  * Portions Copyright (c) 2009, John Birrell.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions and the following disclaimer.
17  * 2. Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the distribution.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 #if defined(USE_META)
34 
35 #ifdef HAVE_CONFIG_H
36 # include "config.h"
37 #endif
38 #include <sys/stat.h>
39 #include <sys/ioctl.h>
40 #include <libgen.h>
41 #include <errno.h>
42 #if !defined(HAVE_CONFIG_H) || defined(HAVE_ERR_H)
43 #include <err.h>
44 #endif
45 
46 #include "make.h"
47 #include "job.h"
48 
49 #ifdef HAVE_FILEMON_H
50 # include <filemon.h>
51 #endif
52 #if !defined(USE_FILEMON) && defined(FILEMON_SET_FD)
53 # define USE_FILEMON
54 #endif
55 
56 static BuildMon Mybm;			/* for compat */
57 static Lst metaBailiwick;		/* our scope of control */
58 static char *metaBailiwickStr;		/* string storage for the list */
59 static Lst metaIgnorePaths;		/* paths we deliberately ignore */
60 static char *metaIgnorePathsStr;	/* string storage for the list */
61 
62 #ifndef MAKE_META_IGNORE_PATHS
63 #define MAKE_META_IGNORE_PATHS ".MAKE.META.IGNORE_PATHS"
64 #endif
65 #ifndef MAKE_META_IGNORE_PATTERNS
66 #define MAKE_META_IGNORE_PATTERNS ".MAKE.META.IGNORE_PATTERNS"
67 #endif
68 #ifndef MAKE_META_IGNORE_FILTER
69 #define MAKE_META_IGNORE_FILTER ".MAKE.META.IGNORE_FILTER"
70 #endif
71 
72 Boolean useMeta = FALSE;
73 static Boolean useFilemon = FALSE;
74 static Boolean writeMeta = FALSE;
75 static Boolean metaMissing = FALSE;	/* oodate if missing */
76 static Boolean filemonMissing = FALSE;	/* oodate if missing */
77 static Boolean metaEnv = FALSE;		/* don't save env unless asked */
78 static Boolean metaVerbose = FALSE;
79 static Boolean metaIgnoreCMDs = FALSE;	/* ignore CMDs in .meta files */
80 static Boolean metaIgnorePatterns = FALSE; /* do we need to do pattern matches */
81 static Boolean metaIgnoreFilter = FALSE;   /* do we have more complex filtering? */
82 static Boolean metaCurdirOk = FALSE;	/* write .meta in .CURDIR Ok? */
83 static Boolean metaSilent = FALSE;	/* if we have a .meta be SILENT */
84 
85 extern Boolean forceJobs;
86 extern Boolean comatMake;
87 extern char    **environ;
88 
89 #define	MAKE_META_PREFIX	".MAKE.META.PREFIX"
90 
91 #ifndef N2U
92 # define N2U(n, u)   (((n) + ((u) - 1)) / (u))
93 #endif
94 #ifndef ROUNDUP
95 # define ROUNDUP(n, u)   (N2U((n), (u)) * (u))
96 #endif
97 
98 #if !defined(HAVE_STRSEP)
99 # define strsep(s, d) stresep((s), (d), 0)
100 #endif
101 
102 /*
103  * Filemon is a kernel module which snoops certain syscalls.
104  *
105  * C chdir
106  * E exec
107  * F [v]fork
108  * L [sym]link
109  * M rename
110  * R read
111  * W write
112  * S stat
113  *
114  * See meta_oodate below - we mainly care about 'E' and 'R'.
115  *
116  * We can still use meta mode without filemon, but
117  * the benefits are more limited.
118  */
119 #ifdef USE_FILEMON
120 # ifndef _PATH_FILEMON
121 #   define _PATH_FILEMON "/dev/filemon"
122 # endif
123 
124 /*
125  * Open the filemon device.
126  */
127 static void
128 filemon_open(BuildMon *pbm)
129 {
130     int retry;
131 
132     pbm->mon_fd = pbm->filemon_fd = -1;
133     if (!useFilemon)
134 	return;
135 
136     for (retry = 5; retry >= 0; retry--) {
137 	if ((pbm->filemon_fd = open(_PATH_FILEMON, O_RDWR)) >= 0)
138 	    break;
139     }
140 
141     if (pbm->filemon_fd < 0) {
142 	useFilemon = FALSE;
143 	warn("Could not open %s", _PATH_FILEMON);
144 	return;
145     }
146 
147     /*
148      * We use a file outside of '.'
149      * to avoid a FreeBSD kernel bug where unlink invalidates
150      * cwd causing getcwd to do a lot more work.
151      * We only care about the descriptor.
152      */
153     pbm->mon_fd = mkTempFile("filemon.XXXXXX", NULL);
154     if (ioctl(pbm->filemon_fd, FILEMON_SET_FD, &pbm->mon_fd) < 0) {
155 	err(1, "Could not set filemon file descriptor!");
156     }
157     /* we don't need these once we exec */
158     (void)fcntl(pbm->mon_fd, F_SETFD, FD_CLOEXEC);
159     (void)fcntl(pbm->filemon_fd, F_SETFD, FD_CLOEXEC);
160 }
161 
162 /*
163  * Read the build monitor output file and write records to the target's
164  * metadata file.
165  */
166 static int
167 filemon_read(FILE *mfp, int fd)
168 {
169     char buf[BUFSIZ];
170     int n;
171     int error;
172 
173     /* Check if we're not writing to a meta data file.*/
174     if (mfp == NULL) {
175 	if (fd >= 0)
176 	    close(fd);			/* not interested */
177 	return 0;
178     }
179     /* rewind */
180     (void)lseek(fd, (off_t)0, SEEK_SET);
181 
182     error = 0;
183     fprintf(mfp, "\n-- filemon acquired metadata --\n");
184 
185     while ((n = read(fd, buf, sizeof(buf))) > 0) {
186 	if ((int)fwrite(buf, 1, n, mfp) < n)
187 	    error = EIO;
188     }
189     fflush(mfp);
190     if (close(fd) < 0)
191 	error = errno;
192     return error;
193 }
194 #endif
195 
196 /*
197  * when realpath() fails,
198  * we use this, to clean up ./ and ../
199  */
200 static void
201 eat_dots(char *buf, size_t bufsz, int dots)
202 {
203     char *cp;
204     char *cp2;
205     const char *eat;
206     size_t eatlen;
207 
208     switch (dots) {
209     case 1:
210 	eat = "/./";
211 	eatlen = 2;
212 	break;
213     case 2:
214 	eat = "/../";
215 	eatlen = 3;
216 	break;
217     default:
218 	return;
219     }
220 
221     do {
222 	cp = strstr(buf, eat);
223 	if (cp) {
224 	    cp2 = cp + eatlen;
225 	    if (dots == 2 && cp > buf) {
226 		do {
227 		    cp--;
228 		} while (cp > buf && *cp != '/');
229 	    }
230 	    if (*cp == '/') {
231 		strlcpy(cp, cp2, bufsz - (cp - buf));
232 	    } else {
233 		return;			/* can't happen? */
234 	    }
235 	}
236     } while (cp);
237 }
238 
239 static char *
240 meta_name(struct GNode *gn, char *mname, size_t mnamelen,
241 	  const char *dname,
242 	  const char *tname,
243 	  const char *cwd)
244 {
245     char buf[MAXPATHLEN];
246     char *rp;
247     char *cp;
248     char *tp;
249 
250     /*
251      * Weed out relative paths from the target file name.
252      * We have to be careful though since if target is a
253      * symlink, the result will be unstable.
254      * So we use realpath() just to get the dirname, and leave the
255      * basename as given to us.
256      */
257     if ((cp = strrchr(tname, '/'))) {
258 	if (cached_realpath(tname, buf)) {
259 	    if ((rp = strrchr(buf, '/'))) {
260 		rp++;
261 		cp++;
262 		if (strcmp(cp, rp) != 0)
263 		    strlcpy(rp, cp, sizeof(buf) - (rp - buf));
264 	    }
265 	    tname = buf;
266 	} else {
267 	    /*
268 	     * We likely have a directory which is about to be made.
269 	     * We pretend realpath() succeeded, to have a chance
270 	     * of generating the same meta file name that we will
271 	     * next time through.
272 	     */
273 	    if (tname[0] == '/') {
274 		strlcpy(buf, tname, sizeof(buf));
275 	    } else {
276 		snprintf(buf, sizeof(buf), "%s/%s", cwd, tname);
277 	    }
278 	    eat_dots(buf, sizeof(buf), 1);	/* ./ */
279 	    eat_dots(buf, sizeof(buf), 2);	/* ../ */
280 	    tname = buf;
281 	}
282     }
283     /* on some systems dirname may modify its arg */
284     tp = bmake_strdup(tname);
285     if (strcmp(dname, dirname(tp)) == 0)
286 	snprintf(mname, mnamelen, "%s.meta", tname);
287     else {
288 	snprintf(mname, mnamelen, "%s/%s.meta", dname, tname);
289 
290 	/*
291 	 * Replace path separators in the file name after the
292 	 * current object directory path.
293 	 */
294 	cp = mname + strlen(dname) + 1;
295 
296 	while (*cp != '\0') {
297 	    if (*cp == '/')
298 		*cp = '_';
299 	    cp++;
300 	}
301     }
302     free(tp);
303     return (mname);
304 }
305 
306 /*
307  * Return true if running ${.MAKE}
308  * Bypassed if target is flagged .MAKE
309  */
310 static int
311 is_submake(void *cmdp, void *gnp)
312 {
313     static char *p_make = NULL;
314     static int p_len;
315     char  *cmd = cmdp;
316     GNode *gn = gnp;
317     char *mp = NULL;
318     char *cp;
319     char *cp2;
320     int rc = 0;				/* keep looking */
321 
322     if (!p_make) {
323 	p_make = Var_Value(".MAKE", gn, &cp);
324 	p_len = strlen(p_make);
325     }
326     cp = strchr(cmd, '$');
327     if ((cp)) {
328 	mp = Var_Subst(NULL, cmd, gn, VARF_WANTRES);
329 	cmd = mp;
330     }
331     cp2 = strstr(cmd, p_make);
332     if ((cp2)) {
333 	switch (cp2[p_len]) {
334 	case '\0':
335 	case ' ':
336 	case '\t':
337 	case '\n':
338 	    rc = 1;
339 	    break;
340 	}
341 	if (cp2 > cmd && rc > 0) {
342 	    switch (cp2[-1]) {
343 	    case ' ':
344 	    case '\t':
345 	    case '\n':
346 		break;
347 	    default:
348 		rc = 0;			/* no match */
349 		break;
350 	    }
351 	}
352     }
353     free(mp);
354     return (rc);
355 }
356 
357 typedef struct meta_file_s {
358     FILE *fp;
359     GNode *gn;
360 } meta_file_t;
361 
362 static int
363 printCMD(void *cmdp, void *mfpp)
364 {
365     meta_file_t *mfp = mfpp;
366     char *cmd = cmdp;
367     char *cp = NULL;
368 
369     if (strchr(cmd, '$')) {
370 	cmd = cp = Var_Subst(NULL, cmd, mfp->gn, VARF_WANTRES);
371     }
372     fprintf(mfp->fp, "CMD %s\n", cmd);
373     free(cp);
374     return 0;
375 }
376 
377 /*
378  * Certain node types never get a .meta file
379  */
380 #define SKIP_META_TYPE(_type) do { \
381     if ((gn->type & __CONCAT(OP_, _type))) {	\
382 	if (verbose) { \
383 	    fprintf(debug_file, "Skipping meta for %s: .%s\n", \
384 		    gn->name, __STRING(_type));		       \
385 	} \
386 	return FALSE; \
387     } \
388 } while (0)
389 
390 
391 /*
392  * Do we need/want a .meta file ?
393  */
394 static Boolean
395 meta_needed(GNode *gn, const char *dname, const char *tname,
396 	     char *objdir, int verbose)
397 {
398     struct stat fs;
399 
400     if (verbose)
401 	verbose = DEBUG(META);
402 
403     /* This may be a phony node which we don't want meta data for... */
404     /* Skip .meta for .BEGIN, .END, .ERROR etc as well. */
405     /* Or it may be explicitly flagged as .NOMETA */
406     SKIP_META_TYPE(NOMETA);
407     /* Unless it is explicitly flagged as .META */
408     if (!(gn->type & OP_META)) {
409 	SKIP_META_TYPE(PHONY);
410 	SKIP_META_TYPE(SPECIAL);
411 	SKIP_META_TYPE(MAKE);
412     }
413 
414     /* Check if there are no commands to execute. */
415     if (Lst_IsEmpty(gn->commands)) {
416 	if (verbose)
417 	    fprintf(debug_file, "Skipping meta for %s: no commands\n",
418 		    gn->name);
419 	return FALSE;
420     }
421     if ((gn->type & (OP_META|OP_SUBMAKE)) == OP_SUBMAKE) {
422 	/* OP_SUBMAKE is a bit too aggressive */
423 	if (Lst_ForEach(gn->commands, is_submake, gn)) {
424 	    if (DEBUG(META))
425 		fprintf(debug_file, "Skipping meta for %s: .SUBMAKE\n",
426 			gn->name);
427 	    return FALSE;
428 	}
429     }
430 
431     /* The object directory may not exist. Check it.. */
432     if (cached_stat(dname, &fs) != 0) {
433 	if (verbose)
434 	    fprintf(debug_file, "Skipping meta for %s: no .OBJDIR\n",
435 		    gn->name);
436 	return FALSE;
437     }
438 
439     /* make sure these are canonical */
440     if (cached_realpath(dname, objdir))
441 	dname = objdir;
442 
443     /* If we aren't in the object directory, don't create a meta file. */
444     if (!metaCurdirOk && strcmp(curdir, dname) == 0) {
445 	if (verbose)
446 	    fprintf(debug_file, "Skipping meta for %s: .OBJDIR == .CURDIR\n",
447 		    gn->name);
448 	return FALSE;
449     }
450     return TRUE;
451 }
452 
453 
454 static FILE *
455 meta_create(BuildMon *pbm, GNode *gn)
456 {
457     meta_file_t mf;
458     char buf[MAXPATHLEN];
459     char objdir[MAXPATHLEN];
460     char **ptr;
461     const char *dname;
462     const char *tname;
463     char *fname;
464     const char *cp;
465     char *p[4];				/* >= possible uses */
466     int i;
467 
468     mf.fp = NULL;
469     i = 0;
470 
471     dname = Var_Value(".OBJDIR", gn, &p[i++]);
472     tname = Var_Value(TARGET, gn, &p[i++]);
473 
474     /* if this succeeds objdir is realpath of dname */
475     if (!meta_needed(gn, dname, tname, objdir, TRUE))
476 	goto out;
477     dname = objdir;
478 
479     if (metaVerbose) {
480 	char *mp;
481 
482 	/* Describe the target we are building */
483 	mp = Var_Subst(NULL, "${" MAKE_META_PREFIX "}", gn, VARF_WANTRES);
484 	if (*mp)
485 	    fprintf(stdout, "%s\n", mp);
486 	free(mp);
487     }
488     /* Get the basename of the target */
489     if ((cp = strrchr(tname, '/')) == NULL) {
490 	cp = tname;
491     } else {
492 	cp++;
493     }
494 
495     fflush(stdout);
496 
497     if (!writeMeta)
498 	/* Don't create meta data. */
499 	goto out;
500 
501     fname = meta_name(gn, pbm->meta_fname, sizeof(pbm->meta_fname),
502 		      dname, tname, objdir);
503 
504 #ifdef DEBUG_META_MODE
505     if (DEBUG(META))
506 	fprintf(debug_file, "meta_create: %s\n", fname);
507 #endif
508 
509     if ((mf.fp = fopen(fname, "w")) == NULL)
510 	err(1, "Could not open meta file '%s'", fname);
511 
512     fprintf(mf.fp, "# Meta data file %s\n", fname);
513 
514     mf.gn = gn;
515 
516     Lst_ForEach(gn->commands, printCMD, &mf);
517 
518     fprintf(mf.fp, "CWD %s\n", getcwd(buf, sizeof(buf)));
519     fprintf(mf.fp, "TARGET %s\n", tname);
520 
521     if (metaEnv) {
522 	for (ptr = environ; *ptr != NULL; ptr++)
523 	    fprintf(mf.fp, "ENV %s\n", *ptr);
524     }
525 
526     fprintf(mf.fp, "-- command output --\n");
527     fflush(mf.fp);
528 
529     Var_Append(".MAKE.META.FILES", fname, VAR_GLOBAL);
530     Var_Append(".MAKE.META.CREATED", fname, VAR_GLOBAL);
531 
532     gn->type |= OP_META;		/* in case anyone wants to know */
533     if (metaSilent) {
534 	    gn->type |= OP_SILENT;
535     }
536  out:
537     for (i--; i >= 0; i--) {
538 	free(p[i]);
539     }
540 
541     return (mf.fp);
542 }
543 
544 static Boolean
545 boolValue(char *s)
546 {
547     switch(*s) {
548     case '0':
549     case 'N':
550     case 'n':
551     case 'F':
552     case 'f':
553 	return FALSE;
554     }
555     return TRUE;
556 }
557 
558 /*
559  * Initialization we need before reading makefiles.
560  */
561 void
562 meta_init(void)
563 {
564 #ifdef USE_FILEMON
565 	/* this allows makefiles to test if we have filemon support */
566 	Var_Set(".MAKE.PATH_FILEMON", _PATH_FILEMON, VAR_GLOBAL, 0);
567 #endif
568 }
569 
570 
571 #define get_mode_bf(bf, token) \
572     if ((cp = strstr(make_mode, token))) \
573 	bf = boolValue(&cp[sizeof(token) - 1])
574 
575 /*
576  * Initialization we need after reading makefiles.
577  */
578 void
579 meta_mode_init(const char *make_mode)
580 {
581     static int once = 0;
582     char *cp;
583 
584     useMeta = TRUE;
585     useFilemon = TRUE;
586     writeMeta = TRUE;
587 
588     if (make_mode) {
589 	if (strstr(make_mode, "env"))
590 	    metaEnv = TRUE;
591 	if (strstr(make_mode, "verb"))
592 	    metaVerbose = TRUE;
593 	if (strstr(make_mode, "read"))
594 	    writeMeta = FALSE;
595 	if (strstr(make_mode, "nofilemon"))
596 	    useFilemon = FALSE;
597 	if (strstr(make_mode, "ignore-cmd"))
598 	    metaIgnoreCMDs = TRUE;
599 	if (useFilemon)
600 	    get_mode_bf(filemonMissing, "missing-filemon=");
601 	get_mode_bf(metaCurdirOk, "curdirok=");
602 	get_mode_bf(metaMissing, "missing-meta=");
603 	get_mode_bf(metaSilent, "silent=");
604     }
605     if (metaVerbose && !Var_Exists(MAKE_META_PREFIX, VAR_GLOBAL)) {
606 	/*
607 	 * The default value for MAKE_META_PREFIX
608 	 * prints the absolute path of the target.
609 	 * This works be cause :H will generate '.' if there is no /
610 	 * and :tA will resolve that to cwd.
611 	 */
612 	Var_Set(MAKE_META_PREFIX, "Building ${.TARGET:H:tA}/${.TARGET:T}", VAR_GLOBAL, 0);
613     }
614     if (once)
615 	return;
616     once = 1;
617     memset(&Mybm, 0, sizeof(Mybm));
618     /*
619      * We consider ourselves master of all within ${.MAKE.META.BAILIWICK}
620      */
621     metaBailiwick = Lst_Init(FALSE);
622     metaBailiwickStr = Var_Subst(NULL, "${.MAKE.META.BAILIWICK:O:u:tA}",
623 	VAR_GLOBAL, VARF_WANTRES);
624     if (metaBailiwickStr) {
625 	str2Lst_Append(metaBailiwick, metaBailiwickStr, NULL);
626     }
627     /*
628      * We ignore any paths that start with ${.MAKE.META.IGNORE_PATHS}
629      */
630     metaIgnorePaths = Lst_Init(FALSE);
631     Var_Append(MAKE_META_IGNORE_PATHS,
632 	       "/dev /etc /proc /tmp /var/run /var/tmp ${TMPDIR}", VAR_GLOBAL);
633     metaIgnorePathsStr = Var_Subst(NULL,
634 		   "${" MAKE_META_IGNORE_PATHS ":O:u:tA}", VAR_GLOBAL,
635 		   VARF_WANTRES);
636     if (metaIgnorePathsStr) {
637 	str2Lst_Append(metaIgnorePaths, metaIgnorePathsStr, NULL);
638     }
639 
640     /*
641      * We ignore any paths that match ${.MAKE.META.IGNORE_PATTERNS}
642      */
643     cp = NULL;
644     if (Var_Value(MAKE_META_IGNORE_PATTERNS, VAR_GLOBAL, &cp)) {
645 	metaIgnorePatterns = TRUE;
646 	free(cp);
647     }
648     cp = NULL;
649     if (Var_Value(MAKE_META_IGNORE_FILTER, VAR_GLOBAL, &cp)) {
650 	metaIgnoreFilter = TRUE;
651 	free(cp);
652     }
653 }
654 
655 /*
656  * In each case below we allow for job==NULL
657  */
658 void
659 meta_job_start(Job *job, GNode *gn)
660 {
661     BuildMon *pbm;
662 
663     if (job != NULL) {
664 	pbm = &job->bm;
665     } else {
666 	pbm = &Mybm;
667     }
668     pbm->mfp = meta_create(pbm, gn);
669 #ifdef USE_FILEMON_ONCE
670     /* compat mode we open the filemon dev once per command */
671     if (job == NULL)
672 	return;
673 #endif
674 #ifdef USE_FILEMON
675     if (pbm->mfp != NULL && useFilemon) {
676 	filemon_open(pbm);
677     } else {
678 	pbm->mon_fd = pbm->filemon_fd = -1;
679     }
680 #endif
681 }
682 
683 /*
684  * The child calls this before doing anything.
685  * It does not disturb our state.
686  */
687 void
688 meta_job_child(Job *job)
689 {
690 #ifdef USE_FILEMON
691     BuildMon *pbm;
692 
693     if (job != NULL) {
694 	pbm = &job->bm;
695     } else {
696 	pbm = &Mybm;
697     }
698     if (pbm->mfp != NULL) {
699 	close(fileno(pbm->mfp));
700 	if (useFilemon) {
701 	    pid_t pid;
702 
703 	    pid = getpid();
704 	    if (ioctl(pbm->filemon_fd, FILEMON_SET_PID, &pid) < 0) {
705 		err(1, "Could not set filemon pid!");
706 	    }
707 	}
708     }
709 #endif
710 }
711 
712 void
713 meta_job_error(Job *job, GNode *gn, int flags, int status)
714 {
715     char cwd[MAXPATHLEN];
716     BuildMon *pbm;
717 
718     if (job != NULL) {
719 	pbm = &job->bm;
720 	if (!gn)
721 	    gn = job->node;
722     } else {
723 	pbm = &Mybm;
724     }
725     if (pbm->mfp != NULL) {
726 	fprintf(pbm->mfp, "*** Error code %d%s\n",
727 		status,
728 		(flags & JOB_IGNERR) ?
729 		"(ignored)" : "");
730     }
731     if (gn) {
732 	Var_Set(".ERROR_TARGET", gn->path ? gn->path : gn->name, VAR_GLOBAL, 0);
733     }
734     getcwd(cwd, sizeof(cwd));
735     Var_Set(".ERROR_CWD", cwd, VAR_GLOBAL, 0);
736     if (pbm->meta_fname[0]) {
737 	Var_Set(".ERROR_META_FILE", pbm->meta_fname, VAR_GLOBAL, 0);
738     }
739     meta_job_finish(job);
740 }
741 
742 void
743 meta_job_output(Job *job, char *cp, const char *nl)
744 {
745     BuildMon *pbm;
746 
747     if (job != NULL) {
748 	pbm = &job->bm;
749     } else {
750 	pbm = &Mybm;
751     }
752     if (pbm->mfp != NULL) {
753 	if (metaVerbose) {
754 	    static char *meta_prefix = NULL;
755 	    static int meta_prefix_len;
756 
757 	    if (!meta_prefix) {
758 		char *cp2;
759 
760 		meta_prefix = Var_Subst(NULL, "${" MAKE_META_PREFIX "}",
761 					VAR_GLOBAL, VARF_WANTRES);
762 		if ((cp2 = strchr(meta_prefix, '$')))
763 		    meta_prefix_len = cp2 - meta_prefix;
764 		else
765 		    meta_prefix_len = strlen(meta_prefix);
766 	    }
767 	    if (strncmp(cp, meta_prefix, meta_prefix_len) == 0) {
768 		cp = strchr(cp+1, '\n');
769 		if (!cp++)
770 		    return;
771 	    }
772 	}
773 	fprintf(pbm->mfp, "%s%s", cp, nl);
774     }
775 }
776 
777 int
778 meta_cmd_finish(void *pbmp)
779 {
780     int error = 0;
781 #ifdef USE_FILEMON
782     BuildMon *pbm = pbmp;
783     int x;
784 
785     if (!pbm)
786 	pbm = &Mybm;
787 
788     if (pbm->filemon_fd >= 0) {
789 	if (close(pbm->filemon_fd) < 0)
790 	    error = errno;
791 	x = filemon_read(pbm->mfp, pbm->mon_fd);
792 	if (error == 0 && x != 0)
793 	    error = x;
794 	pbm->filemon_fd = pbm->mon_fd = -1;
795     }
796 #endif
797     return error;
798 }
799 
800 int
801 meta_job_finish(Job *job)
802 {
803     BuildMon *pbm;
804     int error = 0;
805     int x;
806 
807     if (job != NULL) {
808 	pbm = &job->bm;
809     } else {
810 	pbm = &Mybm;
811     }
812     if (pbm->mfp != NULL) {
813 	error = meta_cmd_finish(pbm);
814 	x = fclose(pbm->mfp);
815 	if (error == 0 && x != 0)
816 	    error = errno;
817 	pbm->mfp = NULL;
818 	pbm->meta_fname[0] = '\0';
819     }
820     return error;
821 }
822 
823 void
824 meta_finish(void)
825 {
826     Lst_Destroy(metaBailiwick, NULL);
827     free(metaBailiwickStr);
828     Lst_Destroy(metaIgnorePaths, NULL);
829     free(metaIgnorePathsStr);
830 }
831 
832 /*
833  * Fetch a full line from fp - growing bufp if needed
834  * Return length in bufp.
835  */
836 static int
837 fgetLine(char **bufp, size_t *szp, int o, FILE *fp)
838 {
839     char *buf = *bufp;
840     size_t bufsz = *szp;
841     struct stat fs;
842     int x;
843 
844     if (fgets(&buf[o], bufsz - o, fp) != NULL) {
845     check_newline:
846 	x = o + strlen(&buf[o]);
847 	if (buf[x - 1] == '\n')
848 	    return x;
849 	/*
850 	 * We need to grow the buffer.
851 	 * The meta file can give us a clue.
852 	 */
853 	if (fstat(fileno(fp), &fs) == 0) {
854 	    size_t newsz;
855 	    char *p;
856 
857 	    newsz = ROUNDUP((fs.st_size / 2), BUFSIZ);
858 	    if (newsz <= bufsz)
859 		newsz = ROUNDUP(fs.st_size, BUFSIZ);
860 	    if (DEBUG(META))
861 		fprintf(debug_file, "growing buffer %zu -> %zu\n",
862 			bufsz, newsz);
863 	    p = bmake_realloc(buf, newsz);
864 	    if (p) {
865 		*bufp = buf = p;
866 		*szp = bufsz = newsz;
867 		/* fetch the rest */
868 		if (!fgets(&buf[x], bufsz - x, fp))
869 		    return x;		/* truncated! */
870 		goto check_newline;
871 	    }
872 	}
873     }
874     return 0;
875 }
876 
877 /* Lst_ForEach wants 1 to stop search */
878 static int
879 prefix_match(void *p, void *q)
880 {
881     const char *prefix = p;
882     const char *path = q;
883     size_t n = strlen(prefix);
884 
885     return (0 == strncmp(path, prefix, n));
886 }
887 
888 /*
889  * looking for exact or prefix/ match to
890  * Lst_Find wants 0 to stop search
891  */
892 static int
893 path_match(const void *p, const void *q)
894 {
895     const char *prefix = q;
896     const char *path = p;
897     size_t n = strlen(prefix);
898     int rc;
899 
900     if ((rc = strncmp(path, prefix, n)) == 0) {
901 	switch (path[n]) {
902 	case '\0':
903 	case '/':
904 	    break;
905 	default:
906 	    rc = 1;
907 	    break;
908 	}
909     }
910     return rc;
911 }
912 
913 /* Lst_Find wants 0 to stop search */
914 static int
915 string_match(const void *p, const void *q)
916 {
917     const char *p1 = p;
918     const char *p2 = q;
919 
920     return strcmp(p1, p2);
921 }
922 
923 
924 static int
925 meta_ignore(GNode *gn, const char *p)
926 {
927     char fname[MAXPATHLEN];
928 
929     if (p == NULL)
930 	return TRUE;
931 
932     if (*p == '/') {
933 	cached_realpath(p, fname); /* clean it up */
934 	if (Lst_ForEach(metaIgnorePaths, prefix_match, fname)) {
935 #ifdef DEBUG_META_MODE
936 	    if (DEBUG(META))
937 		fprintf(debug_file, "meta_oodate: ignoring path: %s\n",
938 			p);
939 #endif
940 	    return TRUE;
941 	}
942     }
943 
944     if (metaIgnorePatterns) {
945 	char *pm;
946 
947 	snprintf(fname, sizeof(fname),
948 		 "${%s:@m@${%s:L:M$m}@}",
949 		 MAKE_META_IGNORE_PATTERNS, p);
950 	pm = Var_Subst(NULL, fname, gn, VARF_WANTRES);
951 	if (*pm) {
952 #ifdef DEBUG_META_MODE
953 	    if (DEBUG(META))
954 		fprintf(debug_file, "meta_oodate: ignoring pattern: %s\n",
955 			p);
956 #endif
957 	    free(pm);
958 	    return TRUE;
959 	}
960 	free(pm);
961     }
962 
963     if (metaIgnoreFilter) {
964 	char *fm;
965 
966 	/* skip if filter result is empty */
967 	snprintf(fname, sizeof(fname),
968 		 "${%s:L:${%s:ts:}}",
969 		 p, MAKE_META_IGNORE_FILTER);
970 	fm = Var_Subst(NULL, fname, gn, VARF_WANTRES);
971 	if (*fm == '\0') {
972 #ifdef DEBUG_META_MODE
973 	    if (DEBUG(META))
974 		fprintf(debug_file, "meta_oodate: ignoring filtered: %s\n",
975 			p);
976 #endif
977 	    free(fm);
978 	    return TRUE;
979 	}
980 	free(fm);
981     }
982     return FALSE;
983 }
984 
985 /*
986  * When running with 'meta' functionality, a target can be out-of-date
987  * if any of the references in its meta data file is more recent.
988  * We have to track the latestdir on a per-process basis.
989  */
990 #define LCWD_VNAME_FMT ".meta.%d.lcwd"
991 #define LDIR_VNAME_FMT ".meta.%d.ldir"
992 
993 /*
994  * It is possible that a .meta file is corrupted,
995  * if we detect this we want to reproduce it.
996  * Setting oodate TRUE will have that effect.
997  */
998 #define CHECK_VALID_META(p) if (!(p && *p)) { \
999     warnx("%s: %d: malformed", fname, lineno); \
1000     oodate = TRUE; \
1001     continue; \
1002     }
1003 
1004 #define DEQUOTE(p) if (*p == '\'') {	\
1005     char *ep; \
1006     p++; \
1007     if ((ep = strchr(p, '\''))) \
1008 	*ep = '\0'; \
1009     }
1010 
1011 Boolean
1012 meta_oodate(GNode *gn, Boolean oodate)
1013 {
1014     static char *tmpdir = NULL;
1015     static char cwd[MAXPATHLEN];
1016     char lcwd_vname[64];
1017     char ldir_vname[64];
1018     char lcwd[MAXPATHLEN];
1019     char latestdir[MAXPATHLEN];
1020     char fname[MAXPATHLEN];
1021     char fname1[MAXPATHLEN];
1022     char fname2[MAXPATHLEN];
1023     char fname3[MAXPATHLEN];
1024     const char *dname;
1025     const char *tname;
1026     char *p;
1027     char *cp;
1028     char *link_src;
1029     char *move_target;
1030     static size_t cwdlen = 0;
1031     static size_t tmplen = 0;
1032     FILE *fp;
1033     Boolean needOODATE = FALSE;
1034     Lst missingFiles;
1035     char *pa[4];			/* >= possible uses */
1036     int i;
1037     int have_filemon = FALSE;
1038 
1039     if (oodate)
1040 	return oodate;		/* we're done */
1041 
1042     i = 0;
1043 
1044     dname = Var_Value(".OBJDIR", gn, &pa[i++]);
1045     tname = Var_Value(TARGET, gn, &pa[i++]);
1046 
1047     /* if this succeeds fname3 is realpath of dname */
1048     if (!meta_needed(gn, dname, tname, fname3, FALSE))
1049 	goto oodate_out;
1050     dname = fname3;
1051 
1052     missingFiles = Lst_Init(FALSE);
1053 
1054     /*
1055      * We need to check if the target is out-of-date. This includes
1056      * checking if the expanded command has changed. This in turn
1057      * requires that all variables are set in the same way that they
1058      * would be if the target needs to be re-built.
1059      */
1060     Make_DoAllVar(gn);
1061 
1062     meta_name(gn, fname, sizeof(fname), dname, tname, dname);
1063 
1064 #ifdef DEBUG_META_MODE
1065     if (DEBUG(META))
1066 	fprintf(debug_file, "meta_oodate: %s\n", fname);
1067 #endif
1068 
1069     if ((fp = fopen(fname, "r")) != NULL) {
1070 	static char *buf = NULL;
1071 	static size_t bufsz;
1072 	int lineno = 0;
1073 	int lastpid = 0;
1074 	int pid;
1075 	int x;
1076 	LstNode ln;
1077 	struct stat fs;
1078 
1079 	if (!buf) {
1080 	    bufsz = 8 * BUFSIZ;
1081 	    buf = bmake_malloc(bufsz);
1082 	}
1083 
1084 	if (!cwdlen) {
1085 	    if (getcwd(cwd, sizeof(cwd)) == NULL)
1086 		err(1, "Could not get current working directory");
1087 	    cwdlen = strlen(cwd);
1088 	}
1089 	strlcpy(lcwd, cwd, sizeof(lcwd));
1090 	strlcpy(latestdir, cwd, sizeof(latestdir));
1091 
1092 	if (!tmpdir) {
1093 	    tmpdir = getTmpdir();
1094 	    tmplen = strlen(tmpdir);
1095 	}
1096 
1097 	/* we want to track all the .meta we read */
1098 	Var_Append(".MAKE.META.FILES", fname, VAR_GLOBAL);
1099 
1100 	ln = Lst_First(gn->commands);
1101 	while (!oodate && (x = fgetLine(&buf, &bufsz, 0, fp)) > 0) {
1102 	    lineno++;
1103 	    if (buf[x - 1] == '\n')
1104 		buf[x - 1] = '\0';
1105 	    else {
1106 		warnx("%s: %d: line truncated at %u", fname, lineno, x);
1107 		oodate = TRUE;
1108 		break;
1109 	    }
1110 	    link_src = NULL;
1111 	    move_target = NULL;
1112 	    /* Find the start of the build monitor section. */
1113 	    if (!have_filemon) {
1114 		if (strncmp(buf, "-- filemon", 10) == 0) {
1115 		    have_filemon = TRUE;
1116 		    continue;
1117 		}
1118 		if (strncmp(buf, "# buildmon", 10) == 0) {
1119 		    have_filemon = TRUE;
1120 		    continue;
1121 		}
1122 	    }
1123 
1124 	    /* Delimit the record type. */
1125 	    p = buf;
1126 #ifdef DEBUG_META_MODE
1127 	    if (DEBUG(META))
1128 		fprintf(debug_file, "%s: %d: %s\n", fname, lineno, buf);
1129 #endif
1130 	    strsep(&p, " ");
1131 	    if (have_filemon) {
1132 		/*
1133 		 * We are in the 'filemon' output section.
1134 		 * Each record from filemon follows the general form:
1135 		 *
1136 		 * <key> <pid> <data>
1137 		 *
1138 		 * Where:
1139 		 * <key> is a single letter, denoting the syscall.
1140 		 * <pid> is the process that made the syscall.
1141 		 * <data> is the arguments (of interest).
1142 		 */
1143 		switch(buf[0]) {
1144 		case '#':		/* comment */
1145 		case 'V':		/* version */
1146 		    break;
1147 		default:
1148 		    /*
1149 		     * We need to track pathnames per-process.
1150 		     *
1151 		     * Each process run by make, starts off in the 'CWD'
1152 		     * recorded in the .meta file, if it chdirs ('C')
1153 		     * elsewhere we need to track that - but only for
1154 		     * that process.  If it forks ('F'), we initialize
1155 		     * the child to have the same cwd as its parent.
1156 		     *
1157 		     * We also need to track the 'latestdir' of
1158 		     * interest.  This is usually the same as cwd, but
1159 		     * not if a process is reading directories.
1160 		     *
1161 		     * Each time we spot a different process ('pid')
1162 		     * we save the current value of 'latestdir' in a
1163 		     * variable qualified by 'lastpid', and
1164 		     * re-initialize 'latestdir' to any pre-saved
1165 		     * value for the current 'pid' and 'CWD' if none.
1166 		     */
1167 		    CHECK_VALID_META(p);
1168 		    pid = atoi(p);
1169 		    if (pid > 0 && pid != lastpid) {
1170 			char *ldir;
1171 			char *tp;
1172 
1173 			if (lastpid > 0) {
1174 			    /* We need to remember these. */
1175 			    Var_Set(lcwd_vname, lcwd, VAR_GLOBAL, 0);
1176 			    Var_Set(ldir_vname, latestdir, VAR_GLOBAL, 0);
1177 			}
1178 			snprintf(lcwd_vname, sizeof(lcwd_vname), LCWD_VNAME_FMT, pid);
1179 			snprintf(ldir_vname, sizeof(ldir_vname), LDIR_VNAME_FMT, pid);
1180 			lastpid = pid;
1181 			ldir = Var_Value(ldir_vname, VAR_GLOBAL, &tp);
1182 			if (ldir) {
1183 			    strlcpy(latestdir, ldir, sizeof(latestdir));
1184 			    free(tp);
1185 			}
1186 			ldir = Var_Value(lcwd_vname, VAR_GLOBAL, &tp);
1187 			if (ldir) {
1188 			    strlcpy(lcwd, ldir, sizeof(lcwd));
1189 			    free(tp);
1190 			}
1191 		    }
1192 		    /* Skip past the pid. */
1193 		    if (strsep(&p, " ") == NULL)
1194 			continue;
1195 #ifdef DEBUG_META_MODE
1196 		    if (DEBUG(META))
1197 			    fprintf(debug_file, "%s: %d: %d: %c: cwd=%s lcwd=%s ldir=%s\n",
1198 				    fname, lineno,
1199 				    pid, buf[0], cwd, lcwd, latestdir);
1200 #endif
1201 		    break;
1202 		}
1203 
1204 		CHECK_VALID_META(p);
1205 
1206 		/* Process according to record type. */
1207 		switch (buf[0]) {
1208 		case 'X':		/* eXit */
1209 		    Var_Delete(lcwd_vname, VAR_GLOBAL);
1210 		    Var_Delete(ldir_vname, VAR_GLOBAL);
1211 		    lastpid = 0;	/* no need to save ldir_vname */
1212 		    break;
1213 
1214 		case 'F':		/* [v]Fork */
1215 		    {
1216 			char cldir[64];
1217 			int child;
1218 
1219 			child = atoi(p);
1220 			if (child > 0) {
1221 			    snprintf(cldir, sizeof(cldir), LCWD_VNAME_FMT, child);
1222 			    Var_Set(cldir, lcwd, VAR_GLOBAL, 0);
1223 			    snprintf(cldir, sizeof(cldir), LDIR_VNAME_FMT, child);
1224 			    Var_Set(cldir, latestdir, VAR_GLOBAL, 0);
1225 #ifdef DEBUG_META_MODE
1226 			    if (DEBUG(META))
1227 				    fprintf(debug_file, "%s: %d: %d: cwd=%s lcwd=%s ldir=%s\n",
1228 					    fname, lineno,
1229 					    child, cwd, lcwd, latestdir);
1230 #endif
1231 			}
1232 		    }
1233 		    break;
1234 
1235 		case 'C':		/* Chdir */
1236 		    /* Update lcwd and latest directory. */
1237 		    strlcpy(latestdir, p, sizeof(latestdir));
1238 		    strlcpy(lcwd, p, sizeof(lcwd));
1239 		    Var_Set(lcwd_vname, lcwd, VAR_GLOBAL, 0);
1240 		    Var_Set(ldir_vname, lcwd, VAR_GLOBAL, 0);
1241 #ifdef DEBUG_META_MODE
1242 		    if (DEBUG(META))
1243 			fprintf(debug_file, "%s: %d: cwd=%s ldir=%s\n", fname, lineno, cwd, lcwd);
1244 #endif
1245 		    break;
1246 
1247 		case 'M':		/* renaMe */
1248 		    /*
1249 		     * For 'M'oves we want to check
1250 		     * the src as for 'R'ead
1251 		     * and the target as for 'W'rite.
1252 		     */
1253 		    cp = p;		/* save this for a second */
1254 		    /* now get target */
1255 		    if (strsep(&p, " ") == NULL)
1256 			continue;
1257 		    CHECK_VALID_META(p);
1258 		    move_target = p;
1259 		    p = cp;
1260 		    /* 'L' and 'M' put single quotes around the args */
1261 		    DEQUOTE(p);
1262 		    DEQUOTE(move_target);
1263 		    /* FALLTHROUGH */
1264 		case 'D':		/* unlink */
1265 		    if (*p == '/' && !Lst_IsEmpty(missingFiles)) {
1266 			/* remove any missingFiles entries that match p */
1267 			if ((ln = Lst_Find(missingFiles, p,
1268 					   path_match)) != NULL) {
1269 			    LstNode nln;
1270 			    char *tp;
1271 
1272 			    do {
1273 				nln = Lst_FindFrom(missingFiles, Lst_Succ(ln),
1274 						   p, path_match);
1275 				tp = Lst_Datum(ln);
1276 				Lst_Remove(missingFiles, ln);
1277 				free(tp);
1278 			    } while ((ln = nln) != NULL);
1279 			}
1280 		    }
1281 		    if (buf[0] == 'M') {
1282 			/* the target of the mv is a file 'W'ritten */
1283 #ifdef DEBUG_META_MODE
1284 			if (DEBUG(META))
1285 			    fprintf(debug_file, "meta_oodate: M %s -> %s\n",
1286 				    p, move_target);
1287 #endif
1288 			p = move_target;
1289 			goto check_write;
1290 		    }
1291 		    break;
1292 		case 'L':		/* Link */
1293 		    /*
1294 		     * For 'L'inks check
1295 		     * the src as for 'R'ead
1296 		     * and the target as for 'W'rite.
1297 		     */
1298 		    link_src = p;
1299 		    /* now get target */
1300 		    if (strsep(&p, " ") == NULL)
1301 			continue;
1302 		    CHECK_VALID_META(p);
1303 		    /* 'L' and 'M' put single quotes around the args */
1304 		    DEQUOTE(p);
1305 		    DEQUOTE(link_src);
1306 #ifdef DEBUG_META_MODE
1307 		    if (DEBUG(META))
1308 			fprintf(debug_file, "meta_oodate: L %s -> %s\n",
1309 				link_src, p);
1310 #endif
1311 		    /* FALLTHROUGH */
1312 		case 'W':		/* Write */
1313 		check_write:
1314 		    /*
1315 		     * If a file we generated within our bailiwick
1316 		     * but outside of .OBJDIR is missing,
1317 		     * we need to do it again.
1318 		     */
1319 		    /* ignore non-absolute paths */
1320 		    if (*p != '/')
1321 			break;
1322 
1323 		    if (Lst_IsEmpty(metaBailiwick))
1324 			break;
1325 
1326 		    /* ignore cwd - normal dependencies handle those */
1327 		    if (strncmp(p, cwd, cwdlen) == 0)
1328 			break;
1329 
1330 		    if (!Lst_ForEach(metaBailiwick, prefix_match, p))
1331 			break;
1332 
1333 		    /* tmpdir might be within */
1334 		    if (tmplen > 0 && strncmp(p, tmpdir, tmplen) == 0)
1335 			break;
1336 
1337 		    /* ignore anything containing the string "tmp" */
1338 		    if ((strstr("tmp", p)))
1339 			break;
1340 
1341 		    if ((link_src != NULL && cached_lstat(p, &fs) < 0) ||
1342 			(link_src == NULL && cached_stat(p, &fs) < 0)) {
1343 			if (!meta_ignore(gn, p)) {
1344 			    if (Lst_Find(missingFiles, p, string_match) == NULL)
1345 				Lst_AtEnd(missingFiles, bmake_strdup(p));
1346 			}
1347 		    }
1348 		    break;
1349 		check_link_src:
1350 		    p = link_src;
1351 		    link_src = NULL;
1352 #ifdef DEBUG_META_MODE
1353 		    if (DEBUG(META))
1354 			fprintf(debug_file, "meta_oodate: L src %s\n", p);
1355 #endif
1356 		    /* FALLTHROUGH */
1357 		case 'R':		/* Read */
1358 		case 'E':		/* Exec */
1359 		    /*
1360 		     * Check for runtime files that can't
1361 		     * be part of the dependencies because
1362 		     * they are _expected_ to change.
1363 		     */
1364 		    if (meta_ignore(gn, p))
1365 			break;
1366 
1367 		    /*
1368 		     * The rest of the record is the file name.
1369 		     * Check if it's not an absolute path.
1370 		     */
1371 		    {
1372 			char *sdirs[4];
1373 			char **sdp;
1374 			int sdx = 0;
1375 			int found = 0;
1376 
1377 			if (*p == '/') {
1378 			    sdirs[sdx++] = p; /* done */
1379 			} else {
1380 			    if (strcmp(".", p) == 0)
1381 				continue;  /* no point */
1382 
1383 			    /* Check vs latestdir */
1384 			    snprintf(fname1, sizeof(fname1), "%s/%s", latestdir, p);
1385 			    sdirs[sdx++] = fname1;
1386 
1387 			    if (strcmp(latestdir, lcwd) != 0) {
1388 				/* Check vs lcwd */
1389 				snprintf(fname2, sizeof(fname2), "%s/%s", lcwd, p);
1390 				sdirs[sdx++] = fname2;
1391 			    }
1392 			    if (strcmp(lcwd, cwd) != 0) {
1393 				/* Check vs cwd */
1394 				snprintf(fname3, sizeof(fname3), "%s/%s", cwd, p);
1395 				sdirs[sdx++] = fname3;
1396 			    }
1397 			}
1398 			sdirs[sdx++] = NULL;
1399 
1400 			for (sdp = sdirs; *sdp && !found; sdp++) {
1401 #ifdef DEBUG_META_MODE
1402 			    if (DEBUG(META))
1403 				fprintf(debug_file, "%s: %d: looking for: %s\n", fname, lineno, *sdp);
1404 #endif
1405 			    if (cached_stat(*sdp, &fs) == 0) {
1406 				found = 1;
1407 				p = *sdp;
1408 			    }
1409 			}
1410 			if (found) {
1411 #ifdef DEBUG_META_MODE
1412 			    if (DEBUG(META))
1413 				fprintf(debug_file, "%s: %d: found: %s\n", fname, lineno, p);
1414 #endif
1415 			    if (!S_ISDIR(fs.st_mode) &&
1416 				fs.st_mtime > gn->mtime) {
1417 				if (DEBUG(META))
1418 				    fprintf(debug_file, "%s: %d: file '%s' is newer than the target...\n", fname, lineno, p);
1419 				oodate = TRUE;
1420 			    } else if (S_ISDIR(fs.st_mode)) {
1421 				/* Update the latest directory. */
1422 				cached_realpath(p, latestdir);
1423 			    }
1424 			} else if (errno == ENOENT && *p == '/' &&
1425 				   strncmp(p, cwd, cwdlen) != 0) {
1426 			    /*
1427 			     * A referenced file outside of CWD is missing.
1428 			     * We cannot catch every eventuality here...
1429 			     */
1430 			    if (Lst_Find(missingFiles, p, string_match) == NULL)
1431 				    Lst_AtEnd(missingFiles, bmake_strdup(p));
1432 			}
1433 		    }
1434 		    if (buf[0] == 'E') {
1435 			/* previous latestdir is no longer relevant */
1436 			strlcpy(latestdir, lcwd, sizeof(latestdir));
1437 		    }
1438 		    break;
1439 		default:
1440 		    break;
1441 		}
1442 		if (!oodate && buf[0] == 'L' && link_src != NULL)
1443 		    goto check_link_src;
1444 	    } else if (strcmp(buf, "CMD") == 0) {
1445 		/*
1446 		 * Compare the current command with the one in the
1447 		 * meta data file.
1448 		 */
1449 		if (ln == NULL) {
1450 		    if (DEBUG(META))
1451 			fprintf(debug_file, "%s: %d: there were more build commands in the meta data file than there are now...\n", fname, lineno);
1452 		    oodate = TRUE;
1453 		} else {
1454 		    char *cmd = (char *)Lst_Datum(ln);
1455 		    Boolean hasOODATE = FALSE;
1456 
1457 		    if (strstr(cmd, "$?"))
1458 			hasOODATE = TRUE;
1459 		    else if ((cp = strstr(cmd, ".OODATE"))) {
1460 			/* check for $[{(].OODATE[:)}] */
1461 			if (cp > cmd + 2 && cp[-2] == '$')
1462 			    hasOODATE = TRUE;
1463 		    }
1464 		    if (hasOODATE) {
1465 			needOODATE = TRUE;
1466 			if (DEBUG(META))
1467 			    fprintf(debug_file, "%s: %d: cannot compare command using .OODATE\n", fname, lineno);
1468 		    }
1469 		    cmd = Var_Subst(NULL, cmd, gn, VARF_WANTRES|VARF_UNDEFERR);
1470 
1471 		    if ((cp = strchr(cmd, '\n'))) {
1472 			int n;
1473 
1474 			/*
1475 			 * This command contains newlines, we need to
1476 			 * fetch more from the .meta file before we
1477 			 * attempt a comparison.
1478 			 */
1479 			/* first put the newline back at buf[x - 1] */
1480 			buf[x - 1] = '\n';
1481 			do {
1482 			    /* now fetch the next line */
1483 			    if ((n = fgetLine(&buf, &bufsz, x, fp)) <= 0)
1484 				break;
1485 			    x = n;
1486 			    lineno++;
1487 			    if (buf[x - 1] != '\n') {
1488 				warnx("%s: %d: line truncated at %u", fname, lineno, x);
1489 				break;
1490 			    }
1491 			    cp = strchr(++cp, '\n');
1492 			} while (cp);
1493 			if (buf[x - 1] == '\n')
1494 			    buf[x - 1] = '\0';
1495 		    }
1496 		    if (!hasOODATE &&
1497 			!(gn->type & OP_NOMETA_CMP) &&
1498 			strcmp(p, cmd) != 0) {
1499 			if (DEBUG(META))
1500 			    fprintf(debug_file, "%s: %d: a build command has changed\n%s\nvs\n%s\n", fname, lineno, p, cmd);
1501 			if (!metaIgnoreCMDs)
1502 			    oodate = TRUE;
1503 		    }
1504 		    free(cmd);
1505 		    ln = Lst_Succ(ln);
1506 		}
1507 	    } else if (strcmp(buf, "CWD") == 0) {
1508 		/*
1509 		 * Check if there are extra commands now
1510 		 * that weren't in the meta data file.
1511 		 */
1512 		if (!oodate && ln != NULL) {
1513 		    if (DEBUG(META))
1514 			fprintf(debug_file, "%s: %d: there are extra build commands now that weren't in the meta data file\n", fname, lineno);
1515 		    oodate = TRUE;
1516 		}
1517 		if (strcmp(p, cwd) != 0) {
1518 		    if (DEBUG(META))
1519 			fprintf(debug_file, "%s: %d: the current working directory has changed from '%s' to '%s'\n", fname, lineno, p, curdir);
1520 		    oodate = TRUE;
1521 		}
1522 	    }
1523 	}
1524 
1525 	fclose(fp);
1526 	if (!Lst_IsEmpty(missingFiles)) {
1527 	    if (DEBUG(META))
1528 		fprintf(debug_file, "%s: missing files: %s...\n",
1529 			fname, (char *)Lst_Datum(Lst_First(missingFiles)));
1530 	    oodate = TRUE;
1531 	}
1532 	if (!oodate && !have_filemon && filemonMissing) {
1533 	    if (DEBUG(META))
1534 		fprintf(debug_file, "%s: missing filemon data\n", fname);
1535 	    oodate = TRUE;
1536 	}
1537     } else {
1538 	if (writeMeta && metaMissing) {
1539 	    cp = NULL;
1540 
1541 	    /* if target is in .CURDIR we do not need a meta file */
1542 	    if (gn->path && (cp = strrchr(gn->path, '/')) && cp > gn->path) {
1543 		if (strncmp(curdir, gn->path, (cp - gn->path)) != 0) {
1544 		    cp = NULL;		/* not in .CURDIR */
1545 		}
1546 	    }
1547 	    if (!cp) {
1548 		if (DEBUG(META))
1549 		    fprintf(debug_file, "%s: required but missing\n", fname);
1550 		oodate = TRUE;
1551 		needOODATE = TRUE;	/* assume the worst */
1552 	    }
1553 	}
1554     }
1555 
1556     Lst_Destroy(missingFiles, (FreeProc *)free);
1557 
1558     if (oodate && needOODATE) {
1559 	/*
1560 	 * Target uses .OODATE which is empty; or we wouldn't be here.
1561 	 * We have decided it is oodate, so .OODATE needs to be set.
1562 	 * All we can sanely do is set it to .ALLSRC.
1563 	 */
1564 	Var_Delete(OODATE, gn);
1565 	Var_Set(OODATE, Var_Value(ALLSRC, gn, &cp), gn, 0);
1566 	free(cp);
1567     }
1568 
1569  oodate_out:
1570     for (i--; i >= 0; i--) {
1571 	free(pa[i]);
1572     }
1573     return oodate;
1574 }
1575 
1576 /* support for compat mode */
1577 
1578 static int childPipe[2];
1579 
1580 void
1581 meta_compat_start(void)
1582 {
1583 #ifdef USE_FILEMON_ONCE
1584     /*
1585      * We need to re-open filemon for each cmd.
1586      */
1587     BuildMon *pbm = &Mybm;
1588 
1589     if (pbm->mfp != NULL && useFilemon) {
1590 	filemon_open(pbm);
1591     } else {
1592 	pbm->mon_fd = pbm->filemon_fd = -1;
1593     }
1594 #endif
1595     if (pipe(childPipe) < 0)
1596 	Punt("Cannot create pipe: %s", strerror(errno));
1597     /* Set close-on-exec flag for both */
1598     (void)fcntl(childPipe[0], F_SETFD, FD_CLOEXEC);
1599     (void)fcntl(childPipe[1], F_SETFD, FD_CLOEXEC);
1600 }
1601 
1602 void
1603 meta_compat_child(void)
1604 {
1605     meta_job_child(NULL);
1606     if (dup2(childPipe[1], 1) < 0 ||
1607 	dup2(1, 2) < 0) {
1608 	execError("dup2", "pipe");
1609 	_exit(1);
1610     }
1611 }
1612 
1613 void
1614 meta_compat_parent(void)
1615 {
1616     FILE *fp;
1617     char buf[BUFSIZ];
1618 
1619     close(childPipe[1]);			/* child side */
1620     fp = fdopen(childPipe[0], "r");
1621     while (fgets(buf, sizeof(buf), fp)) {
1622 	meta_job_output(NULL, buf, "");
1623 	printf("%s", buf);
1624 	fflush(stdout);
1625     }
1626     fclose(fp);
1627 }
1628 
1629 #endif	/* USE_META */
1630