Annotation of src/usr.bin/make/compat.c, Revision 1.40
1.36 espie 1: /* $OpenPackages$ */
1.40 ! mickey 2: /* $OpenBSD: compat.c,v 1.39 2001/05/29 12:53:39 espie Exp $ */
1.8 millert 3: /* $NetBSD: compat.c,v 1.14 1996/11/06 17:59:01 christos Exp $ */
1.1 deraadt 4:
5: /*
6: * Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
7: * Copyright (c) 1988, 1989 by Adam de Boor
8: * Copyright (c) 1989 by Berkeley Softworks
9: * All rights reserved.
10: *
11: * This code is derived from software contributed to Berkeley by
12: * Adam de Boor.
13: *
14: * Redistribution and use in source and binary forms, with or without
15: * modification, are permitted provided that the following conditions
16: * are met:
17: * 1. Redistributions of source code must retain the above copyright
18: * notice, this list of conditions and the following disclaimer.
19: * 2. Redistributions in binary form must reproduce the above copyright
20: * notice, this list of conditions and the following disclaimer in the
21: * documentation and/or other materials provided with the distribution.
22: * 3. All advertising materials mentioning features or use of this software
23: * must display the following acknowledgement:
24: * This product includes software developed by the University of
25: * California, Berkeley and its contributors.
26: * 4. Neither the name of the University nor the names of its contributors
27: * may be used to endorse or promote products derived from this software
28: * without specific prior written permission.
29: *
30: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
31: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
32: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
34: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
35: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
36: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
37: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
38: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
39: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
40: * SUCH DAMAGE.
41: */
42:
1.37 espie 43: #include <sys/types.h>
44: #include <sys/stat.h>
45: #include <sys/wait.h>
46: #include <ctype.h>
47: #include <errno.h>
1.39 espie 48: #include <limits.h>
1.37 espie 49: #include <signal.h>
50: #include <stddef.h>
51: #include <stdio.h>
1.39 espie 52: #include <stdlib.h>
1.38 espie 53: #include <string.h>
1.37 espie 54: #include <unistd.h>
55: #include "config.h"
56: #include "defines.h"
57: #include "dir.h"
58: #include "job.h"
59: #include "compat.h"
60: #include "suff.h"
61: #include "var.h"
62: #include "targ.h"
63: #include "error.h"
64: #include "str.h"
65: #include "extern.h"
66: #include "memory.h"
67: #include "gnode.h"
68: #include "make.h"
69: #include "timestamp.h"
70: #include "lst.h"
71: #include "pathnames.h"
1.1 deraadt 72:
1.36 espie 73: /* The following array is used to make a fast determination of which
1.1 deraadt 74: * characters are interpreted specially by the shell. If a command
75: * contains any of these characters, it is executed by the shell, not
1.36 espie 76: * directly by us. */
1.1 deraadt 77:
1.36 espie 78: static char meta[256];
1.1 deraadt 79:
1.18 espie 80: static GNode *curTarg = NULL;
1.1 deraadt 81: static GNode *ENDNode;
1.36 espie 82: static void CompatInterrupt(int);
83: static int CompatRunCommand(void *, void *);
84: static void CompatMake(void *, void *);
85: static int shellneed(char **);
1.1 deraadt 86:
87: /*-
88: *-----------------------------------------------------------------------
89: * CompatInterrupt --
90: * Interrupt the creation of the current target and remove it if
91: * it ain't precious.
92: *
93: * Side Effects:
94: * The target is removed and the process exits. If .INTERRUPT exists,
95: * its commands are run first WITH INTERRUPTS IGNORED..
96: *-----------------------------------------------------------------------
97: */
98: static void
1.36 espie 99: CompatInterrupt(signo)
100: int signo;
1.1 deraadt 101: {
102: GNode *gn;
1.4 millert 103:
1.36 espie 104: if (curTarg != NULL && !Targ_Precious(curTarg)) {
105: char *file = Varq_Value(TARGET_INDEX, curTarg);
1.1 deraadt 106:
1.36 espie 107: if (!noExecute && eunlink(file) != -1)
1.12 espie 108: Error("*** %s removed\n", file);
1.1 deraadt 109:
1.36 espie 110: /* Run .INTERRUPT only if hit with interrupt signal. */
1.1 deraadt 111: if (signo == SIGINT) {
1.37 espie 112: gn = Targ_FindNode(".INTERRUPT", TARG_NOCREATE);
1.36 espie 113: if (gn != NULL)
1.28 espie 114: Lst_Find(&gn->commands, CompatRunCommand, gn);
1.1 deraadt 115: }
116:
117: }
1.36 espie 118: exit(signo);
1.1 deraadt 119: }
1.36 espie 120:
1.1 deraadt 121: /*-
122: *-----------------------------------------------------------------------
1.10 deraadt 123: * shellneed --
1.36 espie 124: *
1.10 deraadt 125: * Results:
1.36 espie 126: * Returns 1 if a specified set of arguments
127: * must be executed by the shell,
1.12 espie 128: * 0 if it can be run via execve, and -1 if the command can be
1.36 espie 129: * handled internally
1.10 deraadt 130: *
131: * Side Effects:
1.12 espie 132: * May modify the process umask
1.10 deraadt 133: *-----------------------------------------------------------------------
134: */
135: static int
1.36 espie 136: shellneed(av)
1.12 espie 137: char **av;
1.10 deraadt 138: {
1.36 espie 139: char *runsh[] = {
1.11 deraadt 140: "alias", "cd", "eval", "exec", "exit", "read", "set", "ulimit",
1.36 espie 141: "unalias", "unset", "wait",
1.11 deraadt 142: NULL
143: };
144:
1.12 espie 145: char **p;
1.11 deraadt 146:
1.12 espie 147: /* FIXME most of these ARE actual no-ops */
1.11 deraadt 148: for (p = runsh; *p; p++)
1.12 espie 149: if (strcmp(av[0], *p) == 0)
1.36 espie 150: return 1;
1.11 deraadt 151:
1.12 espie 152: if (strcmp(av[0], "umask") == 0) {
1.10 deraadt 153: long umi;
154: char *ep = NULL;
155: mode_t um;
156:
1.12 espie 157: if (av[1] != NULL) {
158: umi = strtol(av[1], &ep, 8);
1.10 deraadt 159: if (ep == NULL)
1.36 espie 160: return 1;
1.10 deraadt 161: um = umi;
162: }
1.12 espie 163: else {
164: um = umask(0);
165: printf("%o\n", um);
166: }
1.36 espie 167: (void)umask(um);
168: return -1;
1.10 deraadt 169: }
170:
1.36 espie 171: return 0;
1.10 deraadt 172: }
1.36 espie 173:
1.10 deraadt 174: /*-
175: *-----------------------------------------------------------------------
1.1 deraadt 176: * CompatRunCommand --
177: * Execute the next command for a target. If the command returns an
178: * error, the node's made field is set to ERROR and creation stops.
179: *
180: * Results:
1.36 espie 181: * 0 in case of error, 1 if ok.
1.1 deraadt 182: *
183: * Side Effects:
184: * The node's 'made' field may be set to ERROR.
185: *-----------------------------------------------------------------------
186: */
187: static int
1.36 espie 188: CompatRunCommand(cmdp, gnp)
189: void * cmdp; /* Command to execute */
190: void * gnp; /* Node from which the command came */
1.1 deraadt 191: {
1.36 espie 192: char *cmdStart; /* Start of expanded command */
1.12 espie 193: char *cp, *bp = NULL;
1.37 espie 194: bool silent, /* Don't print command */
1.36 espie 195: errCheck, /* Check errors */
1.32 espie 196: doExecute; /* Execute the command */
1.36 espie 197: int reason; /* Reason for child's death */
198: int status; /* Description of child's death */
199: int cpid; /* Child actually found */
1.37 espie 200: int stat; /* Status of fork */
1.36 espie 201: LstNode cmdNode; /* Node where current command is located */
202: char **av; /* Argument vector for thing to exec */
203: int argc; /* Number of arguments in av or 0 if not
1.1 deraadt 204: * dynamically allocated */
1.37 espie 205: bool local; /* true if command should be executed
1.1 deraadt 206: * locally */
1.36 espie 207: char *cmd = (char *)cmdp;
208: GNode *gn = (GNode *)gnp;
1.37 espie 209: static char *shargv[4] = { _PATH_BSHELL };
1.36 espie 210:
211: /* Avoid clobbered variable warnings by forcing the compiler
212: * to ``unregister'' variables. */
1.1 deraadt 213: #if __GNUC__
1.36 espie 214: (void)&av;
215: (void)&errCheck;
1.1 deraadt 216: #endif
217: silent = gn->type & OP_SILENT;
218: errCheck = !(gn->type & OP_IGNORE);
1.32 espie 219: doExecute = !noExecute;
1.1 deraadt 220:
1.28 espie 221: cmdNode = Lst_Member(&gn->commands, cmd);
1.37 espie 222: cmdStart = Var_Subst(cmd, &gn->context, false);
1.1 deraadt 223:
1.36 espie 224: /* brk_string will return an argv with a NULL in av[0], thus causing
1.1 deraadt 225: * execvp to choke and die horribly. Besides, how can we execute a null
226: * command? In any case, we warn the user that the command expanded to
1.36 espie 227: * nothing (is this the right thing to do?). */
1.4 millert 228:
1.1 deraadt 229: if (*cmdStart == '\0') {
230: free(cmdStart);
231: Error("%s expands to empty string", cmd);
1.25 espie 232: return 1;
1.36 espie 233: } else
1.1 deraadt 234: cmd = cmdStart;
1.23 espie 235: Lst_Replace(cmdNode, cmdStart);
1.1 deraadt 236:
237: if ((gn->type & OP_SAVE_CMDS) && (gn != ENDNode)) {
1.28 espie 238: Lst_AtEnd(&ENDNode->commands, cmdStart);
1.25 espie 239: return 1;
1.1 deraadt 240: } else if (strcmp(cmdStart, "...") == 0) {
241: gn->type |= OP_SAVE_CMDS;
1.25 espie 242: return 1;
1.1 deraadt 243: }
244:
1.32 espie 245: for (;; cmd++) {
1.36 espie 246: if (*cmd == '@')
1.37 espie 247: silent = DEBUG(LOUD) ? false : true;
1.32 espie 248: else if (*cmd == '-')
1.37 espie 249: errCheck = false;
1.32 espie 250: else if (*cmd == '+')
1.37 espie 251: doExecute = true;
1.32 espie 252: else
253: break;
1.1 deraadt 254: }
255:
1.36 espie 256: while (isspace(*cmd))
1.1 deraadt 257: cmd++;
1.4 millert 258:
1.36 espie 259: /* Search for meta characters in the command. If there are no meta
1.1 deraadt 260: * characters, there's no need to execute a shell to execute the
1.36 espie 261: * command. */
1.1 deraadt 262: for (cp = cmd; !meta[(unsigned char)*cp]; cp++) {
263: continue;
264: }
265:
1.36 espie 266: /* Print the command before echoing if we're not supposed to be quiet for
267: * this one. We also print the command if -n given. */
1.1 deraadt 268: if (!silent || noExecute) {
1.36 espie 269: printf("%s\n", cmd);
1.1 deraadt 270: fflush(stdout);
271: }
272:
1.36 espie 273: /* If we're not supposed to execute any commands, this is as far as
274: * we go... */
1.32 espie 275: if (!doExecute)
1.25 espie 276: return 1;
1.4 millert 277:
1.1 deraadt 278: if (*cp != '\0') {
1.36 espie 279: /* If *cp isn't the null character, we hit a "meta" character and
1.1 deraadt 280: * need to pass the command off to the shell. We give the shell the
281: * -e flag as well as -c if it's supposed to exit when it hits an
1.36 espie 282: * error. */
1.10 deraadt 283:
1.36 espie 284: shargv[1] = errCheck ? "-ec" : "-c";
1.10 deraadt 285: shargv[2] = cmd;
1.36 espie 286: shargv[3] = NULL;
1.10 deraadt 287: av = shargv;
288: argc = 0;
1.12 espie 289: } else {
1.36 espie 290: /* No meta-characters, so probably no need to exec a shell.
291: * Break the command into words to form an argument vector
292: * we can execute. */
293: av = brk_string(cmd, &argc, &bp);
294: switch (shellneed(av)) {
1.12 espie 295: case -1: /* handled internally */
296: free(bp);
297: free(av);
1.25 espie 298: return 1;
1.12 espie 299: case 1:
1.36 espie 300: shargv[1] = errCheck ? "-ec" : "-c";
1.12 espie 301: shargv[2] = cmd;
1.36 espie 302: shargv[3] = NULL;
303: free(av);
1.14 espie 304: free(bp);
305: bp = NULL;
1.12 espie 306: av = shargv;
307: argc = 0;
308: break;
309: default: /* nothing needed */
310: break;
1.10 deraadt 311: }
1.1 deraadt 312: }
1.4 millert 313:
1.37 espie 314: local = true;
1.1 deraadt 315:
1.36 espie 316: /* Fork and execute the single command. If the fork fails, we abort. */
1.1 deraadt 317: cpid = vfork();
1.36 espie 318: if (cpid == -1)
1.1 deraadt 319: Fatal("Could not fork");
320: if (cpid == 0) {
321: if (local) {
322: execvp(av[0], av);
1.17 espie 323: if (errno == ENOENT)
1.36 espie 324: fprintf(stderr, "%s: not found\n", av[0]);
1.17 espie 325: else
326: perror(av[0]);
1.36 espie 327: } else
1.1 deraadt 328: (void)execv(av[0], av);
1.9 deraadt 329: _exit(1);
1.1 deraadt 330: }
1.12 espie 331: if (bp) {
1.36 espie 332: free(av);
1.12 espie 333: free(bp);
334: }
1.1 deraadt 335: free(cmdStart);
1.23 espie 336: Lst_Replace(cmdNode, NULL);
1.4 millert 337:
1.36 espie 338: /* The child is off and running. Now all we can do is wait... */
1.1 deraadt 339: while (1) {
340:
1.2 deraadt 341: while ((stat = wait(&reason)) != cpid) {
1.36 espie 342: if (stat == -1 && errno != EINTR)
1.1 deraadt 343: break;
344: }
1.4 millert 345:
1.36 espie 346: if (stat != -1) {
347: if (WIFSTOPPED(reason))
1.2 deraadt 348: status = WSTOPSIG(reason); /* stopped */
1.36 espie 349: else if (WIFEXITED(reason)) {
1.2 deraadt 350: status = WEXITSTATUS(reason); /* exited */
1.36 espie 351: if (status != 0)
352: printf("*** Error code %d", status);
1.1 deraadt 353: } else {
1.2 deraadt 354: status = WTERMSIG(reason); /* signaled */
1.36 espie 355: printf("*** Signal %d", status);
1.4 millert 356: }
357:
1.1 deraadt 358:
1.36 espie 359: if (!WIFEXITED(reason) || status != 0) {
1.1 deraadt 360: if (errCheck) {
361: gn->made = ERROR;
1.36 espie 362: if (keepgoing)
363: /* Abort the current target, but let others
364: * continue. */
365: printf(" (continuing)\n");
1.1 deraadt 366: } else {
1.36 espie 367: /* Continue executing commands for this target.
368: * If we return 0, this will happen... */
369: printf(" (ignored)\n");
1.1 deraadt 370: status = 0;
371: }
372: }
373: break;
1.36 espie 374: } else
375: Fatal("error in wait: %d", stat);
1.1 deraadt 376: /*NOTREACHED*/
377: }
378:
1.25 espie 379: return !status;
1.1 deraadt 380: }
1.36 espie 381:
1.1 deraadt 382: /*-
383: *-----------------------------------------------------------------------
384: * CompatMake --
385: * Make a target.
386: *
387: * Side Effects:
388: * If an error is detected and not being ignored, the process exits.
389: *-----------------------------------------------------------------------
390: */
1.26 espie 391: static void
392: CompatMake(gnp, pgnp)
1.36 espie 393: void * gnp; /* The node to make */
394: void * pgnp; /* Parent to abort if necessary */
1.1 deraadt 395: {
1.36 espie 396: GNode *gn = (GNode *)gnp;
397: GNode *pgn = (GNode *)pgnp;
1.5 millert 398:
1.7 deraadt 399: if (pgn->type & OP_MADE) {
1.35 espie 400: (void)Dir_MTime(gn);
1.7 deraadt 401: gn->made = UPTODATE;
402: }
403:
1.8 millert 404: if (gn->type & OP_USE) {
405: Make_HandleUse(gn, pgn);
406: } else if (gn->made == UNMADE) {
1.36 espie 407: /* First mark ourselves to be made, then apply whatever transformations
1.1 deraadt 408: * the suffix module thinks are necessary. Once that's done, we can
409: * descend and make all our children. If any of them has an error
1.37 espie 410: * but the -k flag was given, our 'make' field will be set false again.
1.1 deraadt 411: * This is our signal to not attempt to do anything but abort our
1.36 espie 412: * parent as well. */
1.37 espie 413: gn->make = true;
1.1 deraadt 414: gn->made = BEINGMADE;
1.36 espie 415: Suff_FindDeps(gn);
1.28 espie 416: Lst_ForEach(&gn->children, CompatMake, gn);
1.1 deraadt 417: if (!gn->make) {
418: gn->made = ABORTED;
1.37 espie 419: pgn->make = false;
1.26 espie 420: return;
1.1 deraadt 421: }
422:
1.36 espie 423: if (Lst_Member(&gn->iParents, pgn) != NULL) {
1.29 espie 424: Varq_Set(IMPSRC_INDEX, Varq_Value(TARGET_INDEX, gn), pgn);
1.36 espie 425: }
1.4 millert 426:
1.36 espie 427: /* All the children were made ok. Now cmtime contains the modification
1.1 deraadt 428: * time of the newest child, we need to find out if we exist and when
429: * we were modified last. The criteria for datedness are defined by the
1.36 espie 430: * Make_OODate function. */
431: if (DEBUG(MAKE))
1.1 deraadt 432: printf("Examining %s...", gn->name);
433: if (! Make_OODate(gn)) {
434: gn->made = UPTODATE;
1.36 espie 435: if (DEBUG(MAKE))
1.1 deraadt 436: printf("up-to-date.\n");
1.26 espie 437: return;
1.36 espie 438: } else if (DEBUG(MAKE))
1.1 deraadt 439: printf("out-of-date.\n");
440:
1.36 espie 441: /* If the user is just seeing if something is out-of-date, exit now
442: * to tell him/her "yes". */
443: if (queryFlag)
444: exit(-1);
1.1 deraadt 445:
1.36 espie 446: /* We need to be re-made. We also have to make sure we've got a $?
1.1 deraadt 447: * variable. To be nice, we also define the $> variable using
1.36 espie 448: * Make_DoAllVar(). */
1.1 deraadt 449: Make_DoAllVar(gn);
1.4 millert 450:
1.36 espie 451: /* Alter our type to tell if errors should be ignored or things
452: * should not be printed so CompatRunCommand knows what to do. */
453: if (Targ_Ignore(gn))
1.1 deraadt 454: gn->type |= OP_IGNORE;
1.36 espie 455: if (Targ_Silent(gn))
1.1 deraadt 456: gn->type |= OP_SILENT;
457:
1.36 espie 458: if (Job_CheckCommands(gn, Fatal)) {
459: /* Our commands are ok, but we still have to worry about the -t
460: * flag... */
1.1 deraadt 461: if (!touchFlag) {
462: curTarg = gn;
1.28 espie 463: Lst_Find(&gn->commands, CompatRunCommand, gn);
1.18 espie 464: curTarg = NULL;
1.36 espie 465: } else
466: Job_Touch(gn, gn->type & OP_SILENT);
467: } else
1.1 deraadt 468: gn->made = ERROR;
469:
470: if (gn->made != ERROR) {
1.36 espie 471: /* If the node was made successfully, mark it so, update
1.1 deraadt 472: * its modification time and timestamp all its parents. Note
473: * that for .ZEROTIME targets, the timestamping isn't done.
1.36 espie 474: * This is to keep its state from affecting that of its parent. */
1.1 deraadt 475: gn->made = MADE;
476: #ifndef RECHECK
1.36 espie 477: /* We can't re-stat the thing, but we can at least take care of
1.1 deraadt 478: * rules where a target depends on a source that actually creates
479: * the target, but only if it has changed, e.g.
480: *
481: * parse.h : parse.o
482: *
483: * parse.o : parse.y
1.36 espie 484: * yacc -d parse.y
485: * cc -c y.tab.c
486: * mv y.tab.o parse.o
487: * cmp -s y.tab.h parse.h || mv y.tab.h parse.h
1.1 deraadt 488: *
489: * In this case, if the definitions produced by yacc haven't
490: * changed from before, parse.h won't have been updated and
491: * gn->mtime will reflect the current modification time for
492: * parse.h. This is something of a kludge, I admit, but it's a
493: * useful one..
494: *
495: * XXX: People like to use a rule like
496: *
497: * FRC:
498: *
499: * To force things that depend on FRC to be made, so we have to
1.36 espie 500: * check for gn->children being empty as well... */
501: if (!Lst_IsEmpty(&gn->commands) || Lst_IsEmpty(&gn->children))
1.1 deraadt 502: gn->mtime = now;
503: #else
1.36 espie 504: /* This is what Make does and it's actually a good thing, as it
1.1 deraadt 505: * allows rules like
506: *
507: * cmp -s y.tab.h parse.h || cp y.tab.h parse.h
508: *
509: * to function as intended. Unfortunately, thanks to the stateless
510: * nature of NFS (and the speed of this program), there are times
511: * when the modification time of a file created on a remote
512: * machine will not be modified before the stat() implied by
513: * the Dir_MTime occurs, thus leading us to believe that the file
514: * is unchanged, wreaking havoc with files that depend on this one.
515: *
516: * I have decided it is better to make too much than to make too
517: * little, so this stuff is commented out unless you're sure it's
518: * ok.
519: * -- ardeb 1/12/88
520: */
1.35 espie 521: if (noExecute || is_out_of_date(Dir_MTime(gn)))
1.1 deraadt 522: gn->mtime = now;
1.37 espie 523: if (is_strictly_before(gn->mtime, gn->cmtime))
1.1 deraadt 524: gn->mtime = gn->cmtime;
1.36 espie 525: if (DEBUG(MAKE))
1.1 deraadt 526: printf("update time: %s\n", Targ_FmtTime(gn->mtime));
527: #endif
528: if (!(gn->type & OP_EXEC)) {
1.37 espie 529: pgn->childMade = true;
1.1 deraadt 530: Make_TimeStamp(pgn, gn);
531: }
1.36 espie 532: } else if (keepgoing)
1.37 espie 533: pgn->make = false;
1.36 espie 534: else {
535:
1.24 espie 536: if (gn->lineno)
1.36 espie 537: printf("\n\nStop in %s (line %lu of %s).\n",
538: Var_Value(".CURDIR"),
1.24 espie 539: (unsigned long)gn->lineno,
540: gn->fname);
541: else
1.36 espie 542: printf("\n\nStop in %s.\n", Var_Value(".CURDIR"));
543: exit(1);
1.1 deraadt 544: }
1.36 espie 545: } else if (gn->made == ERROR)
546: /* Already had an error when making this beastie. Tell the parent
547: * to abort. */
1.37 espie 548: pgn->make = false;
1.36 espie 549: else {
550: if (Lst_Member(&gn->iParents, pgn) != NULL) {
1.29 espie 551: Varq_Set(IMPSRC_INDEX, Varq_Value(TARGET_INDEX, gn), pgn);
1.36 espie 552: }
553: switch (gn->made) {
1.1 deraadt 554: case BEINGMADE:
555: Error("Graph cycles through %s\n", gn->name);
556: gn->made = ERROR;
1.37 espie 557: pgn->make = false;
1.1 deraadt 558: break;
559: case MADE:
560: if ((gn->type & OP_EXEC) == 0) {
1.37 espie 561: pgn->childMade = true;
1.1 deraadt 562: Make_TimeStamp(pgn, gn);
563: }
564: break;
565: case UPTODATE:
1.36 espie 566: if ((gn->type & OP_EXEC) == 0)
1.1 deraadt 567: Make_TimeStamp(pgn, gn);
568: break;
569: default:
570: break;
571: }
572: }
573: }
1.36 espie 574:
1.1 deraadt 575: void
576: Compat_Run(targs)
1.36 espie 577: Lst targs; /* List of target nodes to re-create */
1.1 deraadt 578: {
1.36 espie 579: char *cp; /* Pointer to string of shell meta-characters */
580: GNode *gn = NULL;/* Current root target */
581: int errors; /* Number of targets not remade due to errors */
1.1 deraadt 582:
1.36 espie 583: if (signal(SIGINT, SIG_IGN) != SIG_IGN)
1.1 deraadt 584: signal(SIGINT, CompatInterrupt);
1.36 espie 585: if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
1.1 deraadt 586: signal(SIGTERM, CompatInterrupt);
1.36 espie 587: if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
1.1 deraadt 588: signal(SIGHUP, CompatInterrupt);
1.36 espie 589: if (signal(SIGQUIT, SIG_IGN) != SIG_IGN)
1.1 deraadt 590: signal(SIGQUIT, CompatInterrupt);
591:
1.36 espie 592: for (cp = "#=|^(){};&<>*?[]:$`\\\n"; *cp != '\0'; cp++)
1.1 deraadt 593: meta[(unsigned char) *cp] = 1;
1.36 espie 594: /* The null character serves as a sentinel in the string. */
1.1 deraadt 595: meta[0] = 1;
596:
1.37 espie 597: ENDNode = Targ_FindNode(".END", TARG_CREATE);
1.36 espie 598: /* If the user has defined a .BEGIN target, execute the commands attached
599: * to it. */
1.1 deraadt 600: if (!queryFlag) {
1.37 espie 601: gn = Targ_FindNode(".BEGIN", TARG_NOCREATE);
1.18 espie 602: if (gn != NULL) {
1.28 espie 603: Lst_Find(&gn->commands, CompatRunCommand, gn);
1.36 espie 604: if (gn->made == ERROR) {
605: printf("\n\nStop.\n");
606: exit(1);
607: }
1.1 deraadt 608: }
609: }
610:
1.36 espie 611: /* For each entry in the list of targets to create, call CompatMake on
1.1 deraadt 612: * it to create the thing. CompatMake will leave the 'made' field of gn
613: * in one of several states:
614: * UPTODATE gn was already up-to-date
1.36 espie 615: * MADE gn was recreated successfully
616: * ERROR An error occurred while gn was being created
1.1 deraadt 617: * ABORTED gn was not remade because one of its inferiors
1.36 espie 618: * could not be made due to errors. */
1.1 deraadt 619: errors = 0;
1.19 espie 620: while ((gn = (GNode *)Lst_DeQueue(targs)) != NULL) {
1.26 espie 621: CompatMake(gn, gn);
1.1 deraadt 622:
1.36 espie 623: if (gn->made == UPTODATE)
624: printf("`%s' is up to date.\n", gn->name);
625: else if (gn->made == ABORTED) {
626: printf("`%s' not remade because of errors.\n", gn->name);
1.1 deraadt 627: errors += 1;
628: }
629: }
630:
1.36 espie 631: /* If the user has defined a .END target, run its commands. */
632: if (errors == 0)
1.40 ! mickey 633: Lst_Find(&ENDNode->commands, CompatRunCommand, ENDNode);
1.1 deraadt 634: }