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

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

1.558   ! rillig      1: /*     $NetBSD: main.c,v 1.557 2021/12/27 23:11:55 rillig Exp $        */
1.19      christos    2:
1.1       cgd         3: /*
1.31      christos    4:  * Copyright (c) 1988, 1989, 1990, 1993
                      5:  *     The Regents of the University of California.  All rights reserved.
1.91      agc         6:  *
                      7:  * This code is derived from software contributed to Berkeley by
                      8:  * Adam de Boor.
                      9:  *
                     10:  * Redistribution and use in source and binary forms, with or without
                     11:  * modification, are permitted provided that the following conditions
                     12:  * are met:
                     13:  * 1. Redistributions of source code must retain the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer.
                     15:  * 2. Redistributions in binary form must reproduce the above copyright
                     16:  *    notice, this list of conditions and the following disclaimer in the
                     17:  *    documentation and/or other materials provided with the distribution.
                     18:  * 3. Neither the name of the University nor the names of its contributors
                     19:  *    may be used to endorse or promote products derived from this software
                     20:  *    without specific prior written permission.
                     21:  *
                     22:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     23:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     24:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     25:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     26:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     27:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     28:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     29:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     30:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     31:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     32:  * SUCH DAMAGE.
                     33:  */
                     34:
                     35: /*
1.1       cgd        36:  * Copyright (c) 1989 by Berkeley Softworks
                     37:  * All rights reserved.
                     38:  *
                     39:  * This code is derived from software contributed to Berkeley by
                     40:  * Adam de Boor.
                     41:  *
                     42:  * Redistribution and use in source and binary forms, with or without
                     43:  * modification, are permitted provided that the following conditions
                     44:  * are met:
                     45:  * 1. Redistributions of source code must retain the above copyright
                     46:  *    notice, this list of conditions and the following disclaimer.
                     47:  * 2. Redistributions in binary form must reproduce the above copyright
                     48:  *    notice, this list of conditions and the following disclaimer in the
                     49:  *    documentation and/or other materials provided with the distribution.
                     50:  * 3. All advertising materials mentioning features or use of this software
                     51:  *    must display the following acknowledgement:
                     52:  *     This product includes software developed by the University of
                     53:  *     California, Berkeley and its contributors.
                     54:  * 4. Neither the name of the University nor the names of its contributors
                     55:  *    may be used to endorse or promote products derived from this software
                     56:  *    without specific prior written permission.
                     57:  *
                     58:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     59:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     60:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     61:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     62:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     63:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     64:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     65:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     66:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     67:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     68:  * SUCH DAMAGE.
                     69:  */
                     70:
1.507     rillig     71: /*
                     72:  * The main file for this entire program. Exit routines etc. reside here.
1.1       cgd        73:  *
                     74:  * Utility functions defined in this file:
                     75:  *
1.521     rillig     76:  *     Main_ParseArgLine
                     77:  *                     Parse and process command line arguments from a
                     78:  *                     single string.  Used to implement the special targets
                     79:  *                     .MFLAGS and .MAKEFLAGS.
1.438     rillig     80:  *
1.521     rillig     81:  *     Error           Print a tagged error message.
1.438     rillig     82:  *
1.521     rillig     83:  *     Fatal           Print an error message and exit.
1.1       cgd        84:  *
1.521     rillig     85:  *     Punt            Abort all jobs and exit with a message.
1.1       cgd        86:  *
1.521     rillig     87:  *     Finish          Finish things up by printing the number of errors
                     88:  *                     that occurred, and exit.
1.1       cgd        89:  */
                     90:
1.13      cgd        91: #include <sys/types.h>
                     92: #include <sys/time.h>
1.1       cgd        93: #include <sys/param.h>
1.13      cgd        94: #include <sys/resource.h>
1.1       cgd        95: #include <sys/stat.h>
1.225     matt       96: #ifdef MAKE_NATIVE
                     97: #include <sys/sysctl.h>
                     98: #endif
1.17      gwr        99: #include <sys/utsname.h>
1.29      christos  100: #include <sys/wait.h>
1.85      wiz       101:
1.1       cgd       102: #include <errno.h>
1.215     christos  103: #include <signal.h>
1.85      wiz       104: #include <stdarg.h>
1.42      kleink    105: #include <time.h>
1.85      wiz       106:
1.1       cgd       107: #include "make.h"
1.13      cgd       108: #include "dir.h"
                    109: #include "job.h"
1.1       cgd       110: #include "pathnames.h"
1.58      sommerfe  111: #include "trace.h"
1.1       cgd       112:
1.337     rillig    113: /*     "@(#)main.c     8.3 (Berkeley) 3/19/94" */
1.558   ! rillig    114: MAKE_RCSID("$NetBSD: main.c,v 1.557 2021/12/27 23:11:55 rillig Exp $");
1.337     rillig    115: #if defined(MAKE_NATIVE) && !defined(lint)
1.369     rillig    116: __COPYRIGHT("@(#) Copyright (c) 1988, 1989, 1990, 1993 "
                    117:            "The Regents of the University of California.  "
                    118:            "All rights reserved.");
1.337     rillig    119: #endif
                    120:
1.391     rillig    121: CmdOpts opts;
1.453     rillig    122: time_t now;                    /* Time at start of make */
1.459     rillig    123: GNode *defaultNode;            /* .DEFAULT node */
1.534     rillig    124: bool allPrecious;              /* .PRECIOUS given on line by itself */
                    125: bool deleteOnError;            /* .DELETE_ON_ERROR: set */
1.1       cgd       126:
1.453     rillig    127: static int maxJobTokens;       /* -j argument */
1.534     rillig    128: bool enterFlagObj;             /* -w and objdir != srcdir */
1.391     rillig    129:
1.453     rillig    130: static int jp_0 = -1, jp_1 = -1; /* ends of parent job pipe */
1.534     rillig    131: bool doing_depend;             /* Set while reading .depend */
                    132: static bool jobsRunning;       /* true if the jobs might be running */
1.453     rillig    133: static const char *tracefile;
1.553     rillig    134: static bool ReadMakefile(const char *);
1.469     rillig    135: static void purge_relative_cached_realpaths(void);
1.453     rillig    136:
1.547     rillig    137: static bool ignorePWD;         /* if we use -C, PWD is meaningless */
1.453     rillig    138: static char objdir[MAXPATHLEN + 1]; /* where we chdir'ed to */
                    139: char curdir[MAXPATHLEN + 1];   /* Startup directory */
1.497     rillig    140: const char *progname;
1.176     sjg       141: char *makeDependfile;
1.183     sjg       142: pid_t myPid;
1.220     christos  143: int makelevel;
1.1       cgd       144:
1.534     rillig    145: bool forceJobs = false;
1.481     rillig    146: static int main_errors = 0;
1.469     rillig    147: static HashTable cached_realpaths;
1.58      sommerfe  148:
1.220     christos  149: /*
                    150:  * For compatibility with the POSIX version of MAKEFLAGS that includes
1.439     rillig    151:  * all the options without '-', convert 'flags' to '-f -l -a -g -s'.
1.220     christos  152:  */
                    153: static char *
                    154: explode(const char *flags)
                    155: {
1.551     rillig    156:        char *exploded, *ep;
                    157:        const char *p;
1.453     rillig    158:
                    159:        if (flags == NULL)
                    160:                return NULL;
                    161:
1.551     rillig    162:        for (p = flags; *p != '\0'; p++)
                    163:                if (!ch_isalpha(*p))
                    164:                        return bmake_strdup(flags);
                    165:
                    166:        exploded = bmake_malloc((size_t)(p - flags) * 3 + 1);
                    167:        for (p = flags, ep = exploded; *p != '\0'; p++) {
                    168:                *ep++ = '-';
                    169:                *ep++ = *p;
                    170:                *ep++ = ' ';
1.453     rillig    171:        }
1.551     rillig    172:        *ep = '\0';
                    173:        return exploded;
1.220     christos  174: }
1.279     rillig    175:
1.450     rillig    176: MAKE_ATTR_DEAD static void
                    177: usage(void)
                    178: {
1.466     rillig    179:        size_t prognameLen = strcspn(progname, "[");
1.450     rillig    180:
                    181:        (void)fprintf(stderr,
1.468     rillig    182: "usage: %.*s [-BeikNnqrSstWwX]\n"
1.450     rillig    183: "            [-C directory] [-D variable] [-d flags] [-f makefile]\n"
                    184: "            [-I directory] [-J private] [-j max_jobs] [-m directory] [-T file]\n"
                    185: "            [-V variable] [-v variable] [variable=value] [target ...]\n",
1.466     rillig    186:            (int)prognameLen, progname);
1.450     rillig    187:        exit(2);
                    188: }
                    189:
1.133     dsl       190: static void
1.522     rillig    191: MainParseArgDebugFile(const char *arg)
1.344     rillig    192: {
1.453     rillig    193:        const char *mode;
                    194:        size_t len;
                    195:        char *fname;
                    196:
                    197:        if (opts.debug_file != stdout && opts.debug_file != stderr)
                    198:                fclose(opts.debug_file);
                    199:
1.522     rillig    200:        if (*arg == '+') {
                    201:                arg++;
1.453     rillig    202:                mode = "a";
                    203:        } else
                    204:                mode = "w";
1.344     rillig    205:
1.522     rillig    206:        if (strcmp(arg, "stdout") == 0) {
1.453     rillig    207:                opts.debug_file = stdout;
                    208:                return;
                    209:        }
1.522     rillig    210:        if (strcmp(arg, "stderr") == 0) {
1.453     rillig    211:                opts.debug_file = stderr;
                    212:                return;
                    213:        }
1.344     rillig    214:
1.522     rillig    215:        len = strlen(arg);
1.453     rillig    216:        fname = bmake_malloc(len + 20);
1.522     rillig    217:        memcpy(fname, arg, len + 1);
1.453     rillig    218:
1.555     rillig    219:        /* Replace the trailing '%d' after '.%d' with the pid. */
                    220:        if (len >= 3 && memcmp(fname + len - 3, ".%d", 3) == 0)
1.453     rillig    221:                snprintf(fname + len - 2, 20, "%d", getpid());
                    222:
                    223:        opts.debug_file = fopen(fname, mode);
                    224:        if (opts.debug_file == NULL) {
1.554     rillig    225:                fprintf(stderr, "Cannot open debug file \"%s\"\n",
1.453     rillig    226:                    fname);
1.554     rillig    227:                exit(2);
1.453     rillig    228:        }
                    229:        free(fname);
1.344     rillig    230: }
                    231:
                    232: static void
1.522     rillig    233: MainParseArgDebug(const char *argvalue)
1.133     dsl       234: {
                    235:        const char *modules;
1.470     rillig    236:        DebugFlags debug = opts.debug;
1.133     dsl       237:
1.523     rillig    238:        for (modules = argvalue; *modules != '\0'; modules++) {
1.133     dsl       239:                switch (*modules) {
1.369     rillig    240:                case '0':       /* undocumented, only intended for tests */
1.543     rillig    241:                        memset(&debug, 0, sizeof(debug));
1.369     rillig    242:                        break;
1.133     dsl       243:                case 'A':
1.543     rillig    244:                        memset(&debug, ~0, sizeof(debug));
1.133     dsl       245:                        break;
                    246:                case 'a':
1.543     rillig    247:                        debug.DEBUG_ARCH = true;
1.133     dsl       248:                        break;
1.155     christos  249:                case 'C':
1.543     rillig    250:                        debug.DEBUG_CWD = true;
1.155     christos  251:                        break;
1.133     dsl       252:                case 'c':
1.543     rillig    253:                        debug.DEBUG_COND = true;
1.133     dsl       254:                        break;
                    255:                case 'd':
1.543     rillig    256:                        debug.DEBUG_DIR = true;
1.133     dsl       257:                        break;
                    258:                case 'e':
1.543     rillig    259:                        debug.DEBUG_ERROR = true;
1.133     dsl       260:                        break;
                    261:                case 'f':
1.543     rillig    262:                        debug.DEBUG_FOR = true;
1.133     dsl       263:                        break;
                    264:                case 'g':
                    265:                        if (modules[1] == '1') {
1.543     rillig    266:                                debug.DEBUG_GRAPH1 = true;
1.475     rillig    267:                                modules++;
1.444     rillig    268:                        } else if (modules[1] == '2') {
1.543     rillig    269:                                debug.DEBUG_GRAPH2 = true;
1.475     rillig    270:                                modules++;
1.444     rillig    271:                        } else if (modules[1] == '3') {
1.543     rillig    272:                                debug.DEBUG_GRAPH3 = true;
1.475     rillig    273:                                modules++;
1.133     dsl       274:                        }
                    275:                        break;
1.280     sjg       276:                case 'h':
1.543     rillig    277:                        debug.DEBUG_HASH = true;
1.280     sjg       278:                        break;
1.133     dsl       279:                case 'j':
1.543     rillig    280:                        debug.DEBUG_JOB = true;
1.133     dsl       281:                        break;
1.285     sjg       282:                case 'L':
1.534     rillig    283:                        opts.strict = true;
1.285     sjg       284:                        break;
1.146     sjg       285:                case 'l':
1.543     rillig    286:                        debug.DEBUG_LOUD = true;
1.146     sjg       287:                        break;
1.190     sjg       288:                case 'M':
1.543     rillig    289:                        debug.DEBUG_META = true;
1.190     sjg       290:                        break;
1.133     dsl       291:                case 'm':
1.543     rillig    292:                        debug.DEBUG_MAKE = true;
1.133     dsl       293:                        break;
                    294:                case 'n':
1.543     rillig    295:                        debug.DEBUG_SCRIPT = true;
1.133     dsl       296:                        break;
                    297:                case 'p':
1.543     rillig    298:                        debug.DEBUG_PARSE = true;
1.133     dsl       299:                        break;
                    300:                case 's':
1.543     rillig    301:                        debug.DEBUG_SUFF = true;
1.133     dsl       302:                        break;
                    303:                case 't':
1.543     rillig    304:                        debug.DEBUG_TARG = true;
1.133     dsl       305:                        break;
1.201     sjg       306:                case 'V':
1.534     rillig    307:                        opts.debugVflag = true;
1.201     sjg       308:                        break;
1.133     dsl       309:                case 'v':
1.543     rillig    310:                        debug.DEBUG_VAR = true;
1.133     dsl       311:                        break;
                    312:                case 'x':
1.543     rillig    313:                        debug.DEBUG_SHELL = true;
1.133     dsl       314:                        break;
                    315:                case 'F':
1.522     rillig    316:                        MainParseArgDebugFile(modules + 1);
1.153     apb       317:                        goto debug_setbuf;
1.133     dsl       318:                default:
                    319:                        (void)fprintf(stderr,
                    320:                            "%s: illegal argument to d option -- %c\n",
                    321:                            progname, *modules);
                    322:                        usage();
                    323:                }
                    324:        }
1.471     rillig    325:
                    326: debug_setbuf:
1.470     rillig    327:        opts.debug = debug;
1.453     rillig    328:
1.153     apb       329:        /*
                    330:         * Make the debug_file unbuffered, and make
                    331:         * stdout line buffered (unless debugfile == stdout).
                    332:         */
1.391     rillig    333:        setvbuf(opts.debug_file, NULL, _IONBF, 0);
                    334:        if (opts.debug_file != stdout) {
1.153     apb       335:                setvbuf(stdout, NULL, _IOLBF, 0);
                    336:        }
1.133     dsl       337: }
                    338:
