[BACK]Return to compat.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / make

Annotation of src/usr.bin/make/compat.c, Revision 1.50

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