[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.8

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