1.521     rillig    339: /* Is path relative, or does it contain any relative component "." or ".."? */
1.534     rillig    340: static bool
1.522     rillig    341: IsRelativePath(const char *path)
1.264     sjg       342: {
1.540     rillig    343:        const char *p;
1.264     sjg       344:
                    345:        if (path[0] != '/')
1.534     rillig    346:                return true;
1.540     rillig    347:        p = path;
                    348:        while ((p = strstr(p, "/.")) != NULL) {
                    349:                p += 2;
                    350:                if (*p == '.')
                    351:                        p++;
                    352:                if (*p == '/' || *p == '\0')
1.534     rillig    353:                        return true;
1.286     rillig    354:        }
1.534     rillig    355:        return false;
1.264     sjg       356: }
                    357:
1.355     rillig    358: static void
                    359: MainParseArgChdir(const char *argvalue)
                    360: {
                    361:        struct stat sa, sb;
                    362:
                    363:        if (chdir(argvalue) == -1) {
                    364:                (void)fprintf(stderr, "%s: chdir %s: %s\n",
                    365:                    progname, argvalue, strerror(errno));
1.505     rillig    366:                exit(2);        /* Not 1 so -q can distinguish error */
1.355     rillig    367:        }
                    368:        if (getcwd(curdir, MAXPATHLEN) == NULL) {
                    369:                (void)fprintf(stderr, "%s: %s.\n", progname, strerror(errno));
                    370:                exit(2);
                    371:        }
1.522     rillig    372:        if (!IsRelativePath(argvalue) &&
1.355     rillig    373:            stat(argvalue, &sa) != -1 &&
                    374:            stat(curdir, &sb) != -1 &&
                    375:            sa.st_ino == sb.st_ino &&
                    376:            sa.st_dev == sb.st_dev)
                    377:                strncpy(curdir, argvalue, MAXPATHLEN);
1.534     rillig    378:        ignorePWD = true;
1.355     rillig    379: }
                    380:
1.356     rillig    381: static void
                    382: MainParseArgJobsInternal(const char *argvalue)
                    383: {
1.440     rillig    384:        char end;
                    385:        if (sscanf(argvalue, "%d,%d%c", &jp_0, &jp_1, &end) != 2) {
1.356     rillig    386:                (void)fprintf(stderr,
1.453     rillig    387:                    "%s: internal error -- J option malformed (%s)\n",
                    388:                    progname, argvalue);
1.356     rillig    389:                usage();
                    390:        }
                    391:        if ((fcntl(jp_0, F_GETFD, 0) < 0) ||
                    392:            (fcntl(jp_1, F_GETFD, 0) < 0)) {
                    393: #if 0
                    394:                (void)fprintf(stderr,
                    395:                    "%s: ###### warning -- J descriptors were closed!\n",
                    396:                    progname);
                    397:                exit(2);
                    398: #endif
                    399:                jp_0 = -1;
                    400:                jp_1 = -1;
1.534     rillig    401:                opts.compatMake = true;
1.356     rillig    402:        } else {
1.529     rillig    403:                Global_Append(MAKEFLAGS, "-J");
                    404:                Global_Append(MAKEFLAGS, argvalue);
1.356     rillig    405:        }
                    406: }
                    407:
                    408: static void
                    409: MainParseArgJobs(const char *argvalue)
                    410: {
                    411:        char *p;
                    412:
1.534     rillig    413:        forceJobs = true;
1.391     rillig    414:        opts.maxJobs = (int)strtol(argvalue, &p, 0);
                    415:        if (*p != '\0' || opts.maxJobs < 1) {
1.356     rillig    416:                (void)fprintf(stderr,
                    417:                    "%s: illegal argument to -j -- must be positive integer!\n",
                    418:                    progname);
1.505     rillig    419:                exit(2);        /* Not 1 so -q can distinguish error */
1.356     rillig    420:        }
1.529     rillig    421:        Global_Append(MAKEFLAGS, "-j");
                    422:        Global_Append(MAKEFLAGS, argvalue);
1.528     rillig    423:        Global_Set(".MAKE.JOBS", argvalue);
1.391     rillig    424:        maxJobTokens = opts.maxJobs;
1.356     rillig    425: }
                    426:
1.357     rillig    427: static void
                    428: MainParseArgSysInc(const char *argvalue)
                    429: {
                    430:        /* look for magic parent directory search string */
                    431:        if (strncmp(".../", argvalue, 4) == 0) {
1.371     rillig    432:                char *found_path = Dir_FindHereOrAbove(curdir, argvalue + 4);
                    433:                if (found_path == NULL)
1.357     rillig    434:                        return;
1.516     rillig    435:                (void)SearchPath_Add(sysIncPath, found_path);
1.371     rillig    436:                free(found_path);
1.357     rillig    437:        } else {
1.516     rillig    438:                (void)SearchPath_Add(sysIncPath, argvalue);
1.357     rillig    439:        }
1.529     rillig    440:        Global_Append(MAKEFLAGS, "-m");
                    441:        Global_Append(MAKEFLAGS, argvalue);
1.357     rillig    442: }
                    443:
1.534     rillig    444: static bool
1.360     rillig    445: MainParseArg(char c, const char *argvalue)
1.354     rillig    446: {
                    447:        switch (c) {
                    448:        case '\0':
                    449:                break;
                    450:        case 'B':
1.534     rillig    451:                opts.compatMake = true;
1.529     rillig    452:                Global_Append(MAKEFLAGS, "-B");
1.528     rillig    453:                Global_Set(MAKE_MODE, "compat");
1.354     rillig    454:                break;
                    455:        case 'C':
1.355     rillig    456:                MainParseArgChdir(argvalue);
1.354     rillig    457:                break;
                    458:        case 'D':
1.546     rillig    459:                if (argvalue[0] == '\0')
                    460:                        return false;
1.527     rillig    461:                Global_SetExpand(argvalue, "1");
1.529     rillig    462:                Global_Append(MAKEFLAGS, "-D");
                    463:                Global_Append(MAKEFLAGS, argvalue);
1.354     rillig    464:                break;
                    465:        case 'I':
                    466:                Parse_AddIncludeDir(argvalue);
1.529     rillig    467:                Global_Append(MAKEFLAGS, "-I");
                    468:                Global_Append(MAKEFLAGS, argvalue);
1.354     rillig    469:                break;
                    470:        case 'J':
1.356     rillig    471:                MainParseArgJobsInternal(argvalue);
1.354     rillig    472:                break;
                    473:        case 'N':
1.534     rillig    474:                opts.noExecute = true;
                    475:                opts.noRecursiveExecute = true;
1.529     rillig    476:                Global_Append(MAKEFLAGS, "-N");
1.354     rillig    477:                break;
                    478:        case 'S':
1.534     rillig    479:                opts.keepgoing = false;
1.529     rillig    480:                Global_Append(MAKEFLAGS, "-S");
1.354     rillig    481:                break;
                    482:        case 'T':
                    483:                tracefile = bmake_strdup(argvalue);
1.529     rillig    484:                Global_Append(MAKEFLAGS, "-T");
                    485:                Global_Append(MAKEFLAGS, argvalue);
1.354     rillig    486:                break;
                    487:        case 'V':
                    488:        case 'v':
1.437     rillig    489:                opts.printVars = c == 'v' ? PVM_EXPANDED : PVM_UNEXPANDED;
1.485     rillig    490:                Lst_Append(&opts.variables, bmake_strdup(argvalue));
1.391     rillig    491:                /* XXX: Why always -V? */
1.529     rillig    492:                Global_Append(MAKEFLAGS, "-V");
                    493:                Global_Append(MAKEFLAGS, argvalue);
1.354     rillig    494:                break;
                    495:        case 'W':
1.534     rillig    496:                opts.parseWarnFatal = true;
1.550     rillig    497:                /* XXX: why no Global_Append? */
1.354     rillig    498:                break;
                    499:        case 'X':
1.534     rillig    500:                opts.varNoExportEnv = true;
1.529     rillig    501:                Global_Append(MAKEFLAGS, "-X");
1.354     rillig    502:                break;
                    503:        case 'd':
                    504:                /* If '-d-opts' don't pass to children */
                    505:                if (argvalue[0] == '-')
                    506:                        argvalue++;
                    507:                else {
1.529     rillig    508:                        Global_Append(MAKEFLAGS, "-d");
                    509:                        Global_Append(MAKEFLAGS, argvalue);
1.354     rillig    510:                }
1.522     rillig    511:                MainParseArgDebug(argvalue);
1.354     rillig    512:                break;
                    513:        case 'e':
1.534     rillig    514:                opts.checkEnvFirst = true;
1.529     rillig    515:                Global_Append(MAKEFLAGS, "-e");
1.354     rillig    516:                break;
                    517:        case 'f':
1.484     rillig    518:                Lst_Append(&opts.makefiles, bmake_strdup(argvalue));
1.354     rillig    519:                break;
                    520:        case 'i':
1.534     rillig    521:                opts.ignoreErrors = true;
1.529     rillig    522:                Global_Append(MAKEFLAGS, "-i");
1.354     rillig    523:                break;
                    524:        case 'j':
1.356     rillig    525:                MainParseArgJobs(argvalue);
1.354     rillig    526:                break;
                    527:        case 'k':
1.534     rillig    528:                opts.keepgoing = true;
1.529     rillig    529:                Global_Append(MAKEFLAGS, "-k");
1.354     rillig    530:                break;
                    531:        case 'm':
1.357     rillig    532:                MainParseArgSysInc(argvalue);
1.441     rillig    533:                /* XXX: why no Var_Append? */
1.354     rillig    534:                break;
                    535:        case 'n':
1.534     rillig    536:                opts.noExecute = true;
1.529     rillig    537:                Global_Append(MAKEFLAGS, "-n");
1.354     rillig    538:                break;
                    539:        case 'q':
1.549     rillig    540:                opts.query = true;
1.354     rillig    541:                /* Kind of nonsensical, wot? */
1.529     rillig    542:                Global_Append(MAKEFLAGS, "-q");
1.354     rillig    543:                break;
                    544:        case 'r':
1.534     rillig    545:                opts.noBuiltins = true;
1.529     rillig    546:                Global_Append(MAKEFLAGS, "-r");
1.354     rillig    547:                break;
                    548:        case 's':
1.549     rillig    549:                opts.silent = true;
1.529     rillig    550:                Global_Append(MAKEFLAGS, "-s");
1.354     rillig    551:                break;
                    552:        case 't':
1.549     rillig    553:                opts.touch = true;
1.529     rillig    554:                Global_Append(MAKEFLAGS, "-t");
1.354     rillig    555:                break;
                    556:        case 'w':
1.534     rillig    557:                opts.enterFlag = true;
1.529     rillig    558:                Global_Append(MAKEFLAGS, "-w");
1.354     rillig    559:                break;
                    560:        default:
                    561:        case '?':
                    562:                usage();
                    563:        }
1.534     rillig    564:        return true;
1.354     rillig    565: }
                    566:
1.507     rillig    567: /*
                    568:  * Parse the given arguments.  Called from main() and from
1.345     rillig    569:  * Main_ParseArgLine() when the .MAKEFLAGS target is used.
1.1       cgd       570:  *
1.345     rillig    571:  * The arguments must be treated as read-only and will be freed after the
                    572:  * call.
1.1       cgd       573:  *
1.507     rillig    574:  * XXX: Deal with command line overriding .MAKEFLAGS in makefile
                    575:  */
