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