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