1.1       cgd       576: static void
1.149     christos  577: MainParseArgs(int argc, char **argv)
1.1       cgd       578: {
1.360     rillig    579:        char c;
1.98      ross      580:        int arginc;
1.133     dsl       581:        char *argvalue;
1.98      ross      582:        char *optscan;
1.534     rillig    583:        bool inOption, dashDash = false;
1.1       cgd       584:
1.359     rillig    585:        const char *optspecs = "BC:D:I:J:NST:V:WXd:ef:ij:km:nqrstv:w";
1.98      ross      586: /* Can't actually use getopt(3) because rescanning is not portable */
                    587:
1.279     rillig    588: rearg:
1.534     rillig    589:        inOption = false;
1.108     lukem     590:        optscan = NULL;
1.358     rillig    591:        while (argc > 1) {
1.359     rillig    592:                const char *optspec;
1.358     rillig    593:                if (!inOption)
1.98      ross      594:                        optscan = argv[1];
                    595:                c = *optscan++;
                    596:                arginc = 0;
1.358     rillig    597:                if (inOption) {
                    598:                        if (c == '\0') {
1.475     rillig    599:                                argv++;
                    600:                                argc--;
1.534     rillig    601:                                inOption = false;
1.98      ross      602:                                continue;
                    603:                        }
                    604:                } else {
1.101     ross      605:                        if (c != '-' || dashDash)
1.98      ross      606:                                break;
1.534     rillig    607:                        inOption = true;
1.98      ross      608:                        c = *optscan++;
                    609:                }
                    610:                /* '-' found at some earlier point */
1.359     rillig    611:                optspec = strchr(optspecs, c);
                    612:                if (c != '\0' && optspec != NULL && optspec[1] == ':') {
1.547     rillig    613:                        /*
                    614:                         * -<something> found, and <something> should have an
                    615:                         * argument
                    616:                         */
1.534     rillig    617:                        inOption = false;
1.98      ross      618:                        arginc = 1;
                    619:                        argvalue = optscan;
1.358     rillig    620:                        if (*argvalue == '\0') {
1.122     christos  621:                                if (argc < 3)
                    622:                                        goto noarg;
1.98      ross      623:                                argvalue = argv[2];
                    624:                                arginc = 2;
                    625:                        }
1.108     lukem     626:                } else {
1.279     rillig    627:                        argvalue = NULL;
1.98      ross      628:                }
1.354     rillig    629:                switch (c) {
1.98      ross      630:                case '\0':
1.358     rillig    631:                        arginc = 1;
1.534     rillig    632:                        inOption = false;
1.358     rillig    633:                        break;
1.101     ross      634:                case '-':
1.534     rillig    635:                        dashDash = true;
1.358     rillig    636:                        break;
1.1       cgd       637:                default:
1.358     rillig    638:                        if (!MainParseArg(c, argvalue))
                    639:                                goto noarg;
1.1       cgd       640:                }
1.98      ross      641:                argv += arginc;
                    642:                argc -= arginc;
1.1       cgd       643:        }
                    644:
                    645:        /*
                    646:         * See if the rest of the arguments are variable assignments and
                    647:         * perform them if so. Else take them to be targets and stuff them
                    648:         * on the end of the "create" list.
                    649:         */
1.523     rillig    650:        for (; argc > 1; argv++, argc--) {
1.369     rillig    651:                VarAssign var;
                    652:                if (Parse_IsVar(argv[1], &var)) {
1.536     rillig    653:                        Parse_Var(&var, SCOPE_CMDLINE);
1.67      sjg       654:                } else {
1.460     rillig    655:                        if (argv[1][0] == '\0')
1.1       cgd       656:                                Punt("illegal (null) argument.");
1.460     rillig    657:                        if (argv[1][0] == '-' && !dashDash)
1.1       cgd       658:                                goto rearg;
1.486     rillig    659:                        Lst_Append(&opts.create, bmake_strdup(argv[1]));
1.1       cgd       660:                }
1.369     rillig    661:        }
1.122     christos  662:
                    663:        return;
                    664: noarg:
                    665:        (void)fprintf(stderr, "%s: option requires an argument -- %c\n",
                    666:            progname, c);
                    667:        usage();
1.1       cgd       668: }
                    669:
1.507     rillig    670: /*
                    671:  * Break a line of arguments into words and parse them.
1.85      wiz       672:  *
1.361     rillig    673:  * Used when a .MFLAGS or .MAKEFLAGS target is encountered during parsing and
1.507     rillig    674:  * by main() when reading the MAKEFLAGS environment variable.
                    675:  */
1.1       cgd       676: void
1.161     dsl       677: Main_ParseArgLine(const char *line)
1.1       cgd       678: {
1.331     rillig    679:        Words words;
1.296     rillig    680:        char *buf;
1.1       cgd       681:
                    682:        if (line == NULL)
                    683:                return;
1.496     rillig    684:        /* XXX: don't use line as an iterator variable */
1.523     rillig    685:        for (; *line == ' '; line++)
1.13      cgd       686:                continue;
1.442     rillig    687:        if (line[0] == '\0')
1.1       cgd       688:                return;
                    689:
1.442     rillig    690:        {
1.532     rillig    691:                FStr argv0 = Var_Value(SCOPE_GLOBAL, ".MAKE");
1.499     rillig    692:                buf = str_concat3(argv0.str, " ", line);
                    693:                FStr_Done(&argv0);
1.442     rillig    694:        }
1.40      christos  695:
1.534     rillig    696:        words = Str_Words(buf, true);
1.331     rillig    697:        if (words.words == NULL) {
1.159     christos  698:                Error("Unterminated quoted string [%s]", buf);
                    699:                free(buf);
                    700:                return;
                    701:        }
1.45      itohy     702:        free(buf);
1.331     rillig    703:        MainParseArgs((int)words.len, words.words);
1.40      christos  704:
1.331     rillig    705:        Words_Free(words);
1.1       cgd       706: }
                    707:
1.534     rillig    708: bool
                    709: Main_SetObjdir(bool writable, const char *fmt, ...)
1.31      christos  710: {
                    711:        struct stat sb;
1.260     christos  712:        char *path;
                    713:        char buf[MAXPATHLEN + 1];
1.265     sjg       714:        char buf2[MAXPATHLEN + 1];
1.534     rillig    715:        bool rc = false;
1.252     christos  716:        va_list ap;
                    717:
                    718:        va_start(ap, fmt);
1.260     christos  719:        vsnprintf(path = buf, MAXPATHLEN, fmt, ap);
1.252     christos  720:        va_end(ap);
1.31      christos  721:
1.74      tv        722:        if (path[0] != '/') {
1.263     sjg       723:                snprintf(buf2, MAXPATHLEN, "%s/%s", curdir, path);
                    724:                path = buf2;
1.74      tv        725:        }
                    726:
                    727:        /* look for the directory and try to chdir there */
1.31      christos  728:        if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) {
1.456     sjg       729:                if ((writable && access(path, W_OK) != 0) ||
1.433     rillig    730:                    (chdir(path) != 0)) {
1.463     rillig    731:                        (void)fprintf(stderr, "%s warning: %s: %s.\n",
                    732:                            progname, path, strerror(errno));
1.74      tv        733:                } else {
1.295     rillig    734:                        snprintf(objdir, sizeof objdir, "%s", path);
1.528     rillig    735:                        Global_Set(".OBJDIR", objdir);
1.74      tv        736:                        setenv("PWD", objdir, 1);
1.79      tv        737:                        Dir_InitDot();
1.469     rillig    738:                        purge_relative_cached_realpaths();
1.534     rillig    739:                        rc = true;
1.391     rillig    740:                        if (opts.enterFlag && strcmp(objdir, curdir) != 0)
1.534     rillig    741:                                enterFlagObj = true;
1.31      christos  742:                }
                    743:        }
                    744:
1.74      tv        745:        return rc;
1.31      christos  746: }
                    747:
1.534     rillig    748: static bool
                    749: SetVarObjdir(bool writable, const char *var, const char *suffix)
1.252     christos  750: {
1.532     rillig    751:        FStr path = Var_Value(SCOPE_CMDLINE, var);
1.296     rillig    752:
1.499     rillig    753:        if (path.str == NULL || path.str[0] == '\0') {
                    754:                FStr_Done(&path);
1.534     rillig    755:                return false;
1.288     rillig    756:        }
1.252     christos  757:
1.260     christos  758:        /* expand variable substitutions */
1.499     rillig    759:        if (strchr(path.str, '$') != 0) {
                    760:                char *expanded;
1.530     rillig    761:                (void)Var_Subst(path.str, SCOPE_GLOBAL, VARE_WANTRES, &expanded);
1.341     rillig    762:                /* TODO: handle errors */
1.556     rillig    763:                FStr_Done(&path);
                    764:                path = FStr_InitOwn(expanded);
1.341     rillig    765:        }
1.260     christos  766:
1.556     rillig    767:        (void)Main_SetObjdir(writable, "%s%s", path.str, suffix);
1.260     christos  768:
1.499     rillig    769:        FStr_Done(&path);
1.534     rillig    770:        return true;
1.252     christos  771: }
                    772:
1.507     rillig    773: /*
                    774:  * Splits str into words, adding them to the list.
                    775:  * The string must be kept alive as long as the list.
                    776:  */
1.197     sjg       777: int
1.462     rillig    778: str2Lst_Append(StringList *lp, char *str)
1.176     sjg       779: {
1.453     rillig    780:        char *cp;
                    781:        int n;
1.176     sjg       782:
1.462     rillig    783:        const char *sep = " \t";
1.176     sjg       784:
1.512     rillig    785:        for (n = 0, cp = strtok(str, sep); cp != NULL; cp = strtok(NULL, sep)) {
1.453     rillig    786:                Lst_Append(lp, cp);
                    787:                n++;
                    788:        }
                    789:        return n;
1.176     sjg       790: }
                    791:
1.167     christos  792: #ifdef SIGINFO
                    793: /*ARGSUSED*/
                    794: static void
1.200     joerg     795: siginfo(int signo MAKE_ATTR_UNUSED)
1.167     christos  796: {
                    797:        char dir[MAXPATHLEN];
                    798:        char str[2 * MAXPATHLEN];
                    799:        int len;
1.426     rillig    800:        if (getcwd(dir, sizeof dir) == NULL)
1.167     christos  801:                return;
1.426     rillig    802:        len = snprintf(str, sizeof str, "%s: Working in: %s\n", progname, dir);
1.167     christos  803:        if (len > 0)
                    804:                (void)write(STDERR_FILENO, str, (size_t)len);
                    805: }
                    806: #endif
                    807:
1.500     rillig    808: /* Allow makefiles some control over the mode we run in. */
                    809: static void
                    810: MakeMode(void)
1.176     sjg       811: {
1.524     rillig    812:        char *mode;
1.176     sjg       813:
1.530     rillig    814:        (void)Var_Subst("${" MAKE_MODE ":tl}", SCOPE_GLOBAL, VARE_WANTRES, &mode);
1.524     rillig    815:        /* TODO: handle errors */
1.176     sjg       816:
1.524     rillig    817:        if (mode[0] != '\0') {
                    818:                if (strstr(mode, "compat") != NULL) {
1.534     rillig    819:                        opts.compatMake = true;
                    820:                        forceJobs = false;
1.453     rillig    821:                }
1.190     sjg       822: #if USE_META
1.524     rillig    823:                if (strstr(mode, "meta") != NULL)
                    824:                        meta_mode_init(mode);
1.190     sjg       825: #endif
1.453     rillig    826:        }
1.238     christos  827:
1.524     rillig    828:        free(mode);
1.176     sjg       829: }
                    830:
1.266     christos  831: static void
1.534     rillig    832: PrintVar(const char *varname, bool expandVars)
1.383     rillig    833: {
1.508     rillig    834:        if (strchr(varname, '$') != NULL) {
1.384     rillig    835:                char *evalue;
1.530     rillig    836:                (void)Var_Subst(varname, SCOPE_GLOBAL, VARE_WANTRES, &evalue);
1.383     rillig    837:                /* TODO: handle errors */
1.384     rillig    838:                printf("%s\n", evalue);
1.545     rillig    839:                free(evalue);
1.384     rillig    840:
1.383     rillig    841:        } else if (expandVars) {
                    842:                char *expr = str_concat3("${", varname, "}");
1.384     rillig    843:                char *evalue;
1.530     rillig    844:                (void)Var_Subst(expr, SCOPE_GLOBAL, VARE_WANTRES, &evalue);
1.383     rillig    845:                /* TODO: handle errors */
                    846:                free(expr);
1.384     rillig    847:                printf("%s\n", evalue);
1.545     rillig    848:                free(evalue);
1.384     rillig    849:
1.383     rillig    850:        } else {
1.532     rillig    851:                FStr value = Var_Value(SCOPE_GLOBAL, varname);
1.499     rillig    852:                printf("%s\n", value.str != NULL ? value.str : "");
                    853:                FStr_Done(&value);
1.383     rillig    854:        }
                    855: }
                    856:
