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

Annotation of src/usr.bin/make/main.c, Revision 1.4

1.4     ! niklas      1: /*     $NetBSD: main.c,v 1.24 1996/02/04 22:20:49 christos Exp $       */
1.1       deraadt     2:
                      3: /*
                      4:  * Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
                      5:  * Copyright (c) 1988, 1989 by Adam de Boor
                      6:  * Copyright (c) 1989 by Berkeley Softworks
                      7:  * All rights reserved.
                      8:  *
                      9:  * This code is derived from software contributed to Berkeley by
                     10:  * Adam de Boor.
                     11:  *
                     12:  * Redistribution and use in source and binary forms, with or without
                     13:  * modification, are permitted provided that the following conditions
                     14:  * are met:
                     15:  * 1. Redistributions of source code must retain the above copyright
                     16:  *    notice, this list of conditions and the following disclaimer.
                     17:  * 2. Redistributions in binary form must reproduce the above copyright
                     18:  *    notice, this list of conditions and the following disclaimer in the
                     19:  *    documentation and/or other materials provided with the distribution.
                     20:  * 3. All advertising materials mentioning features or use of this software
                     21:  *    must display the following acknowledgement:
                     22:  *     This product includes software developed by the University of
                     23:  *     California, Berkeley and its contributors.
                     24:  * 4. Neither the name of the University nor the names of its contributors
                     25:  *    may be used to endorse or promote products derived from this software
                     26:  *    without specific prior written permission.
                     27:  *
                     28:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     29:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     30:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     31:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     32:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     33:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     34:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     35:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     36:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     37:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     38:  * SUCH DAMAGE.
                     39:  */
                     40:
                     41: #ifndef lint
                     42: char copyright[] =
                     43: "@(#) Copyright (c) 1989 The Regents of the University of California.\n\
                     44:  All rights reserved.\n";
                     45: #endif /* not lint */
                     46:
                     47: #ifndef lint
                     48: #if 0
                     49: static char sccsid[] = "@(#)main.c     5.25 (Berkeley) 4/1/91";
                     50: #else
1.4     ! niklas     51: static char rcsid[] = "$NetBSD: main.c,v 1.24 1996/02/04 22:20:49 christos Exp $";
1.1       deraadt    52: #endif
                     53: #endif /* not lint */
                     54:
                     55: /*-
                     56:  * main.c --
                     57:  *     The main file for this entire program. Exit routines etc
                     58:  *     reside here.
                     59:  *
                     60:  * Utility functions defined in this file:
                     61:  *     Main_ParseArgLine       Takes a line of arguments, breaks them and
                     62:  *                             treats them as if they were given when first
                     63:  *                             invoked. Used by the parse module to implement
                     64:  *                             the .MFLAGS target.
                     65:  *
                     66:  *     Error                   Print a tagged error message. The global
                     67:  *                             MAKE variable must have been defined. This
                     68:  *                             takes a format string and two optional
                     69:  *                             arguments for it.
                     70:  *
                     71:  *     Fatal                   Print an error message and exit. Also takes
                     72:  *                             a format string and two arguments.
                     73:  *
                     74:  *     Punt                    Aborts all jobs and exits with a message. Also
                     75:  *                             takes a format string and two arguments.
                     76:  *
                     77:  *     Finish                  Finish things up by printing the number of
                     78:  *                             errors which occured, as passed to it, and
                     79:  *                             exiting.
                     80:  */
                     81:
                     82: #include <sys/types.h>
                     83: #include <sys/time.h>
                     84: #include <sys/param.h>
                     85: #include <sys/resource.h>
1.2       deraadt    86: #include <sys/signal.h>
1.1       deraadt    87: #include <sys/stat.h>
                     88: #include <sys/utsname.h>
1.2       deraadt    89: #include <sys/resource.h>
1.1       deraadt    90: #include <errno.h>
                     91: #include <fcntl.h>
                     92: #include <stdio.h>
                     93: #if __STDC__
                     94: #include <stdarg.h>
                     95: #else
                     96: #include <varargs.h>
                     97: #endif
                     98: #include "make.h"
                     99: #include "hash.h"
                    100: #include "dir.h"
                    101: #include "job.h"
                    102: #include "pathnames.h"
                    103:
                    104: #ifndef        DEFMAXLOCAL
                    105: #define        DEFMAXLOCAL DEFMAXJOBS
1.4     ! niklas    106: #endif /* DEFMAXLOCAL */
1.1       deraadt   107:
                    108: #define        MAKEFLAGS       ".MAKEFLAGS"
                    109:
                    110: Lst                    create;         /* Targets to be made */
                    111: time_t                 now;            /* Time at start of make */
                    112: GNode                  *DEFAULT;       /* .DEFAULT node */
                    113: Boolean                        allPrecious;    /* .PRECIOUS given on line by itself */
                    114:
                    115: static Boolean         noBuiltins;     /* -r flag */
                    116: static Lst             makefiles;      /* ordered list of makefiles to read */