1.432     rillig    857: /*
1.534     rillig    858:  * Return a bool based on a variable.
1.432     rillig    859:  *
                    860:  * If the knob is not set, return the fallback.
                    861:  * If set, anything that looks or smells like "No", "False", "Off", "0", etc.
1.534     rillig    862:  * is false, otherwise true.
1.432     rillig    863:  */
1.534     rillig    864: static bool
1.538     rillig    865: GetBooleanExpr(const char *expr, bool fallback)
1.432     rillig    866: {
1.453     rillig    867:        char *value;
1.534     rillig    868:        bool res;
1.453     rillig    869:
1.530     rillig    870:        (void)Var_Subst(expr, SCOPE_GLOBAL, VARE_WANTRES, &value);
1.453     rillig    871:        /* TODO: handle errors */
                    872:        res = ParseBoolean(value, fallback);
                    873:        free(value);
                    874:        return res;
1.432     rillig    875: }
                    876:
1.383     rillig    877: static void
1.266     christos  878: doPrintVars(void)
                    879: {
1.338     rillig    880:        StringListNode *ln;
1.534     rillig    881:        bool expandVars;
1.266     christos  882:
1.437     rillig    883:        if (opts.printVars == PVM_EXPANDED)
1.534     rillig    884:                expandVars = true;
1.394     rillig    885:        else if (opts.debugVflag)
1.534     rillig    886:                expandVars = false;
1.266     christos  887:        else
1.538     rillig    888:                expandVars = GetBooleanExpr("${.MAKE.EXPAND_VARIABLES}",
                    889:                    false);
1.266     christos  890:
1.485     rillig    891:        for (ln = opts.variables.first; ln != NULL; ln = ln->next) {
1.383     rillig    892:                const char *varname = ln->datum;
                    893:                PrintVar(varname, expandVars);
1.266     christos  894:        }
                    895: }
                    896:
1.534     rillig    897: static bool
1.266     christos  898: runTargets(void)
                    899: {
1.488     rillig    900:        GNodeList targs = LST_INIT;     /* target nodes to create */
1.547     rillig    901:        bool outOfDate;         /* false if all targets up to date */
1.266     christos  902:
                    903:        /*
                    904:         * Have now read the entire graph and need to make a list of
                    905:         * targets to create. If none was given on the command line,
                    906:         * we consult the parsing module to find the main target(s)
                    907:         * to create.
                    908:         */
1.486     rillig    909:        if (Lst_IsEmpty(&opts.create))
1.488     rillig    910:                Parse_MainName(&targs);
1.266     christos  911:        else
1.488     rillig    912:                Targ_FindList(&targs, &opts.create);
1.266     christos  913:
1.391     rillig    914:        if (!opts.compatMake) {
1.266     christos  915:                /*
                    916:                 * Initialize job module before traversing the graph
                    917:                 * now that any .BEGIN and .END targets have been read.
                    918:                 * This is done only if the -q flag wasn't given
                    919:                 * (to prevent the .BEGIN from being executed should
                    920:                 * it exist).
                    921:                 */
1.549     rillig    922:                if (!opts.query) {
1.266     christos  923:                        Job_Init();
1.534     rillig    924:                        jobsRunning = true;
1.266     christos  925:                }
                    926:
                    927:                /* Traverse the graph, checking on all the targets */
1.488     rillig    928:                outOfDate = Make_Run(&targs);
1.266     christos  929:        } else {
                    930:                /*
                    931:                 * Compat_Init will take care of creating all the
                    932:                 * targets as well as initializing the module.
                    933:                 */
1.488     rillig    934:                Compat_Run(&targs);
1.534     rillig    935:                outOfDate = false;
1.266     christos  936:        }
1.525     rillig    937:        Lst_Done(&targs);       /* Don't free the targets themselves. */
1.266     christos  938:        return outOfDate;
                    939: }
                    940:
1.343     rillig    941: /*
                    942:  * Set up the .TARGETS variable to contain the list of targets to be
                    943:  * created. If none specified, make the variable empty -- the parser
                    944:  * will fill the thing in with the default or .MAIN target.
                    945:  */
                    946: static void
                    947: InitVarTargets(void)
                    948: {
                    949:        StringListNode *ln;
                    950:
1.486     rillig    951:        if (Lst_IsEmpty(&opts.create)) {
1.528     rillig    952:                Global_Set(".TARGETS", "");
1.343     rillig    953:                return;
                    954:        }
                    955:
1.486     rillig    956:        for (ln = opts.create.first; ln != NULL; ln = ln->next) {
1.525     rillig    957:                const char *name = ln->datum;
1.529     rillig    958:                Global_Append(".TARGETS", name);
1.343     rillig    959:        }
                    960: }
                    961:
1.404     rillig    962: static void
                    963: InitRandom(void)
                    964: {
                    965:        struct timeval tv;
                    966:
                    967:        gettimeofday(&tv, NULL);
                    968:        srandom((unsigned int)(tv.tv_sec + tv.tv_usec));
                    969: }
                    970:
1.369     rillig    971: static const char *
1.525     rillig    972: InitVarMachine(const struct utsname *utsname MAKE_ATTR_UNUSED)
1.369     rillig    973: {
                    974:        const char *machine = getenv("MACHINE");
                    975:        if (machine != NULL)
                    976:                return machine;
                    977:
1.458     rillig    978: #if defined(MAKE_NATIVE)
1.369     rillig    979:        return utsname->machine;
1.458     rillig    980: #elif defined(MAKE_MACHINE)
1.369     rillig    981:        return MAKE_MACHINE;
                    982: #else
                    983:        return "unknown";
                    984: #endif
                    985: }
                    986:
                    987: static const char *
1.451     rillig    988: InitVarMachineArch(void)
1.369     rillig    989: {
                    990:        const char *env = getenv("MACHINE_ARCH");
                    991:        if (env != NULL)
                    992:                return env;
                    993:
                    994: #ifdef MAKE_NATIVE
                    995:        {
                    996:                struct utsname utsname;
1.426     rillig    997:                static char machine_arch_buf[sizeof utsname.machine];
1.369     rillig    998:                const int mib[2] = { CTL_HW, HW_MACHINE_ARCH };
1.426     rillig    999:                size_t len = sizeof machine_arch_buf;
1.369     rillig   1000:
1.510     rillig   1001:                if (sysctl(mib, (unsigned int)__arraycount(mib),
                   1002:                    machine_arch_buf, &len, NULL, 0) < 0) {
                   1003:                        (void)fprintf(stderr, "%s: sysctl failed (%s).\n",
                   1004:                            progname, strerror(errno));
                   1005:                        exit(2);
1.369     rillig   1006:                }
                   1007:
                   1008:                return machine_arch_buf;
                   1009:        }
1.457     rillig   1010: #elif defined(MACHINE_ARCH)
                   1011:        return MACHINE_ARCH;
                   1012: #elif defined(MAKE_MACHINE_ARCH)
1.369     rillig   1013:        return MAKE_MACHINE_ARCH;
                   1014: #else
                   1015:        return "unknown";
                   1016: #endif
                   1017: }
                   1018:
1.381     rillig   1019: #ifndef NO_PWD_OVERRIDE
                   1020: /*
                   1021:  * All this code is so that we know where we are when we start up
                   1022:  * on a different machine with pmake.
1.382     rillig   1023:  *
1.525     rillig   1024:  * XXX: Make no longer has "local" and "remote" mode.  Is this code still
                   1025:  * necessary?
                   1026:  *
1.381     rillig   1027:  * Overriding getcwd() with $PWD totally breaks MAKEOBJDIRPREFIX
                   1028:  * since the value of curdir can vary depending on how we got
                   1029:  * here.  Ie sitting at a shell prompt (shell that provides $PWD)
                   1030:  * or via subdir.mk in which case its likely a shell which does
                   1031:  * not provide it.
1.382     rillig   1032:  *
1.381     rillig   1033:  * So, to stop it breaking this case only, we ignore PWD if
1.382     rillig   1034:  * MAKEOBJDIRPREFIX is set or MAKEOBJDIR contains a variable expression.
1.381     rillig   1035:  */
                   1036: static void
1.382     rillig   1037: HandlePWD(const struct stat *curdir_st)
1.381     rillig   1038: {
1.382     rillig   1039:        char *pwd;
1.499     rillig   1040:        FStr prefix, makeobjdir;
1.382     rillig   1041:        struct stat pwd_st;
1.381     rillig   1042:
                   1043:        if (ignorePWD || (pwd = getenv("PWD")) == NULL)
                   1044:                return;
                   1045:
1.532     rillig   1046:        prefix = Var_Value(SCOPE_CMDLINE, "MAKEOBJDIRPREFIX");
1.499     rillig   1047:        if (prefix.str != NULL) {
                   1048:                FStr_Done(&prefix);
1.382     rillig   1049:                return;
1.381     rillig   1050:        }
1.382     rillig   1051:
1.532     rillig   1052:        makeobjdir = Var_Value(SCOPE_CMDLINE, "MAKEOBJDIR");
1.499     rillig   1053:        if (makeobjdir.str != NULL && strchr(makeobjdir.str, '$') != NULL)
1.382     rillig   1054:                goto ignore_pwd;
                   1055:
                   1056:        if (stat(pwd, &pwd_st) == 0 &&
                   1057:            curdir_st->st_ino == pwd_st.st_ino &&
                   1058:            curdir_st->st_dev == pwd_st.st_dev)
                   1059:                (void)strncpy(curdir, pwd, MAXPATHLEN);
                   1060:
                   1061: ignore_pwd:
1.499     rillig   1062:        FStr_Done(&makeobjdir);
1.381     rillig   1063: }
                   1064: #endif
                   1065:
1.407     rillig   1066: /*
1.550     rillig   1067:  * Find the .OBJDIR.  If MAKEOBJDIRPREFIX, or failing that, MAKEOBJDIR is set
                   1068:  * in the environment, try only that value and fall back to .CURDIR if it
                   1069:  * does not exist.
1.407     rillig   1070:  *
                   1071:  * Otherwise, try _PATH_OBJDIR.MACHINE-MACHINE_ARCH, _PATH_OBJDIR.MACHINE,
1.550     rillig   1072:  * and finally _PATH_OBJDIRPREFIX`pwd`, in that order.  If none of these
                   1073:  * paths exist, just use .CURDIR.
1.407     rillig   1074:  */
                   1075: static void
                   1076: InitObjdir(const char *machine, const char *machine_arch)
                   1077: {
1.534     rillig   1078:        bool writable;
1.456     sjg      1079:
1.491     rillig   1080:        Dir_InitCur(curdir);
1.538     rillig   1081:        writable = GetBooleanExpr("${MAKE_OBJDIR_CHECK_WRITABLE}", true);
1.534     rillig   1082:        (void)Main_SetObjdir(false, "%s", curdir);
1.407     rillig   1083:
1.461     rillig   1084:        if (!SetVarObjdir(writable, "MAKEOBJDIRPREFIX", curdir) &&
                   1085:            !SetVarObjdir(writable, "MAKEOBJDIR", "") &&
1.456     sjg      1086:            !Main_SetObjdir(writable, "%s.%s-%s", _PATH_OBJDIR, machine, machine_arch) &&
                   1087:            !Main_SetObjdir(writable, "%s.%s", _PATH_OBJDIR, machine) &&
                   1088:            !Main_SetObjdir(writable, "%s", _PATH_OBJDIR))
                   1089:                (void)Main_SetObjdir(writable, "%s%s", _PATH_OBJDIRPREFIX, curdir);
1.407     rillig   1090: }
                   1091:
1.393     rillig   1092: /* get rid of resource limit on file descriptors */
                   1093: static void
                   1094: UnlimitFiles(void)
                   1095: {
                   1096: #if defined(MAKE_NATIVE) || (defined(HAVE_SETRLIMIT) && defined(RLIMIT_NOFILE))
                   1097:        struct rlimit rl;
                   1098:        if (getrlimit(RLIMIT_NOFILE, &rl) != -1 &&
                   1099:            rl.rlim_cur != rl.rlim_max) {
                   1100:                rl.rlim_cur = rl.rlim_max;
                   1101:                (void)setrlimit(RLIMIT_NOFILE, &rl);
                   1102:        }
                   1103: #endif
                   1104: }
                   1105:
1.395     rillig   1106: static void
                   1107: CmdOpts_Init(void)
                   1108: {
1.534     rillig   1109:        opts.compatMake = false;
1.543     rillig   1110:        memset(&opts.debug, 0, sizeof(opts.debug));
1.525     rillig   1111:        /* opts.debug_file has already been initialized earlier */
1.534     rillig   1112:        opts.strict = false;
                   1113:        opts.debugVflag = false;
                   1114:        opts.checkEnvFirst = false;
1.484     rillig   1115:        Lst_Init(&opts.makefiles);
1.534     rillig   1116:        opts.ignoreErrors = false;      /* Pay attention to non-zero returns */
1.493     rillig   1117:        opts.maxJobs = 1;
1.534     rillig   1118:        opts.keepgoing = false;         /* Stop on error */
                   1119:        opts.noRecursiveExecute = false; /* Execute all .MAKE targets */
                   1120:        opts.noExecute = false;         /* Execute all commands */
1.549     rillig   1121:        opts.query = false;
1.534     rillig   1122:        opts.noBuiltins = false;        /* Read the built-in rules */
1.549     rillig   1123:        opts.silent = false;            /* Print commands as executed */
                   1124:        opts.touch = false;
1.437     rillig   1125:        opts.printVars = PVM_NONE;
1.485     rillig   1126:        Lst_Init(&opts.variables);
1.534     rillig   1127:        opts.parseWarnFatal = false;
                   1128:        opts.enterFlag = false;
                   1129:        opts.varNoExportEnv = false;
1.486     rillig   1130:        Lst_Init(&opts.create);
1.395     rillig   1131: }
                   1132:
1.507     rillig   1133: /*
                   1134:  * Initialize MAKE and .MAKE to the path of the executable, so that it can be
1.406     rillig   1135:  * found by execvp(3) and the shells, even after a chdir.
                   1136:  *
                   1137:  * If it's a relative path and contains a '/', resolve it to an absolute path.
1.507     rillig   1138:  * Otherwise keep it as is, assuming it will be found in the PATH.
                   1139:  */
1.397     rillig   1140: static void
1.406     rillig   1141: InitVarMake(const char *argv0)
1.405     rillig   1142: {
1.406     rillig   1143:        const char *make = argv0;
1.405     rillig   1144:
1.406     rillig   1145:        if (argv0[0] != '/' && strchr(argv0, '/') != NULL) {
                   1146:                char pathbuf[MAXPATHLEN];
1.502     rillig   1147:                const char *abspath = cached_realpath(argv0, pathbuf);
1.406     rillig   1148:                struct stat st;
1.502     rillig   1149:                if (abspath != NULL && abspath[0] == '/' &&
                   1150:                    stat(make, &st) == 0)
                   1151:                        make = abspath;
1.405     rillig   1152:        }
1.406     rillig   1153:
1.528     rillig   1154:        Global_Set("MAKE", make);
                   1155:        Global_Set(".MAKE", make);
1.405     rillig   1156: }
                   1157:
1.507     rillig   1158: /*
                   1159:  * Add the directories from the colon-separated syspath to defSysIncPath.
                   1160:  * After returning, the contents of syspath is unspecified.
                   1161:  */
1.405     rillig   1162: static void
1.409     rillig   1163: InitDefSysIncPath(char *syspath)
1.397     rillig   1164: {
                   1165:        static char defsyspath[] = _PATH_DEFSYSPATH;
                   1166:        char *start, *cp;
                   1167:
                   1168:        /*
                   1169:         * If no user-supplied system path was given (through the -m option)
                   1170:         * add the directories from the DEFSYSPATH (more than one may be given
                   1171:         * as dir1:...:dirn) to the system include path.
                   1172:         */
                   1173:        if (syspath == NULL || syspath[0] == '\0')
                   1174:                syspath = defsyspath;
                   1175:        else
                   1176:                syspath = bmake_strdup(syspath);
                   1177:
                   1178:        for (start = syspath; *start != '\0'; start = cp) {
                   1179:                for (cp = start; *cp != '\0' && *cp != ':'; cp++)
                   1180:                        continue;
1.433     rillig   1181:                if (*cp == ':')
1.397     rillig   1182:                        *cp++ = '\0';
1.433     rillig   1183:
1.397     rillig   1184:                /* look for magic parent directory search string */
1.464     rillig   1185:                if (strncmp(start, ".../", 4) == 0) {
1.397     rillig   1186:                        char *dir = Dir_FindHereOrAbove(curdir, start + 4);
                   1187:                        if (dir != NULL) {
1.516     rillig   1188:                                (void)SearchPath_Add(defSysIncPath, dir);
1.397     rillig   1189:                                free(dir);
                   1190:                        }
1.464     rillig   1191:                } else {
1.516     rillig   1192:                        (void)SearchPath_Add(defSysIncPath, start);
1.397     rillig   1193:                }
                   1194:        }
                   1195:
                   1196:        if (syspath != defsyspath)
                   1197:                free(syspath);
                   1198: }
                   1199:
1.398     rillig   1200: static void
                   1201: ReadBuiltinRules(void)
                   1202: {
1.445     rillig   1203:        StringListNode *ln;
1.525     rillig   1204:        StringList sysMkFiles = LST_INIT;
1.445     rillig   1205:
1.515     rillig   1206:        SearchPath_Expand(
1.517     rillig   1207:            Lst_IsEmpty(&sysIncPath->dirs) ? defSysIncPath : sysIncPath,
1.515     rillig   1208:            _PATH_DEFSYSMK,
1.525     rillig   1209:            &sysMkFiles);
                   1210:        if (Lst_IsEmpty(&sysMkFiles))
1.398     rillig   1211:                Fatal("%s: no system rules (%s).", progname, _PATH_DEFSYSMK);
1.445     rillig   1212:
1.525     rillig   1213:        for (ln = sysMkFiles.first; ln != NULL; ln = ln->next)
1.553     rillig   1214:                if (ReadMakefile(ln->datum))
1.445     rillig   1215:                        break;
                   1216:
                   1217:        if (ln == NULL)
                   1218:                Fatal("%s: cannot open %s.",
1.525     rillig   1219:                    progname, (const char *)sysMkFiles.first->datum);
1.445     rillig   1220:
1.557     rillig   1221:        Lst_DoneCall(&sysMkFiles, free);
1.398     rillig   1222: }
                   1223:
1.408     rillig   1224: static void
                   1225: InitMaxJobs(void)
                   1226: {
                   1227:        char *value;
                   1228:        int n;
                   1229:
                   1230:        if (forceJobs || opts.compatMake ||
1.532     rillig   1231:            !Var_Exists(SCOPE_GLOBAL, ".MAKE.JOBS"))
1.408     rillig   1232:                return;
                   1233:
1.530     rillig   1234:        (void)Var_Subst("${.MAKE.JOBS}", SCOPE_GLOBAL, VARE_WANTRES, &value);
1.408     rillig   1235:        /* TODO: handle errors */
                   1236:        n = (int)strtol(value, NULL, 0);
                   1237:        if (n < 1) {
                   1238:                (void)fprintf(stderr,
1.453     rillig   1239:                    "%s: illegal value for .MAKE.JOBS "
                   1240:                    "-- must be positive integer!\n",
                   1241:                    progname);
1.505     rillig   1242:                exit(2);        /* Not 1 so -q can distinguish error */
1.408     rillig   1243:        }
                   1244:
                   1245:        if (n != opts.maxJobs) {
1.529     rillig   1246:                Global_Append(MAKEFLAGS, "-j");
                   1247:                Global_Append(MAKEFLAGS, value);
1.408     rillig   1248:        }
                   1249:
                   1250:        opts.maxJobs = n;
                   1251:        maxJobTokens = opts.maxJobs;
1.534     rillig   1252:        forceJobs = true;
1.408     rillig   1253:        free(value);
                   1254: }
                   1255:
1.400     rillig   1256: /*
                   1257:  * For compatibility, look at the directories in the VPATH variable
                   1258:  * and add them to the search path, if the variable is defined. The
                   1259:  * variable's value is in the same format as the PATH environment
                   1260:  * variable, i.e. <directory>:<directory>:<directory>...
                   1261:  */
                   1262: static void
                   1263: InitVpath(void)
                   1264: {
                   1265:        char *vpath, savec, *path;
1.532     rillig   1266:        if (!Var_Exists(SCOPE_CMDLINE, "VPATH"))
1.400     rillig   1267:                return;
                   1268:
1.530     rillig   1269:        (void)Var_Subst("${VPATH}", SCOPE_CMDLINE, VARE_WANTRES, &vpath);
1.400     rillig   1270:        /* TODO: handle errors */
                   1271:        path = vpath;
                   1272:        do {
                   1273:                char *cp;
                   1274:                /* skip to end of directory */
                   1275:                for (cp = path; *cp != ':' && *cp != '\0'; cp++)
                   1276:                        continue;
                   1277:                /* Save terminator character so know when to stop */
                   1278:                savec = *cp;
                   1279:                *cp = '\0';
                   1280:                /* Add directory to search path */
1.516     rillig   1281:                (void)SearchPath_Add(&dirSearchPath, path);
1.400     rillig   1282:                *cp = savec;
                   1283:                path = cp + 1;
                   1284:        } while (savec == ':');
                   1285:        free(vpath);
                   1286: }
                   1287:
1.402     rillig   1288: static void
1.553     rillig   1289: ReadAllMakefiles(const StringList *makefiles)
1.403     rillig   1290: {
1.443     rillig   1291:        StringListNode *ln;
1.403     rillig   1292:
1.443     rillig   1293:        for (ln = makefiles->first; ln != NULL; ln = ln->next) {
                   1294:                const char *fname = ln->datum;
1.553     rillig   1295:                if (!ReadMakefile(fname))
1.443     rillig   1296:                        Fatal("%s: cannot open %s.", progname, fname);
1.403     rillig   1297:        }
                   1298: }
                   1299:
                   1300: static void
1.443     rillig   1301: ReadFirstDefaultMakefile(void)
                   1302: {
1.446     rillig   1303:        StringListNode *ln;
1.443     rillig   1304:        char *prefs;
1.446     rillig   1305:
1.443     rillig   1306:        (void)Var_Subst("${" MAKE_MAKEFILE_PREFERENCE "}",
1.530     rillig   1307:            SCOPE_CMDLINE, VARE_WANTRES, &prefs);
1.443     rillig   1308:        /* TODO: handle errors */
                   1309:
1.547     rillig   1310:        /*
                   1311:         * XXX: This should use a local list instead of opts.makefiles since
                   1312:         * these makefiles do not come from the command line.  They also have
                   1313:         * different semantics in that only the first file that is found is
                   1314:         * processed.  See ReadAllMakefiles.
                   1315:         */
1.484     rillig   1316:        (void)str2Lst_Append(&opts.makefiles, prefs);
1.446     rillig   1317:
1.484     rillig   1318:        for (ln = opts.makefiles.first; ln != NULL; ln = ln->next)
1.553     rillig   1319:                if (ReadMakefile(ln->datum))
1.446     rillig   1320:                        break;
                   1321:
1.443     rillig   1322:        free(prefs);
                   1323: }
                   1324:
1.507     rillig   1325: /*
                   1326:  * Initialize variables such as MAKE, MACHINE, .MAKEFLAGS.
1.449     rillig   1327:  * Initialize a few modules.
1.507     rillig   1328:  * Parse the arguments from MAKEFLAGS and the command line.
                   1329:  */