1.2       deraadt   117: int                    maxJobs;        /* -j argument */
1.1       deraadt   118: static int             maxLocal;       /* -L argument */
                    119: Boolean                        compatMake;     /* -B argument */
                    120: Boolean                        debug;          /* -d flag */
                    121: Boolean                        noExecute;      /* -n flag */
                    122: Boolean                        keepgoing;      /* -k flag */
                    123: Boolean                        queryFlag;      /* -q flag */
                    124: Boolean                        touchFlag;      /* -t flag */
                    125: Boolean                        usePipes;       /* !-P flag */
                    126: Boolean                        ignoreErrors;   /* -i flag */
                    127: Boolean                        beSilent;       /* -s flag */
                    128: Boolean                        oldVars;        /* variable substitution style */
                    129: Boolean                        checkEnvFirst;  /* -e flag */
                    130: static Boolean         jobsRunning;    /* TRUE if the jobs might be running */
                    131:
                    132: static Boolean         ReadMakefile();
                    133: static void            usage();
                    134:
                    135: static char *curdir;                   /* startup directory */
                    136: static char *objdir;                   /* where we chdir'ed to */
                    137:
                    138: /*-
                    139:  * MainParseArgs --
                    140:  *     Parse a given argument vector. Called from main() and from
                    141:  *     Main_ParseArgLine() when the .MAKEFLAGS target is used.
                    142:  *
                    143:  *     XXX: Deal with command line overriding .MAKEFLAGS in makefile
                    144:  *
                    145:  * Results:
                    146:  *     None
                    147:  *
                    148:  * Side Effects:
                    149:  *     Various global and local flags will be set depending on the flags
                    150:  *     given
                    151:  */
                    152: static void
                    153: MainParseArgs(argc, argv)
                    154:        int argc;
                    155:        char **argv;
                    156: {
                    157:        extern int optind;
                    158:        extern char *optarg;
                    159:        int c;
1.2       deraadt   160:        int forceJobs = 0;
1.1       deraadt   161:
                    162:        optind = 1;     /* since we're called more than once */
1.2       deraadt   163: #ifdef REMOTE
1.1       deraadt   164: # define OPTFLAGS "BD:I:L:PSd:ef:ij:knqrst"
                    165: #else
1.2       deraadt   166: # define OPTFLAGS "BD:I:PSd:ef:ij:knqrst"
1.1       deraadt   167: #endif
                    168: rearg: while((c = getopt(argc, argv, OPTFLAGS)) != EOF) {
                    169:                switch(c) {
                    170:                case 'D':
                    171:                        Var_Set(optarg, "1", VAR_GLOBAL);
                    172:                        Var_Append(MAKEFLAGS, "-D", VAR_GLOBAL);
                    173:                        Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
                    174:                        break;
                    175:                case 'I':
                    176:                        Parse_AddIncludeDir(optarg);
                    177:                        Var_Append(MAKEFLAGS, "-I", VAR_GLOBAL);
                    178:                        Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
                    179:                        break;
                    180:                case 'B':
                    181:                        compatMake = TRUE;
                    182:                        break;
1.2       deraadt   183: #ifdef REMOTE
1.1       deraadt   184:                case 'L':
                    185:                        maxLocal = atoi(optarg);
                    186:                        Var_Append(MAKEFLAGS, "-L", VAR_GLOBAL);
                    187:                        Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
                    188:                        break;
1.2       deraadt   189: #endif
1.1       deraadt   190:                case 'P':
                    191:                        usePipes = FALSE;
                    192:                        Var_Append(MAKEFLAGS, "-P", VAR_GLOBAL);
                    193:                        break;
                    194:                case 'S':
                    195:                        keepgoing = FALSE;
                    196:                        Var_Append(MAKEFLAGS, "-S", VAR_GLOBAL);
                    197:                        break;
                    198:                case 'd': {
                    199:                        char *modules = optarg;
                    200:
                    201:                        for (; *modules; ++modules)
                    202:                                switch (*modules) {
                    203:                                case 'A':
                    204:                                        debug = ~0;
                    205:                                        break;
                    206:                                case 'a':
                    207:                                        debug |= DEBUG_ARCH;
                    208:                                        break;
                    209:                                case 'c':
                    210:                                        debug |= DEBUG_COND;
                    211:                                        break;
                    212:                                case 'd':
                    213:                                        debug |= DEBUG_DIR;
                    214:                                        break;
                    215:                                case 'f':
                    216:                                        debug |= DEBUG_FOR;
                    217:                                        break;
                    218:                                case 'g':
                    219:                                        if (modules[1] == '1') {
                    220:                                                debug |= DEBUG_GRAPH1;
                    221:                                                ++modules;
                    222:                                        }
                    223:                                        else if (modules[1] == '2') {
                    224:                                                debug |= DEBUG_GRAPH2;
                    225:                                                ++modules;
                    226:                                        }
                    227:                                        break;
                    228:                                case 'j':
                    229:                                        debug |= DEBUG_JOB;
                    230:                                        break;
                    231:                                case 'm':
                    232:                                        debug |= DEBUG_MAKE;
                    233:                                        break;
                    234:                                case 's':
                    235:                                        debug |= DEBUG_SUFF;
                    236:                                        break;
                    237:                                case 't':
                    238:                                        debug |= DEBUG_TARG;
                    239:                                        break;
                    240:                                case 'v':
                    241:                                        debug |= DEBUG_VAR;
                    242:                                        break;
                    243:                                default:
                    244:                                        (void)fprintf(stderr,
                    245:                                "make: illegal argument to d option -- %c\n",
                    246:                                            *modules);
                    247:                                        usage();
                    248:                                }
                    249:                        Var_Append(MAKEFLAGS, "-d", VAR_GLOBAL);
                    250:                        Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
                    251:                        break;
                    252:                }
                    253:                case 'e':
                    254:                        checkEnvFirst = TRUE;
                    255:                        Var_Append(MAKEFLAGS, "-e", VAR_GLOBAL);
                    256:                        break;
                    257:                case 'f':
                    258:                        (void)Lst_AtEnd(makefiles, (ClientData)optarg);
                    259:                        break;
                    260:                case 'i':
                    261:                        ignoreErrors = TRUE;
                    262:                        Var_Append(MAKEFLAGS, "-i", VAR_GLOBAL);
                    263:                        break;
                    264:                case 'j':
1.2       deraadt   265:                        forceJobs = TRUE;
1.1       deraadt   266:                        maxJobs = atoi(optarg);
1.2       deraadt   267: #ifndef REMOTE
                    268:                        maxLocal = maxJobs;
                    269: #endif
1.1       deraadt   270:                        Var_Append(MAKEFLAGS, "-j", VAR_GLOBAL);
                    271:                        Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
                    272:                        break;
                    273:                case 'k':
                    274:                        keepgoing = TRUE;
                    275:                        Var_Append(MAKEFLAGS, "-k", VAR_GLOBAL);
                    276:                        break;
                    277:                case 'n':
                    278:                        noExecute = TRUE;
                    279:                        Var_Append(MAKEFLAGS, "-n", VAR_GLOBAL);
                    280:                        break;
                    281:                case 'q':
                    282:                        queryFlag = TRUE;
                    283:                        /* Kind of nonsensical, wot? */
                    284:                        Var_Append(MAKEFLAGS, "-q", VAR_GLOBAL);
                    285:                        break;
                    286:                case 'r':
                    287:                        noBuiltins = TRUE;
                    288:                        Var_Append(MAKEFLAGS, "-r", VAR_GLOBAL);
                    289:                        break;
                    290:                case 's':
                    291:                        beSilent = TRUE;
                    292:                        Var_Append(MAKEFLAGS, "-s", VAR_GLOBAL);
                    293:                        break;
                    294:                case 't':
                    295:                        touchFlag = TRUE;
                    296:                        Var_Append(MAKEFLAGS, "-t", VAR_GLOBAL);
                    297:                        break;
                    298:                default:
                    299:                case '?':
                    300:                        usage();
                    301:                }
                    302:        }
                    303:
1.2       deraadt   304:        /*
                    305:         * Be compatible if user did not specify -j and did not explicitly
                    306:         * turned compatibility on
                    307:         */
                    308:        if (!compatMake && !forceJobs)
                    309:                compatMake = TRUE;
                    310:
1.1       deraadt   311:        oldVars = TRUE;
                    312:
                    313:        /*
                    314:         * See if the rest of the arguments are variable assignments and
                    315:         * perform them if so. Else take them to be targets and stuff them
                    316:         * on the end of the "create" list.
                    317:         */
                    318:        for (argv += optind, argc -= optind; *argv; ++argv, --argc)
1.3       deraadt   319:                if (Parse_IsVar(*argv)) {
                    320:                        char *var = strdup(*argv);
                    321:
                    322:                        Parse_DoVar(var, VAR_CMD);
                    323:                        free(var);
                    324:                } else {
1.1       deraadt   325:                        if (!**argv)
                    326:                                Punt("illegal (null) argument.");
                    327:                        if (**argv == '-') {
                    328:                                if ((*argv)[1])
                    329:                                        optind = 0;     /* -flag... */
                    330:                                else
                    331:                                        optind = 1;     /* - */
                    332:                                goto rearg;
                    333:                        }
                    334:                        (void)Lst_AtEnd(create, (ClientData)strdup(*argv));
                    335:                }
                    336: }
                    337:
                    338: /*-
                    339:  * Main_ParseArgLine --
                    340:  *     Used by the parse module when a .MFLAGS or .MAKEFLAGS target
                    341:  *     is encountered and by main() when reading the .MAKEFLAGS envariable.
                    342:  *     Takes a line of arguments and breaks it into its
                    343:  *     component words and passes those words and the number of them to the
                    344:  *     MainParseArgs function.
                    345:  *     The line should have all its leading whitespace removed.
                    346:  *
                    347:  * Results:
                    348:  *     None
                    349:  *
                    350:  * Side Effects:
                    351:  *     Only those that come from the various arguments.
                    352:  */
                    353: void
                    354: Main_ParseArgLine(line)
                    355:        char *line;                     /* Line to fracture */
                    356: {
                    357:        char **argv;                    /* Manufactured argument vector */
                    358:        int argc;                       /* Number of arguments in argv */
                    359:
                    360:        if (line == NULL)
                    361:                return;
                    362:        for (; *line == ' '; ++line)
                    363:                continue;
                    364:        if (!*line)
                    365:                return;
                    366:
                    367:        argv = brk_string(line, &argc, TRUE);
                    368:        MainParseArgs(argc, argv);
                    369: }
                    370:
                    371: /*-
                    372:  * main --
                    373:  *     The main function, for obvious reasons. Initializes variables
                    374:  *     and a few modules, then parses the arguments give it in the
                    375:  *     environment and on the command line. Reads the system makefile
                    376:  *     followed by either Makefile, makefile or the file given by the
                    377:  *     -f argument. Sets the .MAKEFLAGS PMake variable based on all the
                    378:  *     flags it has received by then uses either the Make or the Compat
                    379:  *     module to create the initial list of targets.
                    380:  *
                    381:  * Results:
                    382:  *     If -q was given, exits -1 if anything was out-of-date. Else it exits
                    383:  *     0.
                    384:  *
                    385:  * Side Effects:
                    386:  *     The program exits when done. Targets are created. etc. etc. etc.
                    387:  */
                    388: int
                    389: main(argc, argv)
                    390:        int argc;
                    391:        char **argv;
                    392: {
                    393:        Lst targs;      /* target nodes to create -- passed to Make_Init */
                    394:        Boolean outOfDate = TRUE;       /* FALSE if all targets up to date */
                    395:        struct stat sb, sa;
                    396:        char *p, *p1, *path, *pwd, *getenv(), *getwd();
                    397:        char mdpath[MAXPATHLEN + 1];
                    398:        char obpath[MAXPATHLEN + 1];
                    399:        char cdpath[MAXPATHLEN + 1];
                    400:        struct utsname utsname;
                    401:        char *machine = getenv("MACHINE");
                    402:
1.2       deraadt   403: #ifdef RLIMIT_NOFILE
                    404:        /*
                    405:         * get rid of resource limit on file descriptors
                    406:         */
                    407:        {
                    408:                struct rlimit rl;
                    409:                if (getrlimit(RLIMIT_NOFILE, &rl) != -1 &&
                    410:                    rl.rlim_cur != rl.rlim_max) {
                    411:                        rl.rlim_cur = rl.rlim_max;
                    412:                        (void) setrlimit(RLIMIT_NOFILE, &rl);
                    413:                }
                    414:        }
                    415: #endif
1.1       deraadt   416:        /*
                    417:         * Find where we are and take care of PWD for the automounter...
                    418:         * All this code is so that we know where we are when we start up
                    419:         * on a different machine with pmake.
                    420:         */
                    421:        curdir = cdpath;
                    422:        if (getcwd(curdir, MAXPATHLEN) == NULL) {
                    423:                (void)fprintf(stderr, "make: %s.\n", strerror(errno));
                    424:                exit(2);
                    425:        }
                    426:
                    427:        if (stat(curdir, &sa) == -1) {
                    428:            (void)fprintf(stderr, "make: %s: %s.\n",
                    429:                          curdir, strerror(errno));
                    430:            exit(2);
                    431:        }
                    432:
                    433:        if ((pwd = getenv("PWD")) != NULL) {
                    434:            if (stat(pwd, &sb) == 0 && sa.st_ino == sb.st_ino &&
                    435:                sa.st_dev == sb.st_dev)
                    436:                (void) strcpy(curdir, pwd);
                    437:        }
                    438:
                    439:        /*
                    440:         * Get the name of this type of MACHINE from utsname
                    441:         * so we can share an executable for similar machines.
                    442:         * (i.e. m68k: amiga hp300, mac68k, sun3, ...)
                    443:         *
                    444:         * Note that while MACHINE is decided at run-time,
                    445:         * MACHINE_ARCH is always known at compile time.
                    446:         */
                    447:        if (!machine) {
1.2       deraadt   448:            if (uname(&utsname) == -1) {
1.1       deraadt   449:                    perror("make: uname");
                    450:                    exit(2);
                    451:            }
                    452:            machine = utsname.machine;
                    453:        }
                    454:
                    455:        /*
                    456:         * if the MAKEOBJDIR (or by default, the _PATH_OBJDIR) directory
                    457:         * exists, change into it and build there.  Once things are
                    458:         * initted, have to add the original directory to the search path,
                    459:         * and modify the paths for the Makefiles apropriately.  The
                    460:         * current directory is also placed as a variable for make scripts.
                    461:         */
                    462:        if (!(path = getenv("MAKEOBJDIR"))) {
                    463:                path = _PATH_OBJDIR;
                    464:                (void) sprintf(mdpath, "%s.%s", path, machine);
                    465:        }
                    466:        else
                    467:                (void) strncpy(mdpath, path, MAXPATHLEN + 1);
                    468:
                    469:        if (stat(mdpath, &sb) == 0 && S_ISDIR(sb.st_mode)) {
                    470:
                    471:                if (chdir(mdpath)) {
                    472:                        (void)fprintf(stderr, "make warning: %s: %s.\n",
                    473:                                      mdpath, strerror(errno));
                    474:                        objdir = curdir;
                    475:                }
                    476:                else {
                    477:                        if (mdpath[0] != '/') {
                    478:                                (void) sprintf(obpath, "%s/%s", curdir, mdpath);
                    479:                                objdir = obpath;
                    480:                        }
                    481:                        else
                    482:                                objdir = mdpath;
                    483:                }
                    484:        }
                    485:        else {
                    486:                if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) {
                    487:
                    488:                        if (chdir(path)) {
                    489:                                (void)fprintf(stderr, "make warning: %s: %s.\n",
                    490:                                              path, strerror(errno));
                    491:                                objdir = curdir;
                    492:                        }
                    493:                        else {
                    494:                                if (path[0] != '/') {
                    495:                                        (void) sprintf(obpath, "%s/%s", curdir,
                    496:                                                       path);
                    497:                                        objdir = obpath;
                    498:                                }
                    499:                                else
                    500:                                        objdir = obpath;
                    501:                        }
                    502:                }
                    503:                else
                    504:                        objdir = curdir;
                    505:        }
                    506:
                    507:        setenv("PWD", objdir, 1);
                    508:
                    509:        create = Lst_Init(FALSE);
                    510:        makefiles = Lst_Init(FALSE);
                    511:        beSilent = FALSE;               /* Print commands as executed */
                    512:        ignoreErrors = FALSE;           /* Pay attention to non-zero returns */
                    513:        noExecute = FALSE;              /* Execute all commands */
                    514:        keepgoing = FALSE;              /* Stop on error */
                    515:        allPrecious = FALSE;            /* Remove targets when interrupted */
                    516:        queryFlag = FALSE;              /* This is not just a check-run */
                    517:        noBuiltins = FALSE;             /* Read the built-in rules */
                    518:        touchFlag = FALSE;              /* Actually update targets */
                    519:        usePipes = TRUE;                /* Catch child output in pipes */
                    520:        debug = 0;                      /* No debug verbosity, please. */
                    521:        jobsRunning = FALSE;
                    522:
1.2       deraadt   523:        maxLocal = DEFMAXLOCAL;         /* Set default local max concurrency */
                    524: #ifdef REMOTE
1.1       deraadt   525:        maxJobs = DEFMAXJOBS;           /* Set default max concurrency */
                    526: #else
1.2       deraadt   527:        maxJobs = maxLocal;
1.1       deraadt   528: #endif
1.2       deraadt   529:        compatMake = FALSE;             /* No compat mode */
1.1       deraadt   530:
                    531:
                    532:        /*
                    533:         * Initialize the parsing, directory and variable modules to prepare
                    534:         * for the reading of inclusion paths and variable settings on the
                    535:         * command line
                    536:         */
                    537:        Dir_Init();             /* Initialize directory structures so -I flags
                    538:                                 * can be processed correctly */
                    539:        Parse_Init();           /* Need to initialize the paths of #include
                    540:                                 * directories */
                    541:        Var_Init();             /* As well as the lists of variables for
                    542:                                 * parsing arguments */
                    543:         str_init();
                    544:        if (objdir != curdir)
                    545:                Dir_AddDir(dirSearchPath, curdir);
                    546:        Var_Set(".CURDIR", curdir, VAR_GLOBAL);
                    547:        Var_Set(".OBJDIR", objdir, VAR_GLOBAL);
                    548:
                    549:        /*
                    550:         * Initialize various variables.
                    551:         *      MAKE also gets this name, for compatibility
                    552:         *      .MAKEFLAGS gets set to the empty string just in case.
                    553:         *      MFLAGS also gets initialized empty, for compatibility.
                    554:         */
                    555:        Var_Set("MAKE", argv[0], VAR_GLOBAL);
                    556:        Var_Set(MAKEFLAGS, "", VAR_GLOBAL);
                    557:        Var_Set("MFLAGS", "", VAR_GLOBAL);
                    558:        Var_Set("MACHINE", machine, VAR_GLOBAL);
                    559: #ifdef MACHINE_ARCH
                    560:        Var_Set("MACHINE_ARCH", MACHINE_ARCH, VAR_GLOBAL);
                    561: #endif
                    562:
                    563:        /*
                    564:         * First snag any flags out of the MAKE environment variable.
                    565:         * (Note this is *not* MAKEFLAGS since /bin/make uses that and it's
                    566:         * in a different format).
                    567:         */
                    568: #ifdef POSIX
                    569:        Main_ParseArgLine(getenv("MAKEFLAGS"));
                    570: #else
                    571:        Main_ParseArgLine(getenv("MAKE"));
                    572: #endif
                    573:
                    574:        MainParseArgs(argc, argv);
                    575:
                    576:        /*
                    577:         * Initialize archive, target and suffix modules in preparation for
                    578:         * parsing the makefile(s)
                    579:         */
                    580:        Arch_Init();
                    581:        Targ_Init();
                    582:        Suff_Init();
                    583:
                    584:        DEFAULT = NILGNODE;
                    585:        (void)time(&now);
                    586:
                    587:        /*
                    588:         * Set up the .TARGETS variable to contain the list of targets to be
                    589:         * created. If none specified, make the variable empty -- the parser
                    590:         * will fill the thing in with the default or .MAIN target.
                    591:         */
                    592:        if (!Lst_IsEmpty(create)) {
                    593:                LstNode ln;
                    594:
                    595:                for (ln = Lst_First(create); ln != NILLNODE;
                    596:                    ln = Lst_Succ(ln)) {
                    597:                        char *name = (char *)Lst_Datum(ln);
                    598:
                    599:                        Var_Append(".TARGETS", name, VAR_GLOBAL);
                    600:                }
                    601:        } else
                    602:                Var_Set(".TARGETS", "", VAR_GLOBAL);
                    603:
                    604:        /*
                    605:         * Read in the built-in rules first, followed by the specified makefile,
                    606:         * if it was (makefile != (char *) NULL), or the default Makefile and
                    607:         * makefile, in that order, if it wasn't.
                    608:         */
                    609:         if (!noBuiltins && !ReadMakefile(_PATH_DEFSYSMK))
                    610:                Fatal("make: no system rules (%s).", _PATH_DEFSYSMK);
                    611:
                    612:        if (!Lst_IsEmpty(makefiles)) {
                    613:                LstNode ln;
                    614:
                    615:                ln = Lst_Find(makefiles, (ClientData)NULL, ReadMakefile);
                    616:                if (ln != NILLNODE)
                    617:                        Fatal("make: cannot open %s.", (char *)Lst_Datum(ln));
                    618:        } else if (!ReadMakefile("makefile"))
                    619:                (void)ReadMakefile("Makefile");
                    620:
                    621:        (void)ReadMakefile(".depend");
                    622:
                    623:        Var_Append("MFLAGS", Var_Value(MAKEFLAGS, VAR_GLOBAL, &p1), VAR_GLOBAL);
                    624:        if (p1)
                    625:            free(p1);
                    626:
                    627:        /* Install all the flags into the MAKE envariable. */
                    628:        if (((p = Var_Value(MAKEFLAGS, VAR_GLOBAL, &p1)) != NULL) && *p)
                    629: #ifdef POSIX
                    630:                setenv("MAKEFLAGS", p, 1);
                    631: #else
                    632:                setenv("MAKE", p, 1);
                    633: #endif
                    634:        if (p1)
                    635:            free(p1);
                    636:
                    637:        /*
                    638:         * For compatibility, look at the directories in the VPATH variable
                    639:         * and add them to the search path, if the variable is defined. The
                    640:         * variable's value is in the same format as the PATH envariable, i.e.
                    641:         * <directory>:<directory>:<directory>...
                    642:         */
                    643:        if (Var_Exists("VPATH", VAR_CMD)) {
                    644:                char *vpath, *path, *cp, savec;
                    645:                /*
                    646:                 * GCC stores string constants in read-only memory, but
                    647:                 * Var_Subst will want to write this thing, so store it
                    648:                 * in an array
                    649:                 */
                    650:                static char VPATH[] = "${VPATH}";
                    651:
                    652:                vpath = Var_Subst(NULL, VPATH, VAR_CMD, FALSE);
                    653:                path = vpath;
                    654:                do {
                    655:                        /* skip to end of directory */
                    656:                        for (cp = path; *cp != ':' && *cp != '\0'; cp++)
                    657:                                continue;
                    658:                        /* Save terminator character so know when to stop */
                    659:                        savec = *cp;
                    660:                        *cp = '\0';
                    661:                        /* Add directory to search path */
                    662:                        Dir_AddDir(dirSearchPath, path);
                    663:                        *cp = savec;
                    664:                        path = cp + 1;
                    665:                } while (savec == ':');
                    666:                (void)free((Address)vpath);
                    667:        }
                    668:
                    669:        /*
                    670:         * Now that all search paths have been read for suffixes et al, it's
                    671:         * time to add the default search path to their lists...
                    672:         */
                    673:        Suff_DoPaths();
                    674:
                    675:        /* print the initial graph, if the user requested it */
                    676:        if (DEBUG(GRAPH1))
                    677:                Targ_PrintGraph(1);
                    678:
                    679:        /*
                    680:         * Have now read the entire graph and need to make a list of targets
                    681:         * to create. If none was given on the command line, we consult the
                    682:         * parsing module to find the main target(s) to create.
                    683:         */
                    684:        if (Lst_IsEmpty(create))
                    685:                targs = Parse_MainName();
                    686:        else
                    687:                targs = Targ_FindList(create, TARG_CREATE);
                    688:
                    689:        if (!compatMake) {
                    690:                /*
                    691:                 * Initialize job module before traversing the graph, now that
                    692:                 * any .BEGIN and .END targets have been read.  This is done
                    693:                 * only if the -q flag wasn't given (to prevent the .BEGIN from
                    694:                 * being executed should it exist).
                    695:                 */
                    696:                if (!queryFlag) {
                    697:                        if (maxLocal == -1)
                    698:                                maxLocal = maxJobs;
                    699:                        Job_Init(maxJobs, maxLocal);
                    700:                        jobsRunning = TRUE;
                    701:                }
                    702:
                    703:                /* Traverse the graph, checking on all the targets */
                    704:                outOfDate = Make_Run(targs);
                    705:        } else
                    706:                /*
                    707:                 * Compat_Init will take care of creating all the targets as
                    708:                 * well as initializing the module.
                    709:                 */
                    710:                Compat_Run(targs);
                    711:
                    712:        Lst_Destroy(targs, NOFREE);
                    713:        Lst_Destroy(makefiles, NOFREE);
                    714:        Lst_Destroy(create, (void (*) __P((ClientData))) free);
                    715:
                    716:        /* print the graph now it's been processed if the user requested it */
                    717:        if (DEBUG(GRAPH2))
                    718:                Targ_PrintGraph(2);
                    719:
                    720:        Suff_End();
                    721:         Targ_End();
                    722:        Arch_End();
                    723:        str_end();
                    724:        Var_End();
                    725:        Parse_End();
                    726:        Dir_End();
                    727:
                    728:        if (queryFlag && outOfDate)
                    729:                return(1);
                    730:        else
                    731:                return(0);
                    732: }
                    733:
                    734: /*-
                    735:  * ReadMakefile  --
                    736:  *     Open and parse the given makefile.
                    737:  *
                    738:  * Results:
                    739:  *     TRUE if ok. FALSE if couldn't open file.
                    740:  *
                    741:  * Side Effects:
                    742:  *     lots
                    743:  */
                    744: static Boolean
                    745: ReadMakefile(fname)
                    746:        char *fname;            /* makefile to read */
                    747: {
                    748:        extern Lst parseIncPath, sysIncPath;
                    749:        FILE *stream;
                    750:        char *name, path[MAXPATHLEN + 1];
                    751:
                    752:        if (!strcmp(fname, "-")) {
                    753:                Parse_File("(stdin)", stdin);
                    754:                Var_Set("MAKEFILE", "", VAR_GLOBAL);
                    755:        } else {
                    756:                if ((stream = fopen(fname, "r")) != NULL)
                    757:                        goto found;
                    758:                /* if we've chdir'd, rebuild the path name */
                    759:                if (curdir != objdir && *fname != '/') {
                    760:                        (void)sprintf(path, "%s/%s", curdir, fname);
                    761:                        if ((stream = fopen(path, "r")) != NULL) {
                    762:                                fname = path;
                    763:                                goto found;
                    764:                        }
                    765:                }
                    766:                /* look in -I and system include directories. */
                    767:                name = Dir_FindFile(fname, parseIncPath);
                    768:                if (!name)
                    769:                        name = Dir_FindFile(fname, sysIncPath);
                    770:                if (!name || !(stream = fopen(name, "r")))
                    771:                        return(FALSE);
                    772:                fname = name;
                    773:                /*
                    774:                 * set the MAKEFILE variable desired by System V fans -- the
                    775:                 * placement of the setting here means it gets set to the last
                    776:                 * makefile specified, as it is set by SysV make.
                    777:                 */
                    778: found:         Var_Set("MAKEFILE", fname, VAR_GLOBAL);
                    779:                Parse_File(fname, stream);
                    780:                (void)fclose(stream);
                    781:        }
                    782:        return(TRUE);
                    783: }
                    784:
                    785: /*-
                    786:  * Error --
                    787:  *     Print an error message given its format.
                    788:  *
                    789:  * Results:
                    790:  *     None.
                    791:  *
                    792:  * Side Effects:
                    793:  *     The message is printed.
                    794:  */
                    795: /* VARARGS */
                    796: void
                    797: #if __STDC__
                    798: Error(char *fmt, ...)
                    799: #else
                    800: Error(va_alist)
                    801:        va_dcl
                    802: #endif
                    803: {
                    804:        va_list ap;
                    805: #if __STDC__
                    806:        va_start(ap, fmt);
                    807: #else
                    808:        char *fmt;
                    809:
                    810:        va_start(ap);
                    811:        fmt = va_arg(ap, char *);
                    812: #endif
                    813:        (void)vfprintf(stderr, fmt, ap);
                    814:        va_end(ap);
                    815:        (void)fprintf(stderr, "\n");
                    816:        (void)fflush(stderr);
                    817: }
                    818:
                    819: /*-
                    820:  * Fatal --
                    821:  *     Produce a Fatal error message. If jobs are running, waits for them
                    822:  *     to finish.
                    823:  *
                    824:  * Results:
                    825:  *     None
                    826:  *
                    827:  * Side Effects:
                    828:  *     The program exits
                    829:  */
                    830: /* VARARGS */
                    831: void
                    832: #if __STDC__
                    833: Fatal(char *fmt, ...)
                    834: #else
                    835: Fatal(va_alist)
                    836:        va_dcl
                    837: #endif
                    838: {
                    839:        va_list ap;
                    840: #if __STDC__
                    841:        va_start(ap, fmt);
                    842: #else
                    843:        char *fmt;
                    844:
                    845:        va_start(ap);
                    846:        fmt = va_arg(ap, char *);
                    847: #endif
                    848:        if (jobsRunning)
                    849:                Job_Wait();
                    850:
                    851:        (void)vfprintf(stderr, fmt, ap);
                    852:        va_end(ap);
                    853:        (void)fprintf(stderr, "\n");
                    854:        (void)fflush(stderr);
                    855:
                    856:        if (DEBUG(GRAPH2))
                    857:                Targ_PrintGraph(2);
                    858:        exit(2);                /* Not 1 so -q can distinguish error */
                    859: }
                    860:
                    861: /*
                    862:  * Punt --
                    863:  *     Major exception once jobs are being created. Kills all jobs, prints
                    864:  *     a message and exits.
                    865:  *
                    866:  * Results:
                    867:  *     None
                    868:  *
                    869:  * Side Effects:
                    870:  *     All children are killed indiscriminately and the program Lib_Exits
                    871:  */
                    872: /* VARARGS */
                    873: void
                    874: #if __STDC__
                    875: Punt(char *fmt, ...)
                    876: #else
                    877: Punt(va_alist)
                    878:        va_dcl
                    879: #endif
                    880: {
                    881:        va_list ap;
                    882: #if __STDC__
                    883:        va_start(ap, fmt);
                    884: #else
                    885:        char *fmt;
                    886:
                    887:        va_start(ap);
                    888:        fmt = va_arg(ap, char *);
                    889: #endif
                    890:
                    891:        (void)fprintf(stderr, "make: ");
                    892:        (void)vfprintf(stderr, fmt, ap);
                    893:        va_end(ap);
                    894:        (void)fprintf(stderr, "\n");
                    895:        (void)fflush(stderr);
                    896:
                    897:        DieHorribly();
                    898: }
                    899:
                    900: /*-
                    901:  * DieHorribly --
                    902:  *     Exit without giving a message.
                    903:  *
                    904:  * Results:
                    905:  *     None
                    906:  *
                    907:  * Side Effects:
                    908:  *     A big one...
                    909:  */
                    910: void
                    911: DieHorribly()
                    912: {
                    913:        if (jobsRunning)
                    914:                Job_AbortAll();
                    915:        if (DEBUG(GRAPH2))
                    916:                Targ_PrintGraph(2);
                    917:        exit(2);                /* Not 1, so -q can distinguish error */
                    918: }
                    919:
                    920: /*
                    921:  * Finish --
                    922:  *     Called when aborting due to errors in child shell to signal
                    923:  *     abnormal exit.
                    924:  *
                    925:  * Results:
                    926:  *     None
                    927:  *
                    928:  * Side Effects:
                    929:  *     The program exits
                    930:  */
                    931: void
                    932: Finish(errors)
                    933:        int errors;     /* number of errors encountered in Make_Make */
                    934: {
                    935:        Fatal("%d error%s", errors, errors == 1 ? "" : "s");
                    936: }
                    937:
                    938: /*
                    939:  * emalloc --
                    940:  *     malloc, but die on error.
                    941:  */
                    942: char *
                    943: emalloc(len)
                    944:        size_t len;
                    945: {
                    946:        char *p;
                    947:
                    948:        if ((p = (char *) malloc(len)) == NULL)
                    949:                enomem();
                    950:        return(p);
                    951: }
                    952:
                    953: /*
                    954:  * enomem --
                    955:  *     die when out of memory.
                    956:  */
                    957: void
                    958: enomem()
                    959: {
                    960:        (void)fprintf(stderr, "make: %s.\n", strerror(errno));
                    961:        exit(2);
1.2       deraadt   962: }
                    963:
                    964: /*
                    965:  * enunlink --
                    966:  *     Remove a file carefully, avoiding directories.
                    967:  */
                    968: int
                    969: eunlink(file)
                    970:        const char *file;
                    971: {
                    972:        struct stat st;
                    973:
                    974:        if (lstat(file, &st) == -1)
                    975:                return -1;
                    976:
                    977:        if (S_ISDIR(st.st_mode)) {
                    978:                errno = EISDIR;
                    979:                return -1;
                    980:        }
                    981:        return unlink(file);
1.1       deraadt   982: }
                    983:
                    984: /*
                    985:  * usage --
                    986:  *     exit with usage message
                    987:  */
                    988: static void
                    989: usage()
                    990: {
                    991:        (void)fprintf(stderr,
                    992: "usage: make [-eiknqrst] [-D variable] [-d flags] [-f makefile ]\n\
                    993:             [-I directory] [-j max_jobs] [variable=value]\n");
                    994:        exit(2);
                    995: }
                    996:
                    997:
                    998: int
                    999: PrintAddr(a, b)
                   1000:     ClientData a;
                   1001:     ClientData b;
                   1002: {
                   1003:     printf("%lx ", (unsigned long) a);
                   1004:     return b ? 0 : 0;
                   1005: }