1.443     rillig   1330: static void
1.448     rillig   1331: main_Init(int argc, char **argv)
1.402     rillig   1332: {
1.381     rillig   1333:        struct stat sa;
1.369     rillig   1334:        const char *machine;
                   1335:        const char *machine_arch;
1.55      sjg      1336:        char *syspath = getenv("MAKESYSPATH");
1.119     tsutsui  1337:        struct utsname utsname;
1.107     sjg      1338:
1.154     apb      1339:        /* default to writing debug to stderr */
1.391     rillig   1340:        opts.debug_file = stderr;
1.133     dsl      1341:
1.542     rillig   1342:        Str_Intern_Init();
1.469     rillig   1343:        HashTable_Init(&cached_realpaths);
                   1344:
1.167     christos 1345: #ifdef SIGINFO
1.188     sjg      1346:        (void)bmake_signal(SIGINFO, siginfo);
1.167     christos 1347: #endif
1.404     rillig   1348:
                   1349:        InitRandom();
1.277     rillig   1350:
1.498     rillig   1351:        progname = str_basename(argv[0]);
1.393     rillig   1352:
                   1353:        UnlimitFiles();
1.13      cgd      1354:
1.206     christos 1355:        if (uname(&utsname) == -1) {
1.447     rillig   1356:                (void)fprintf(stderr, "%s: uname failed (%s).\n", progname,
1.453     rillig   1357:                    strerror(errno));
1.447     rillig   1358:                exit(2);
1.206     christos 1359:        }
                   1360:
1.17      gwr      1361:        /*
                   1362:         * Get the name of this type of MACHINE from utsname
                   1363:         * so we can share an executable for similar machines.
                   1364:         * (i.e. m68k: amiga hp300, mac68k, sun3, ...)
                   1365:         *
1.33      christos 1366:         * Note that both MACHINE and MACHINE_ARCH are decided at
                   1367:         * run-time.
1.17      gwr      1368:         */
1.451     rillig   1369:        machine = InitVarMachine(&utsname);
                   1370:        machine_arch = InitVarMachineArch();
1.33      christos 1371:
1.447     rillig   1372:        myPid = getpid();       /* remember this for vFork() */
1.183     sjg      1373:
1.1       cgd      1374:        /*
1.51      sjg      1375:         * Just in case MAKEOBJDIR wants us to do something tricky.
                   1376:         */
1.476     rillig   1377:        Targ_Init();
                   1378:        Var_Init();
1.528     rillig   1379:        Global_Set(".MAKE.OS", utsname.sysname);
                   1380:        Global_Set("MACHINE", machine);
                   1381:        Global_Set("MACHINE_ARCH", machine_arch);
1.170     perry    1382: #ifdef MAKE_VERSION
1.528     rillig   1383:        Global_Set("MAKE_VERSION", MAKE_VERSION);
1.170     perry    1384: #endif
1.547     rillig   1385:        Global_Set(".newline", "\n");   /* handy for :@ loops */
1.176     sjg      1386: #ifndef MAKEFILE_PREFERENCE_LIST
1.550     rillig   1387:        /* This is the traditional preference for makefiles. */
1.176     sjg      1388: # define MAKEFILE_PREFERENCE_LIST "makefile Makefile"
                   1389: #endif
1.528     rillig   1390:        Global_Set(MAKE_MAKEFILE_PREFERENCE, MAKEFILE_PREFERENCE_LIST);
                   1391:        Global_Set(MAKE_DEPENDFILE, ".depend");
1.51      sjg      1392:
1.395     rillig   1393:        CmdOpts_Init();
1.534     rillig   1394:        allPrecious = false;    /* Remove targets when interrupted */
                   1395:        deleteOnError = false;  /* Historical default behavior */
                   1396:        jobsRunning = false;
1.1       cgd      1397:
1.391     rillig   1398:        maxJobTokens = opts.maxJobs;
1.534     rillig   1399:        ignorePWD = false;
1.13      cgd      1400:
1.1       cgd      1401:        /*
                   1402:         * Initialize the parsing, directory and variable modules to prepare
                   1403:         * for the reading of inclusion paths and variable settings on the
                   1404:         * command line
                   1405:         */
1.36      gwr      1406:
                   1407:        /*
1.1       cgd      1408:         * Initialize various variables.
                   1409:         *      MAKE also gets this name, for compatibility
                   1410:         *      .MAKEFLAGS gets set to the empty string just in case.
                   1411:         *      MFLAGS also gets initialized empty, for compatibility.
                   1412:         */
1.79      tv       1413:        Parse_Init();
1.406     rillig   1414:        InitVarMake(argv[0]);
1.528     rillig   1415:        Global_Set(MAKEFLAGS, "");
                   1416:        Global_Set(MAKEOVERRIDES, "");
                   1417:        Global_Set("MFLAGS", "");
                   1418:        Global_Set(".ALLTARGETS", "");
1.532     rillig   1419:        Var_Set(SCOPE_CMDLINE, MAKE_LEVEL ".ENV", MAKE_LEVEL_ENV);
1.1       cgd      1420:
1.447     rillig   1421:        /* Set some other useful variables. */
1.142     sjg      1422:        {
1.552     rillig   1423:                char buf[64], *ep = getenv(MAKE_LEVEL_ENV);
1.142     sjg      1424:
1.447     rillig   1425:                makelevel = ep != NULL && ep[0] != '\0' ? atoi(ep) : 0;
                   1426:                if (makelevel < 0)
                   1427:                        makelevel = 0;
1.552     rillig   1428:                snprintf(buf, sizeof buf, "%d", makelevel);
                   1429:                Global_Set(MAKE_LEVEL, buf);
                   1430:                snprintf(buf, sizeof buf, "%u", myPid);
                   1431:                Global_Set(".MAKE.PID", buf);
                   1432:                snprintf(buf, sizeof buf, "%u", getppid());
                   1433:                Global_Set(".MAKE.PPID", buf);
                   1434:                snprintf(buf, sizeof buf, "%u", getuid());
                   1435:                Global_Set(".MAKE.UID", buf);
                   1436:                snprintf(buf, sizeof buf, "%u", getgid());
                   1437:                Global_Set(".MAKE.GID", buf);
1.142     sjg      1438:        }
1.220     christos 1439:        if (makelevel > 0) {
                   1440:                char pn[1024];
1.426     rillig   1441:                snprintf(pn, sizeof pn, "%s[%d]", progname, makelevel);
1.221     christos 1442:                progname = bmake_strdup(pn);
1.220     christos 1443:        }
1.142     sjg      1444:
1.210     sjg      1445: #ifdef USE_META
                   1446:        meta_init();
                   1447: #endif
1.306     rillig   1448:        Dir_Init();
1.255     sjg      1449:
1.1       cgd      1450: #ifdef POSIX
1.412     rillig   1451:        {
1.447     rillig   1452:                char *p1 = explode(getenv("MAKEFLAGS"));
                   1453:                Main_ParseArgLine(p1);
                   1454:                free(p1);
1.412     rillig   1455:        }
1.1       cgd      1456: #else
1.550     rillig   1457:        /*
                   1458:         * First snag any flags out of the MAKE environment variable.
                   1459:         * (Note this is *not* MAKEFLAGS since /bin/make uses that and it's
                   1460:         * in a different format).
                   1461:         */
1.1       cgd      1462:        Main_ParseArgLine(getenv("MAKE"));
                   1463: #endif
1.31      christos 1464:
1.174     sjg      1465:        if (getcwd(curdir, MAXPATHLEN) == NULL) {
1.194     dholland 1466:                (void)fprintf(stderr, "%s: getcwd: %s.\n",
1.453     rillig   1467:                    progname, strerror(errno));
1.174     sjg      1468:                exit(2);
                   1469:        }
                   1470:
1.175     sjg      1471:        MainParseArgs(argc, argv);
                   1472:
1.391     rillig   1473:        if (opts.enterFlag)
1.220     christos 1474:                printf("%s: Entering directory `%s'\n", progname, curdir);
                   1475:
1.174     sjg      1476:        if (stat(curdir, &sa) == -1) {
1.447     rillig   1477:                (void)fprintf(stderr, "%s: %s: %s.\n",
1.453     rillig   1478:                    progname, curdir, strerror(errno));
1.447     rillig   1479:                exit(2);
1.174     sjg      1480:        }
                   1481:
1.222     sjg      1482: #ifndef NO_PWD_OVERRIDE
1.381     rillig   1483:        HandlePWD(&sa);
1.222     sjg      1484: #endif
1.528     rillig   1485:        Global_Set(".CURDIR", curdir);
1.174     sjg      1486:
1.407     rillig   1487:        InitObjdir(machine, machine_arch);
1.174     sjg      1488:
1.1       cgd      1489:        Arch_Init();
                   1490:        Suff_Init();
1.58      sommerfe 1491:        Trace_Init(tracefile);
1.1       cgd      1492:
1.459     rillig   1493:        defaultNode = NULL;
1.1       cgd      1494:        (void)time(&now);
                   1495:
1.58      sommerfe 1496:        Trace_Log(MAKESTART, NULL);
1.279     rillig   1497:
1.343     rillig   1498:        InitVarTargets();
1.25      christos 1499:
1.409     rillig   1500:        InitDefSysIncPath(syspath);
1.448     rillig   1501: }
1.25      christos 1502:
1.507     rillig   1503: /*
                   1504:  * Read the system makefile followed by either makefile, Makefile or the
                   1505:  * files given by the -f option. Exit on parse errors.
                   1506:  */
1.448     rillig   1507: static void
                   1508: main_ReadFiles(void)
                   1509: {
1.452     rillig   1510:
1.398     rillig   1511:        if (!opts.noBuiltins)
                   1512:                ReadBuiltinRules();
1.452     rillig   1513:
1.484     rillig   1514:        if (!Lst_IsEmpty(&opts.makefiles))
                   1515:                ReadAllMakefiles(&opts.makefiles);
1.443     rillig   1516:        else
                   1517:                ReadFirstDefaultMakefile();
1.448     rillig   1518: }
1.436     rillig   1519:
1.449     rillig   1520: /* Compute the dependency graph. */
1.448     rillig   1521: static void
                   1522: main_PrepareMaking(void)
                   1523: {
1.138     dsl      1524:        /* In particular suppress .depend for '-r -V .OBJDIR -f /dev/null' */
1.437     rillig   1525:        if (!opts.noBuiltins || opts.printVars == PVM_NONE) {
1.503     sjg      1526:                (void)Var_Subst("${.MAKE.DEPENDFILE}",
1.530     rillig   1527:                    SCOPE_CMDLINE, VARE_WANTRES, &makeDependfile);
1.447     rillig   1528:                if (makeDependfile[0] != '\0') {
                   1529:                        /* TODO: handle errors */
1.534     rillig   1530:                        doing_depend = true;
1.447     rillig   1531:                        (void)ReadMakefile(makeDependfile);
1.534     rillig   1532:                        doing_depend = false;
1.447     rillig   1533:                }
1.145     dsl      1534:        }
1.1       cgd      1535:
1.233     sjg      1536:        if (enterFlagObj)
                   1537:                printf("%s: Entering directory `%s'\n", progname, objdir);
1.279     rillig   1538:
1.500     rillig   1539:        MakeMode();
1.176     sjg      1540:
1.412     rillig   1541:        {
1.532     rillig   1542:                FStr makeflags = Var_Value(SCOPE_GLOBAL, MAKEFLAGS);
1.529     rillig   1543:                Global_Append("MFLAGS", makeflags.str);
1.499     rillig   1544:                FStr_Done(&makeflags);
1.412     rillig   1545:        }
1.1       cgd      1546:
1.408     rillig   1547:        InitMaxJobs();
1.243     matthias 1548:
1.447     rillig   1549:        if (!opts.compatMake && !forceJobs)
1.534     rillig   1550:                opts.compatMake = true;
1.243     matthias 1551:
1.391     rillig   1552:        if (!opts.compatMake)
1.447     rillig   1553:                Job_ServerStart(maxJobTokens, jp_0, jp_1);
1.352     rillig   1554:        DEBUG5(JOB, "job_pipe %d %d, maxjobs %d, tokens %d, compat %d\n",
1.453     rillig   1555:            jp_0, jp_1, opts.maxJobs, maxJobTokens, opts.compatMake ? 1 : 0);
1.58      sommerfe 1556:
1.437     rillig   1557:        if (opts.printVars == PVM_NONE)
1.534     rillig   1558:                Main_ExportMAKEFLAGS(true);     /* initial export */
1.279     rillig   1559:
1.400     rillig   1560:        InitVpath();
1.1       cgd      1561:
                   1562:        /*
                   1563:         * Now that all search paths have been read for suffixes et al, it's
                   1564:         * time to add the default search path to their lists...
                   1565:         */
1.535     rillig   1566:        Suff_ExtendPaths();
1.50      mycroft  1567:
                   1568:        /*
                   1569:         * Propagate attributes through :: dependency lists.
                   1570:         */
                   1571:        Targ_Propagate();
1.1       cgd      1572:
                   1573:        /* print the initial graph, if the user requested it */
                   1574:        if (DEBUG(GRAPH1))
                   1575:                Targ_PrintGraph(1);
1.448     rillig   1576: }
1.1       cgd      1577:
1.507     rillig   1578: /*
                   1579:  * Make the targets.
1.449     rillig   1580:  * If the -v or -V options are given, print variables instead.
1.507     rillig   1581:  * Return whether any of the targets is out-of-date.
                   1582:  */
1.534     rillig   1583: static bool
1.448     rillig   1584: main_Run(void)
                   1585: {
1.437     rillig   1586:        if (opts.printVars != PVM_NONE) {
1.465     rillig   1587:                /* print the values of any variables requested by the user */
1.266     christos 1588:                doPrintVars();
1.534     rillig   1589:                return false;
1.138     dsl      1590:        } else {
1.448     rillig   1591:                return runTargets();
1.31      christos 1592:        }
1.448     rillig   1593: }
                   1594:
1.449     rillig   1595: /* Clean up after making the targets. */
1.448     rillig   1596: static void
                   1597: main_CleanUp(void)
                   1598: {
                   1599: #ifdef CLEANUP
1.485     rillig   1600:        Lst_DoneCall(&opts.variables, free);
1.557     rillig   1601:        Lst_DoneCall(&opts.makefiles, free);
1.489     rillig   1602:        Lst_DoneCall(&opts.create, free);
1.448     rillig   1603: #endif
                   1604:
                   1605:        if (DEBUG(GRAPH2))
                   1606:                Targ_PrintGraph(2);
1.31      christos 1607:
1.448     rillig   1608:        Trace_Log(MAKEEND, NULL);
                   1609:
                   1610:        if (enterFlagObj)
                   1611:                printf("%s: Leaving directory `%s'\n", progname, objdir);
                   1612:        if (opts.enterFlag)
                   1613:                printf("%s: Leaving directory `%s'\n", progname, curdir);
1.14      jtc      1614:
1.448     rillig   1615: #ifdef USE_META
                   1616:        meta_finish();
                   1617: #endif
                   1618:        Suff_End();
                   1619:        Targ_End();
                   1620:        Arch_End();
                   1621:        Var_End();
                   1622:        Parse_End();
                   1623:        Dir_End();
                   1624:        Job_End();
                   1625:        Trace_End();
1.544     rillig   1626:        Str_Intern_End();
1.448     rillig   1627: }
                   1628:
1.449     rillig   1629: /* Determine the exit code. */
1.448     rillig   1630: static int
1.534     rillig   1631: main_Exit(bool outOfDate)
1.448     rillig   1632: {
1.541     rillig   1633:        if (opts.strict && (main_errors > 0 || Parse_NumErrors() > 0))
1.447     rillig   1634:                return 2;       /* Not 1 so -q can distinguish error */
1.137     dsl      1635:        return outOfDate ? 1 : 0;
1.1       cgd      1636: }
                   1637:
1.448     rillig   1638: int
                   1639: main(int argc, char **argv)
                   1640: {
1.534     rillig   1641:        bool outOfDate;
1.448     rillig   1642:
                   1643:        main_Init(argc, argv);
                   1644:        main_ReadFiles();
                   1645:        main_PrepareMaking();
                   1646:        outOfDate = main_Run();
                   1647:        main_CleanUp();
                   1648:        return main_Exit(outOfDate);
                   1649: }
                   1650:
1.507     rillig   1651: /*
                   1652:  * Open and parse the given makefile, with all its side effects.
1.553     rillig   1653:  * Return false if the file could not be opened.
1.1       cgd      1654:  */
1.553     rillig   1655: static bool
1.325     rillig   1656: ReadMakefile(const char *fname)
1.1       cgd      1657: {
1.140     dsl      1658:        int fd;
1.304     rillig   1659:        char *name, *path = NULL;
1.1       cgd      1660:
1.454     rillig   1661:        if (strcmp(fname, "-") == 0) {
1.193     dholland 1662:                Parse_File(NULL /*stdin*/, -1);
1.532     rillig   1663:                Var_Set(SCOPE_INTERNAL, "MAKEFILE", "");
1.1       cgd      1664:        } else {
                   1665:                /* if we've chdir'd, rebuild the path name */
1.454     rillig   1666:                if (strcmp(curdir, objdir) != 0 && *fname != '/') {
1.304     rillig   1667:                        path = str_concat3(curdir, "/", fname);
1.140     dsl      1668:                        fd = open(path, O_RDONLY);
                   1669:                        if (fd != -1) {
1.1       cgd      1670:                                fname = path;
                   1671:                                goto found;
                   1672:                        }
1.309     rillig   1673:                        free(path);
1.279     rillig   1674:
1.95      jmc      1675:                        /* If curdir failed, try objdir (ala .depend) */
1.304     rillig   1676:                        path = str_concat3(objdir, "/", fname);
1.140     dsl      1677:                        fd = open(path, O_RDONLY);
                   1678:                        if (fd != -1) {
1.95      jmc      1679:                                fname = path;
                   1680:                                goto found;
                   1681:                        }
1.140     dsl      1682:                } else {
                   1683:                        fd = open(fname, O_RDONLY);
                   1684:                        if (fd != -1)
                   1685:                                goto found;
                   1686:                }
1.1       cgd      1687:                /* look in -I and system include directories. */
                   1688:                name = Dir_FindFile(fname, parseIncPath);
1.454     rillig   1689:                if (name == NULL) {
1.517     rillig   1690:                        SearchPath *sysInc = Lst_IsEmpty(&sysIncPath->dirs)
1.546     rillig   1691:                            ? defSysIncPath : sysIncPath;
1.409     rillig   1692:                        name = Dir_FindFile(fname, sysInc);
                   1693:                }
1.454     rillig   1694:                if (name == NULL || (fd = open(name, O_RDONLY)) == -1) {
1.238     christos 1695:                        free(name);
1.48      christos 1696:                        free(path);
1.553     rillig   1697:                        return false;
1.48      christos 1698:                }
1.1       cgd      1699:                fname = name;
                   1700:                /*
                   1701:                 * set the MAKEFILE variable desired by System V fans -- the
                   1702:                 * placement of the setting here means it gets set to the last
                   1703:                 * makefile specified, as it is set by SysV make.
                   1704:                 */
1.67      sjg      1705: found:
1.176     sjg      1706:                if (!doing_depend)
1.532     rillig   1707:                        Var_Set(SCOPE_INTERNAL, "MAKEFILE", fname);
1.140     dsl      1708:                Parse_File(fname, fd);
1.1       cgd      1709:        }
1.48      christos 1710:        free(path);
1.553     rillig   1711:        return true;
1.54      sjg      1712: }
                   1713:
1.514     rillig   1714: /*
1.550     rillig   1715:  * Execute the command in cmd, and return its output (only stdout, not
                   1716:  * stderr).  In the output, replace newlines with spaces.
1.29      christos 1717:  *
                   1718:  * Results:
1.550     rillig   1719:  *     The output of the command, can be empty.
1.293     rillig   1720:  *     *errfmt returns a format string describing the command failure,
                   1721:  *     if any, using a single %s conversion specification.
1.550     rillig   1722:  *     TODO: replace errfmt with an actual error message.
1.29      christos 1723:  */
                   1724: char *
1.293     rillig   1725: Cmd_Exec(const char *cmd, const char **errfmt)
1.29      christos 1726: {
1.550     rillig   1727:        const char *args[4];    /* Arguments for invoking the shell */
1.482     rillig   1728:        int pipefds[2];
1.453     rillig   1729:        int cpid;               /* Child PID */
                   1730:        int pid;                /* PID from wait() */
                   1731:        int status;             /* command exit status */
                   1732:        Buffer buf;             /* buffer to store the result */
                   1733:        ssize_t bytes_read;
                   1734:        char *res;              /* result */
                   1735:        size_t res_len;
                   1736:        char *cp;
                   1737:        int savederr;           /* saved errno */
                   1738:
                   1739:        *errfmt = NULL;
                   1740:
1.511     rillig   1741:        if (shellName == NULL)
1.453     rillig   1742:                Shell_Init();
1.550     rillig   1743:
1.453     rillig   1744:        args[0] = shellName;
                   1745:        args[1] = "-c";
                   1746:        args[2] = cmd;
                   1747:        args[3] = NULL;
1.31      christos 1748:
1.482     rillig   1749:        if (pipe(pipefds) == -1) {
1.453     rillig   1750:                *errfmt = "Couldn't create pipe for \"%s\"";
1.558   ! rillig   1751:                return bmake_strdup("");
1.453     rillig   1752:        }
                   1753:
1.504     rillig   1754:        Var_ReexportVars();
                   1755:
1.526     rillig   1756:        switch (cpid = vfork()) {
1.453     rillig   1757:        case 0:
1.550     rillig   1758:                (void)close(pipefds[0]);
1.482     rillig   1759:                (void)dup2(pipefds[1], 1);
                   1760:                (void)close(pipefds[1]);
1.143     sjg      1761:
1.453     rillig   1762:                (void)execv(shellPath, UNCONST(args));
                   1763:                _exit(1);
1.547     rillig   1764:                /* NOTREACHED */
1.453     rillig   1765:
                   1766:        case -1:
                   1767:                *errfmt = "Couldn't exec \"%s\"";
1.558   ! rillig   1768:                return bmake_strdup("");
        !          1769:        }
1.29      christos 1770:
1.558   ! rillig   1771:        (void)close(pipefds[1]);        /* No need for the writing half */
1.31      christos 1772:
1.558   ! rillig   1773:        savederr = 0;
        !          1774:        Buf_Init(&buf);
        !          1775:
        !          1776:        do {
        !          1777:                char result[BUFSIZ];
        !          1778:                bytes_read = read(pipefds[0], result, sizeof result);
        !          1779:                if (bytes_read > 0)
        !          1780:                        Buf_AddBytes(&buf, result, (size_t)bytes_read);
        !          1781:        } while (bytes_read > 0 || (bytes_read == -1 && errno == EINTR));
        !          1782:        if (bytes_read == -1)
        !          1783:                savederr = errno;
        !          1784:
        !          1785:        (void)close(pipefds[0]); /* Close the input side of the pipe. */
        !          1786:
        !          1787:        while ((pid = waitpid(cpid, &status, 0)) != cpid && pid >= 0)
        !          1788:                JobReapChild(pid, status, false);
        !          1789:
        !          1790:        res_len = buf.len;
        !          1791:        res = Buf_DoneData(&buf);
        !          1792:
        !          1793:        if (savederr != 0)
        !          1794:                *errfmt = "Couldn't read shell's output for \"%s\"";
        !          1795:
        !          1796:        if (WIFSIGNALED(status))
        !          1797:                *errfmt = "\"%s\" exited on a signal";
        !          1798:        else if (WEXITSTATUS(status) != 0)
        !          1799:                *errfmt = "\"%s\" returned non-zero status";
        !          1800:
        !          1801:        /* Convert newlines to spaces, strip the final newline. */
        !          1802:        if (res_len > 0 && res[res_len - 1] == '\n')
        !          1803:                res[res_len - 1] = '\0';
        !          1804:        for (cp = res; *cp != '\0'; cp++)
        !          1805:                if (*cp == '\n')
        !          1806:                        *cp = ' ';
1.29      christos 1807:
1.453     rillig   1808:        return res;
1.1       cgd      1809: }
                   1810:
1.507     rillig   1811: /*
                   1812:  * Print a printf-style error message.
1.1       cgd      1813:  *
1.550     rillig   1814:  * In default mode, this error message has no consequences, for compatibility
                   1815:  * reasons, in particular it does not affect the exit status.  Only in lint
                   1816:  * mode (-dL) it does.
1.507     rillig   1817:  */
1.1       cgd      1818: void
1.89      christos 1819: Error(const char *fmt, ...)
1.1       cgd      1820: {
                   1821:        va_list ap;
1.162     dsl      1822:        FILE *err_file;
1.85      wiz      1823:
1.391     rillig   1824:        err_file = opts.debug_file;
1.162     dsl      1825:        if (err_file == stdout)
                   1826:                err_file = stderr;
1.184     sjg      1827:        (void)fflush(stdout);
1.162     dsl      1828:        for (;;) {
                   1829:                va_start(ap, fmt);
                   1830:                fprintf(err_file, "%s: ", progname);
                   1831:                (void)vfprintf(err_file, fmt, ap);
                   1832:                va_end(ap);
                   1833:                (void)fprintf(err_file, "\n");
                   1834:                (void)fflush(err_file);
                   1835:                if (err_file == stderr)
                   1836:                        break;
                   1837:                err_file = stderr;
                   1838:        }
1.481     rillig   1839:        main_errors++;
1.1       cgd      1840: }
                   1841:
1.507     rillig   1842: /*
                   1843:  * Wait for any running jobs to finish, then produce an error message,
1.465     rillig   1844:  * finally exit immediately.
1.1       cgd      1845:  *
1.465     rillig   1846:  * Exiting immediately differs from Parse_Error, which exits only after the
1.507     rillig   1847:  * current top-level makefile has been parsed completely.
                   1848:  */
1.1       cgd      1849: void
1.89      christos 1850: Fatal(const char *fmt, ...)
1.1       cgd      1851: {
                   1852:        va_list ap;
1.85      wiz      1853:
1.1       cgd      1854:        if (jobsRunning)
                   1855:                Job_Wait();
                   1856:
1.184     sjg      1857:        (void)fflush(stdout);
1.465     rillig   1858:        va_start(ap, fmt);
1.1       cgd      1859:        (void)vfprintf(stderr, fmt, ap);
                   1860:        va_end(ap);
                   1861:        (void)fprintf(stderr, "\n");
                   1862:        (void)fflush(stderr);
                   1863:
1.176     sjg      1864:        PrintOnError(NULL, NULL);
1.67      sjg      1865:
1.94      dsl      1866:        if (DEBUG(GRAPH2) || DEBUG(GRAPH3))
1.1       cgd      1867:                Targ_PrintGraph(2);
1.433     rillig   1868:        Trace_Log(MAKEERROR, NULL);
1.1       cgd      1869:        exit(2);                /* Not 1 so -q can distinguish error */
                   1870: }
                   1871:
1.507     rillig   1872: /*
                   1873:  * Major exception once jobs are being created.
                   1874:  * Kills all jobs, prints a message and exits.
                   1875:  */
1.1       cgd      1876: void
1.89      christos 1877: Punt(const char *fmt, ...)
1.1       cgd      1878: {
                   1879:        va_list ap;
1.85      wiz      1880:
1.13      cgd      1881:        va_start(ap, fmt);
1.184     sjg      1882:        (void)fflush(stdout);
1.63      christos 1883:        (void)fprintf(stderr, "%s: ", progname);
1.1       cgd      1884:        (void)vfprintf(stderr, fmt, ap);
                   1885:        va_end(ap);
                   1886:        (void)fprintf(stderr, "\n");
                   1887:        (void)fflush(stderr);
                   1888:
1.176     sjg      1889:        PrintOnError(NULL, NULL);
1.67      sjg      1890:
1.1       cgd      1891:        DieHorribly();
                   1892: }
                   1893:
1.392     rillig   1894: /* Exit without giving a message. */
1.1       cgd      1895: void
1.85      wiz      1896: DieHorribly(void)
1.1       cgd      1897: {
                   1898:        if (jobsRunning)
                   1899:                Job_AbortAll();
                   1900:        if (DEBUG(GRAPH2))
                   1901:                Targ_PrintGraph(2);
1.433     rillig   1902:        Trace_Log(MAKEERROR, NULL);
1.505     rillig   1903:        exit(2);                /* Not 1 so -q can distinguish error */
1.1       cgd      1904: }
                   1905:
1.507     rillig   1906: /*
                   1907:  * Called when aborting due to errors in child shell to signal abnormal exit.
1.392     rillig   1908:  * The program exits.
1.507     rillig   1909:  * Errors is the number of errors encountered in Make_Make.
                   1910:  */
1.1       cgd      1911: void
1.421     rillig   1912: Finish(int errs)
1.1       cgd      1913: {
1.429     rillig   1914:        if (shouldDieQuietly(NULL, -1))
1.275     sjg      1915:                exit(2);
1.421     rillig   1916:        Fatal("%d error%s", errs, errs == 1 ? "" : "s");
1.1       cgd      1917: }
                   1918:
1.548     rillig   1919: bool
                   1920: unlink_file(const char *file)
1.21      christos 1921: {
                   1922:        struct stat st;
                   1923:
                   1924:        if (lstat(file, &st) == -1)
1.548     rillig   1925:                return false;
1.21      christos 1926:
                   1927:        if (S_ISDIR(st.st_mode)) {
                   1928:                errno = EISDIR;
1.548     rillig   1929:                return false;
1.21      christos 1930:        }
1.548     rillig   1931:        return unlink(file) == 0;
1.1       cgd      1932: }
                   1933:
1.373     rillig   1934: static void
                   1935: write_all(int fd, const void *data, size_t n)
                   1936: {
                   1937:        const char *mem = data;
                   1938:
                   1939:        while (n > 0) {
                   1940:                ssize_t written = write(fd, mem, n);
                   1941:                if (written == -1 && errno == EAGAIN)
                   1942:                        continue;
                   1943:                if (written == -1)
                   1944:                        break;
                   1945:                mem += written;
1.375     rillig   1946:                n -= (size_t)written;
1.373     rillig   1947:        }
                   1948: }
                   1949:
1.550     rillig   1950: /* Print why exec failed, avoiding stdio. */
1.372     rillig   1951: void MAKE_ATTR_DEAD
                   1952: execDie(const char *af, const char *av)
1.66      christos 1953: {
1.373     rillig   1954:        Buffer buf;
                   1955:
1.435     rillig   1956:        Buf_Init(&buf);
1.373     rillig   1957:        Buf_AddStr(&buf, progname);
                   1958:        Buf_AddStr(&buf, ": ");
                   1959:        Buf_AddStr(&buf, af);
                   1960:        Buf_AddStr(&buf, "(");
                   1961:        Buf_AddStr(&buf, av);
                   1962:        Buf_AddStr(&buf, ") failed (");
                   1963:        Buf_AddStr(&buf, strerror(errno));
                   1964:        Buf_AddStr(&buf, ")\n");
1.66      christos 1965:
1.520     rillig   1966:        write_all(STDERR_FILENO, buf.data, buf.len);
1.66      christos 1967:
1.518     rillig   1968:        Buf_Done(&buf);
1.372     rillig   1969:        _exit(1);
1.66      christos 1970: }
                   1971:
1.262     riastrad 1972: /* purge any relative paths */
                   1973: static void
1.469     rillig   1974: purge_relative_cached_realpaths(void)
1.262     riastrad 1975: {
1.453     rillig   1976:        HashEntry *he, *nhe;
                   1977:        HashIter hi;
                   1978:
1.469     rillig   1979:        HashIter_Init(&hi, &cached_realpaths);
1.453     rillig   1980:        he = HashIter_Next(&hi);
                   1981:        while (he != NULL) {
                   1982:                nhe = HashIter_Next(&hi);
                   1983:                if (he->key[0] != '/') {
1.469     rillig   1984:                        DEBUG1(DIR, "cached_realpath: purging %s\n", he->key);
                   1985:                        HashTable_DeleteEntry(&cached_realpaths, he);
1.547     rillig   1986:                        /*
                   1987:                         * XXX: What about the allocated he->value? Either
                   1988:                         * free them or document why they cannot be freed.
                   1989:                         */
1.453     rillig   1990:                }
                   1991:                he = nhe;
1.262     riastrad 1992:        }
                   1993: }
                   1994:
1.245     sjg      1995: char *
                   1996: cached_realpath(const char *pathname, char *resolved)
                   1997: {
1.453     rillig   1998:        const char *rp;
                   1999:
                   2000:        if (pathname == NULL || pathname[0] == '\0')
                   2001:                return NULL;
                   2002:
1.469     rillig   2003:        rp = HashTable_FindValue(&cached_realpaths, pathname);
                   2004:        if (rp != NULL) {
1.453     rillig   2005:                /* a hit */
                   2006:                strncpy(resolved, rp, MAXPATHLEN);
                   2007:                resolved[MAXPATHLEN - 1] = '\0';
1.469     rillig   2008:                return resolved;
                   2009:        }
                   2010:
                   2011:        rp = realpath(pathname, resolved);
                   2012:        if (rp != NULL) {
                   2013:                HashTable_Set(&cached_realpaths, pathname, bmake_strdup(rp));
                   2014:                DEBUG2(DIR, "cached_realpath: %s -> %s\n", pathname, rp);
                   2015:                return resolved;
                   2016:        }
1.248     christos 2017:
1.469     rillig   2018:        /* should we negative-cache? */
                   2019:        return NULL;
1.245     sjg      2020: }
                   2021:
1.275     sjg      2022: /*
                   2023:  * Return true if we should die without noise.
1.429     rillig   2024:  * For example our failing child was a sub-make or failure happened elsewhere.
1.275     sjg      2025:  */
1.534     rillig   2026: bool
1.429     rillig   2027: shouldDieQuietly(GNode *gn, int bf)
1.275     sjg      2028: {
1.453     rillig   2029:        static int quietly = -1;
1.275     sjg      2030:
1.453     rillig   2031:        if (quietly < 0) {
1.538     rillig   2032:                if (DEBUG(JOB) ||
                   2033:                    !GetBooleanExpr("${.MAKE.DIE_QUIETLY}", true))
1.453     rillig   2034:                        quietly = 0;
                   2035:                else if (bf >= 0)
                   2036:                        quietly = bf;
                   2037:                else
1.512     rillig   2038:                        quietly = (gn != NULL && (gn->type & OP_MAKE)) ? 1 : 0;
1.453     rillig   2039:        }
1.513     rillig   2040:        return quietly != 0;
1.275     sjg      2041: }
                   2042:
1.385     rillig   2043: static void
                   2044: SetErrorVars(GNode *gn)
                   2045: {
1.453     rillig   2046:        StringListNode *ln;
1.385     rillig   2047:
1.453     rillig   2048:        /*
                   2049:         * We can print this even if there is no .ERROR target.
                   2050:         */
1.528     rillig   2051:        Global_Set(".ERROR_TARGET", gn->name);
1.531     rillig   2052:        Global_Delete(".ERROR_CMD");
1.453     rillig   2053:
1.483     rillig   2054:        for (ln = gn->commands.first; ln != NULL; ln = ln->next) {
1.453     rillig   2055:                const char *cmd = ln->datum;
                   2056:
                   2057:                if (cmd == NULL)
                   2058:                        break;
1.529     rillig   2059:                Global_Append(".ERROR_CMD", cmd);
1.453     rillig   2060:        }
1.385     rillig   2061: }
                   2062:
1.507     rillig   2063: /*
                   2064:  * Print some helpful information in case of an error.
                   2065:  * The caller should exit soon after calling this function.
                   2066:  */
1.67      sjg      2067: void
1.472     rillig   2068: PrintOnError(GNode *gn, const char *msg)
1.67      sjg      2069: {
1.472     rillig   2070:        static GNode *errorNode = NULL;
1.283     sjg      2071:
1.453     rillig   2072:        if (DEBUG(HASH)) {
                   2073:                Targ_Stats();
                   2074:                Var_Stats();
                   2075:        }
                   2076:
1.509     sjg      2077:        if (errorNode != NULL)
                   2078:                return;         /* we've been here! */
1.453     rillig   2079:
1.472     rillig   2080:        if (msg != NULL)
                   2081:                printf("%s", msg);
1.453     rillig   2082:        printf("\n%s: stopped in %s\n", progname, curdir);
1.279     rillig   2083:
1.509     sjg      2084:        /* we generally want to keep quiet if a sub-make died */
                   2085:        if (shouldDieQuietly(gn, -1))
                   2086:                return;
1.472     rillig   2087:
                   2088:        if (gn != NULL)
1.453     rillig   2089:                SetErrorVars(gn);
1.472     rillig   2090:
                   2091:        {
                   2092:                char *errorVarsValues;
                   2093:                (void)Var_Subst("${MAKE_PRINT_VAR_ON_ERROR:@v@$v='${$v}'\n@}",
1.546     rillig   2094:                    SCOPE_GLOBAL, VARE_WANTRES, &errorVarsValues);
1.472     rillig   2095:                /* TODO: handle errors */
                   2096:                printf("%s", errorVarsValues);
                   2097:                free(errorVarsValues);
                   2098:        }
                   2099:
1.453     rillig   2100:        fflush(stdout);
1.176     sjg      2101:
1.453     rillig   2102:        /*
                   2103:         * Finally, see if there is a .ERROR target, and run it if so.
                   2104:         */
1.472     rillig   2105:        errorNode = Targ_FindNode(".ERROR");
                   2106:        if (errorNode != NULL) {
                   2107:                errorNode->type |= OP_SPECIAL;
                   2108:                Compat_Make(errorNode, errorNode);
1.453     rillig   2109:        }
1.68      sjg      2110: }
                   2111:
                   2112: void
1.534     rillig   2113: Main_ExportMAKEFLAGS(bool first)
1.68      sjg      2114: {
1.534     rillig   2115:        static bool once = true;
1.453     rillig   2116:        const char *expr;
                   2117:        char *s;
1.68      sjg      2118:
1.453     rillig   2119:        if (once != first)
                   2120:                return;
1.534     rillig   2121:        once = false;
1.279     rillig   2122:
1.453     rillig   2123:        expr = "${.MAKEFLAGS} ${.MAKEOVERRIDES:O:u:@v@$v=${$v:Q}@}";
1.530     rillig   2124:        (void)Var_Subst(expr, SCOPE_CMDLINE, VARE_WANTRES, &s);
1.453     rillig   2125:        /* TODO: handle errors */
                   2126:        if (s[0] != '\0') {
1.68      sjg      2127: #ifdef POSIX
1.453     rillig   2128:                setenv("MAKEFLAGS", s, 1);
1.68      sjg      2129: #else
1.453     rillig   2130:                setenv("MAKE", s, 1);
1.68      sjg      2131: #endif
1.453     rillig   2132:        }
1.1       cgd      2133: }
1.180     sjg      2134:
1.191     sjg      2135: char *
                   2136: getTmpdir(void)
1.180     sjg      2137: {
1.453     rillig   2138:        static char *tmpdir = NULL;
1.473     rillig   2139:        struct stat st;
                   2140:
                   2141:        if (tmpdir != NULL)
                   2142:                return tmpdir;
1.180     sjg      2143:
1.473     rillig   2144:        /* Honor $TMPDIR but only if it is valid. Ensure it ends with '/'. */
1.539     rillig   2145:        (void)Var_Subst("${TMPDIR:tA:U" _PATH_TMP ":S,/$,,W}/",
1.530     rillig   2146:            SCOPE_GLOBAL, VARE_WANTRES, &tmpdir);
1.473     rillig   2147:        /* TODO: handle errors */
1.180     sjg      2148:
1.473     rillig   2149:        if (stat(tmpdir, &st) < 0 || !S_ISDIR(st.st_mode)) {
                   2150:                free(tmpdir);
                   2151:                tmpdir = bmake_strdup(_PATH_TMP);
1.180     sjg      2152:        }
1.453     rillig   2153:        return tmpdir;
1.191     sjg      2154: }
                   2155:
                   2156: /*
                   2157:  * Create and open a temp file using "pattern".
1.414     rillig   2158:  * If out_fname is provided, set it to a copy of the filename created.
1.191     sjg      2159:  * Otherwise unlink the file once open.
                   2160:  */
                   2161: int
1.533     sjg      2162: mkTempFile(const char *pattern, char *tfile, size_t tfile_sz)
1.191     sjg      2163: {
1.453     rillig   2164:        static char *tmpdir = NULL;
1.533     sjg      2165:        char tbuf[MAXPATHLEN];
1.453     rillig   2166:        int fd;
                   2167:
                   2168:        if (pattern == NULL)
                   2169:                pattern = TMPPAT;
                   2170:        if (tmpdir == NULL)
                   2171:                tmpdir = getTmpdir();
1.533     sjg      2172:        if (tfile == NULL) {
1.546     rillig   2173:                tfile = tbuf;
                   2174:                tfile_sz = sizeof tbuf;
1.533     sjg      2175:        }
1.453     rillig   2176:        if (pattern[0] == '/') {
1.533     sjg      2177:                snprintf(tfile, tfile_sz, "%s", pattern);
1.453     rillig   2178:        } else {
1.533     sjg      2179:                snprintf(tfile, tfile_sz, "%s%s", tmpdir, pattern);
1.453     rillig   2180:        }
                   2181:        if ((fd = mkstemp(tfile)) < 0)
                   2182:                Punt("Could not create temporary file %s: %s", tfile,
                   2183:                    strerror(errno));
1.533     sjg      2184:        if (tfile == tbuf) {
1.479     rillig   2185:                unlink(tfile);  /* we just want the descriptor */
1.453     rillig   2186:        }
                   2187:        return fd;
1.180     sjg      2188: }
1.201     sjg      2189:
1.240     sjg      2190: /*
1.474     rillig   2191:  * Convert a string representation of a boolean into a boolean value.
1.534     rillig   2192:  * Anything that looks like "No", "False", "Off", "0" etc. is false,
                   2193:  * the empty string is the fallback, everything else is true.
1.240     sjg      2194:  */
1.534     rillig   2195: bool
                   2196: ParseBoolean(const char *s, bool fallback)
1.240     sjg      2197: {
1.474     rillig   2198:        char ch = ch_tolower(s[0]);
                   2199:        if (ch == '\0')
                   2200:                return fallback;
                   2201:        if (ch == '0' || ch == 'f' || ch == 'n')
1.534     rillig   2202:                return false;
1.474     rillig   2203:        if (ch == 'o')
                   2204:                return ch_tolower(s[1]) != 'f';
1.534     rillig   2205:        return true;
1.240     sjg      2206: }

CVSweb <webmaster@jp.NetBSD.org>