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

1.117   ! dsl         1: /*     $NetBSD: main.c,v 1.116 2005/08/09 21:36:42 christos 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.102     ross       71: #ifndef MAKE_NATIVE
1.117   ! dsl        72: static char rcsid[] = "$NetBSD: main.c,v 1.116 2005/08/09 21:36:42 christos Exp $";
1.38      lukem      73: #else
1.37      christos   74: #include <sys/cdefs.h>
1.1       cgd        75: #ifndef lint
1.37      christos   76: __COPYRIGHT("@(#) Copyright (c) 1988, 1989, 1990, 1993\n\
                     77:        The Regents of the University of California.  All rights reserved.\n");
1.1       cgd        78: #endif /* not lint */
                     79:
                     80: #ifndef lint
1.19      christos   81: #if 0
1.31      christos   82: static char sccsid[] = "@(#)main.c     8.3 (Berkeley) 3/19/94";
1.19      christos   83: #else
1.117   ! dsl        84: __RCSID("$NetBSD: main.c,v 1.116 2005/08/09 21:36:42 christos Exp $");
1.19      christos   85: #endif
1.1       cgd        86: #endif /* not lint */
1.38      lukem      87: #endif
1.1       cgd        88:
                     89: /*-
                     90:  * main.c --
                     91:  *     The main file for this entire program. Exit routines etc
                     92:  *     reside here.
                     93:  *
                     94:  * Utility functions defined in this file:
                     95:  *     Main_ParseArgLine       Takes a line of arguments, breaks them and
                     96:  *                             treats them as if they were given when first
                     97:  *                             invoked. Used by the parse module to implement
                     98:  *                             the .MFLAGS target.
                     99:  *
                    100:  *     Error                   Print a tagged error message. The global
                    101:  *                             MAKE variable must have been defined. This
                    102:  *                             takes a format string and two optional
                    103:  *                             arguments for it.
                    104:  *
                    105:  *     Fatal                   Print an error message and exit. Also takes
                    106:  *                             a format string and two arguments.
                    107:  *
                    108:  *     Punt                    Aborts all jobs and exits with a message. Also
                    109:  *                             takes a format string and two arguments.
                    110:  *
                    111:  *     Finish                  Finish things up by printing the number of
1.72      wiz       112:  *                             errors which occurred, as passed to it, and
1.1       cgd       113:  *                             exiting.
                    114:  */
                    115:
1.13      cgd       116: #include <sys/types.h>
                    117: #include <sys/time.h>
1.1       cgd       118: #include <sys/param.h>
1.13      cgd       119: #include <sys/resource.h>
1.21      christos  120: #include <sys/signal.h>
1.1       cgd       121: #include <sys/stat.h>
1.102     ross      122: #ifdef MAKE_NATIVE
1.17      gwr       123: #include <sys/utsname.h>
1.31      christos  124: #endif
1.29      christos  125: #include <sys/wait.h>
1.85      wiz       126:
1.1       cgd       127: #include <errno.h>
                    128: #include <fcntl.h>
1.85      wiz       129: #include <stdarg.h>
1.1       cgd       130: #include <stdio.h>
1.32      christos  131: #include <stdlib.h>
1.42      kleink    132: #include <time.h>
1.85      wiz       133:
1.1       cgd       134: #include "make.h"
1.13      cgd       135: #include "hash.h"
                    136: #include "dir.h"
                    137: #include "job.h"
1.1       cgd       138: #include "pathnames.h"
1.58      sommerfe  139: #include "trace.h"
1.1       cgd       140:
1.66      christos  141: #ifdef USE_IOVEC
                    142: #include <sys/uio.h>
                    143: #endif
                    144:
1.1       cgd       145: #ifndef        DEFMAXLOCAL
                    146: #define        DEFMAXLOCAL DEFMAXJOBS
1.24      christos  147: #endif /* DEFMAXLOCAL */
1.1       cgd       148:
                    149: Lst                    create;         /* Targets to be made */
                    150: time_t                 now;            /* Time at start of make */
                    151: GNode                  *DEFAULT;       /* .DEFAULT node */
                    152: Boolean                        allPrecious;    /* .PRECIOUS given on line by itself */
                    153:
                    154: static Boolean         noBuiltins;     /* -r flag */
                    155: static Lst             makefiles;      /* ordered list of makefiles to read */
1.31      christos  156: static Boolean         printVars;      /* print value of one or more vars */
                    157: static Lst             variables;      /* list of variables to print */
1.21      christos  158: int                    maxJobs;        /* -j argument */
1.1       cgd       159: static int             maxLocal;       /* -L argument */
1.13      cgd       160: Boolean                        compatMake;     /* -B argument */
1.113     christos  161: int                    debug;          /* -d argument */
1.1       cgd       162: Boolean                        noExecute;      /* -n flag */
1.61      sommerfe  163: Boolean                        noRecursiveExecute;     /* -N flag */
1.1       cgd       164: Boolean                        keepgoing;      /* -k flag */
                    165: Boolean                        queryFlag;      /* -q flag */
                    166: Boolean                        touchFlag;      /* -t flag */
                    167: Boolean                        usePipes;       /* !-P flag */
                    168: Boolean                        ignoreErrors;   /* -i flag */
                    169: Boolean                        beSilent;       /* -s flag */
                    170: Boolean                        oldVars;        /* variable substitution style */
                    171: Boolean                        checkEnvFirst;  /* -e flag */
1.63      christos  172: Boolean                        parseWarnFatal; /* -W flag */
1.58      sommerfe  173: Boolean                        jobServer;      /* -J flag */
1.87      thorpej   174: Boolean                        varNoExportEnv; /* -X flag */
1.1       cgd       175: static Boolean         jobsRunning;    /* TRUE if the jobs might be running */
1.58      sommerfe  176: static const char *    tracefile;
1.85      wiz       177: static char *          Check_Cwd_av(int, char **, int);
                    178: static void            MainParseArgs(int, char **);
                    179: static int             ReadMakefile(ClientData, ClientData);
                    180: static void            usage(void);
1.1       cgd       181:
1.74      tv        182: static char curdir[MAXPATHLEN + 1];    /* startup directory */
                    183: static char objdir[MAXPATHLEN + 1];    /* where we chdir'ed to */
1.63      christos  184: char *progname;                                /* the program name */
1.1       cgd       185:
1.58      sommerfe  186: Boolean forceJobs = FALSE;
                    187:
1.63      christos  188: extern Lst parseIncPath;
                    189:
1.1       cgd       190: /*-
                    191:  * MainParseArgs --
                    192:  *     Parse a given argument vector. Called from main() and from
                    193:  *     Main_ParseArgLine() when the .MAKEFLAGS target is used.
                    194:  *
                    195:  *     XXX: Deal with command line overriding .MAKEFLAGS in makefile
                    196:  *
                    197:  * Results:
                    198:  *     None
                    199:  *
                    200:  * Side Effects:
                    201:  *     Various global and local flags will be set depending on the flags
                    202:  *     given
                    203:  */
                    204: static void
1.85      wiz       205: MainParseArgs(int argc, char **argv)
1.1       cgd       206: {
1.47      hubertf   207:        char *p;
                    208:        int c;
1.98      ross      209:        int arginc;
                    210:        char *argvalue;
                    211:        const char *getopt_def;
                    212:        char *optscan;
1.101     ross      213:        Boolean inOption, dashDash = FALSE;
1.97      chuck     214:        char found_path[MAXPATHLEN + 1];        /* for searching for sys.mk */
1.1       cgd       215:
1.21      christos  216: #ifdef REMOTE
1.87      thorpej   217: # define OPTFLAGS "BD:I:J:L:NPST:V:WXd:ef:ij:km:nqrst"
1.13      cgd       218: #else
1.87      thorpej   219: # define OPTFLAGS "BD:I:J:NPST:V:WXd:ef:ij:km:nqrst"
1.13      cgd       220: #endif
1.98      ross      221: #undef optarg
                    222: #define optarg argvalue
                    223: /* Can't actually use getopt(3) because rescanning is not portable */
                    224:
                    225:        getopt_def = OPTFLAGS;
                    226: rearg:
                    227:        inOption = FALSE;
1.108     lukem     228:        optscan = NULL;
1.98      ross      229:        while(argc > 1) {
                    230:                char *getopt_spec;
                    231:                if(!inOption)
                    232:                        optscan = argv[1];
                    233:                c = *optscan++;
                    234:                arginc = 0;
                    235:                if(inOption) {
                    236:                        if(c == '\0') {
                    237:                                ++argv;
                    238:                                --argc;
                    239:                                inOption = FALSE;
                    240:                                continue;
                    241:                        }
                    242:                } else {
1.101     ross      243:                        if (c != '-' || dashDash)
1.98      ross      244:                                break;
                    245:                        inOption = TRUE;
                    246:                        c = *optscan++;
                    247:                }
                    248:                /* '-' found at some earlier point */
                    249:                getopt_spec = strchr(getopt_def, c);
                    250:                if(c != '\0' && getopt_spec != NULL && getopt_spec[1] == ':') {
                    251:                        /* -<something> found, and <something> should have an arg */
                    252:                        inOption = FALSE;
                    253:                        arginc = 1;
                    254:                        argvalue = optscan;
                    255:                        if(*argvalue == '\0') {
1.100     enami     256:                                if (argc < 3) {
                    257:                                        (void)fprintf(stderr,
                    258:                                            "%s: option requires "
                    259:                                            "an argument -- %c\n",
                    260:                                            progname, c);
                    261:                                        usage();
                    262:                                }
1.98      ross      263:                                argvalue = argv[2];
                    264:                                arginc = 2;
                    265:                        }
1.108     lukem     266:                } else {
                    267:                        argvalue = NULL;
1.98      ross      268:                }
1.1       cgd       269:                switch(c) {
1.98      ross      270:                case '\0':
                    271:                        arginc = 1;
                    272:                        inOption = FALSE;
                    273:                        break;
1.92      sjg       274:                case 'B':
                    275:                        compatMake = TRUE;
                    276:                        Var_Append(MAKEFLAGS, "-B", VAR_GLOBAL);
                    277:                        break;
1.1       cgd       278:                case 'D':
1.71      sjg       279:                        Var_Set(optarg, "1", VAR_GLOBAL, 0);
1.1       cgd       280:                        Var_Append(MAKEFLAGS, "-D", VAR_GLOBAL);
                    281:                        Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
                    282:                        break;
                    283:                case 'I':
                    284:                        Parse_AddIncludeDir(optarg);
                    285:                        Var_Append(MAKEFLAGS, "-I", VAR_GLOBAL);
                    286:                        Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
                    287:                        break;
1.58      sommerfe  288:                case 'J':
                    289:                        if (sscanf(optarg, "%d,%d", &job_pipe[0], &job_pipe[1]) != 2) {
1.65      cgd       290:                            /* backslash to avoid trigraph ??) */
1.63      christos  291:                            (void)fprintf(stderr,
1.65      cgd       292:                                "%s: internal error -- J option malformed (%s?\?)\n",
1.63      christos  293:                                progname, optarg);
1.58      sommerfe  294:                                usage();
                    295:                        }
                    296:                        if ((fcntl(job_pipe[0], F_GETFD, 0) < 0) ||
                    297:                            (fcntl(job_pipe[1], F_GETFD, 0) < 0)) {
1.61      sommerfe  298: #if 0
1.58      sommerfe  299:                            (void)fprintf(stderr,
1.63      christos  300:                                "%s: warning -- J descriptors were closed!\n",
                    301:                                progname);
1.61      sommerfe  302: #endif
1.58      sommerfe  303:                            job_pipe[0] = -1;
                    304:                            job_pipe[1] = -1;
1.61      sommerfe  305:                            compatMake = TRUE;
1.58      sommerfe  306:                        } else {
                    307:                            Var_Append(MAKEFLAGS, "-J", VAR_GLOBAL);
                    308:                            Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
                    309:                            jobServer = TRUE;
                    310:                        }
                    311:                        break;
1.21      christos  312: #ifdef REMOTE
1.1       cgd       313:                case 'L':
1.47      hubertf   314:                        maxLocal = strtol(optarg, &p, 0);
                    315:                        if (*p != '\0' || maxLocal < 1) {
1.112     christos  316:                            (void)fprintf(stderr, "%s: illegal argument to -L -- must be positive integer!\n",
1.63      christos  317:                                progname);
                    318:                            exit(1);
1.46      hubertf   319:                        }
1.1       cgd       320:                        Var_Append(MAKEFLAGS, "-L", VAR_GLOBAL);
                    321:                        Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
                    322:                        break;
1.21      christos  323: #endif
1.61      sommerfe  324:                case 'N':
                    325:                        noExecute = TRUE;
                    326:                        noRecursiveExecute = TRUE;
                    327:                        Var_Append(MAKEFLAGS, "-N", VAR_GLOBAL);
                    328:                        break;
1.1       cgd       329:                case 'P':
                    330:                        usePipes = FALSE;
                    331:                        Var_Append(MAKEFLAGS, "-P", VAR_GLOBAL);
                    332:                        break;
                    333:                case 'S':
                    334:                        keepgoing = FALSE;
                    335:                        Var_Append(MAKEFLAGS, "-S", VAR_GLOBAL);
                    336:                        break;
1.58      sommerfe  337:                case 'T':
1.59      sommerfe  338:                        tracefile = estrdup(optarg);
1.58      sommerfe  339:                        Var_Append(MAKEFLAGS, "-T", VAR_GLOBAL);
                    340:                        Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
                    341:                        break;
1.92      sjg       342:                case 'V':
                    343:                        printVars = TRUE;
                    344:                        (void)Lst_AtEnd(variables, (ClientData)optarg);
                    345:                        Var_Append(MAKEFLAGS, "-V", VAR_GLOBAL);
                    346:                        Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
                    347:                        break;
1.63      christos  348:                case 'W':
                    349:                        parseWarnFatal = TRUE;
1.87      thorpej   350:                        break;
                    351:                case 'X':
                    352:                        varNoExportEnv = TRUE;
                    353:                        Var_Append(MAKEFLAGS, "-X", VAR_GLOBAL);
1.63      christos  354:                        break;
1.1       cgd       355:                case 'd': {
                    356:                        char *modules = optarg;
                    357:
                    358:                        for (; *modules; ++modules)
                    359:                                switch (*modules) {
                    360:                                case 'A':
                    361:                                        debug = ~0;
                    362:                                        break;
                    363:                                case 'a':
                    364:                                        debug |= DEBUG_ARCH;
                    365:                                        break;
                    366:                                case 'c':
                    367:                                        debug |= DEBUG_COND;
                    368:                                        break;
                    369:                                case 'd':
                    370:                                        debug |= DEBUG_DIR;
1.93      jmmv      371:                                        break;
                    372:                                case 'e':
                    373:                                        debug |= DEBUG_ERROR;
1.1       cgd       374:                                        break;
1.13      cgd       375:                                case 'f':
                    376:                                        debug |= DEBUG_FOR;
                    377:                                        break;
1.1       cgd       378:                                case 'g':
                    379:                                        if (modules[1] == '1') {
                    380:                                                debug |= DEBUG_GRAPH1;
                    381:                                                ++modules;
                    382:                                        }
                    383:                                        else if (modules[1] == '2') {
                    384:                                                debug |= DEBUG_GRAPH2;
                    385:                                                ++modules;
                    386:                                        }
1.94      dsl       387:                                        else if (modules[1] == '3') {
                    388:                                                debug |= DEBUG_GRAPH3;
                    389:                                                ++modules;
                    390:                                        }
1.1       cgd       391:                                        break;
                    392:                                case 'j':
                    393:                                        debug |= DEBUG_JOB;
                    394:                                        break;
                    395:                                case 'm':
                    396:                                        debug |= DEBUG_MAKE;
                    397:                                        break;
1.109     jmc       398:                                case 'n':
                    399:                                        debug |= DEBUG_SCRIPT;
                    400:                                        break;
1.1       cgd       401:                                case 's':
                    402:                                        debug |= DEBUG_SUFF;
                    403:                                        break;
                    404:                                case 't':
                    405:                                        debug |= DEBUG_TARG;
                    406:                                        break;
                    407:                                case 'v':
                    408:                                        debug |= DEBUG_VAR;
                    409:                                        break;
1.67      sjg       410:                                case 'x':
                    411:                                        debug |= DEBUG_SHELL;
                    412:                                        break;
1.1       cgd       413:                                default:
                    414:                                        (void)fprintf(stderr,
1.63      christos  415:                                "%s: illegal argument to d option -- %c\n",
                    416:                                            progname, *modules);
1.1       cgd       417:                                        usage();
                    418:                                }
                    419:                        Var_Append(MAKEFLAGS, "-d", VAR_GLOBAL);
                    420:                        Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
                    421:                        break;
                    422:                }
                    423:                case 'e':
                    424:                        checkEnvFirst = TRUE;
                    425:                        Var_Append(MAKEFLAGS, "-e", VAR_GLOBAL);
                    426:                        break;
                    427:                case 'f':
                    428:                        (void)Lst_AtEnd(makefiles, (ClientData)optarg);
                    429:                        break;
                    430:                case 'i':
                    431:                        ignoreErrors = TRUE;
                    432:                        Var_Append(MAKEFLAGS, "-i", VAR_GLOBAL);
                    433:                        break;
                    434:                case 'j':
1.22      christos  435:                        forceJobs = TRUE;
1.47      hubertf   436:                        maxJobs = strtol(optarg, &p, 0);
                    437:                        if (*p != '\0' || maxJobs < 1) {
1.112     christos  438:                                (void)fprintf(stderr, "%s: illegal argument to -j -- must be positive integer!\n",
1.63      christos  439:                                    progname);
1.46      hubertf   440:                                exit(1);
                    441:                        }
1.21      christos  442: #ifndef REMOTE
                    443:                        maxLocal = maxJobs;
                    444: #endif
1.9       jtc       445:                        Var_Append(MAKEFLAGS, "-j", VAR_GLOBAL);
1.1       cgd       446:                        Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
                    447:                        break;
                    448:                case 'k':
                    449:                        keepgoing = TRUE;
                    450:                        Var_Append(MAKEFLAGS, "-k", VAR_GLOBAL);
                    451:                        break;
1.25      christos  452:                case 'm':
1.97      chuck     453:                        /* look for magic parent directory search string */
                    454:                        if (strncmp(".../", optarg, 4) == 0) {
                    455:                                if (!Dir_FindHereOrAbove(curdir, optarg+4,
                    456:                                    found_path, sizeof(found_path)))
                    457:                                        break;          /* nothing doing */
1.112     christos  458:                                (void)Dir_AddDir(sysIncPath, found_path);
1.97      chuck     459:
                    460:                        } else {
1.112     christos  461:                                (void)Dir_AddDir(sysIncPath, optarg);
1.97      chuck     462:                        }
1.25      christos  463:                        Var_Append(MAKEFLAGS, "-m", VAR_GLOBAL);
                    464:                        Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
                    465:                        break;
1.1       cgd       466:                case 'n':
                    467:                        noExecute = TRUE;
                    468:                        Var_Append(MAKEFLAGS, "-n", VAR_GLOBAL);
                    469:                        break;
                    470:                case 'q':
                    471:                        queryFlag = TRUE;
                    472:                        /* Kind of nonsensical, wot? */
                    473:                        Var_Append(MAKEFLAGS, "-q", VAR_GLOBAL);
                    474:                        break;
                    475:                case 'r':
                    476:                        noBuiltins = TRUE;
                    477:                        Var_Append(MAKEFLAGS, "-r", VAR_GLOBAL);
                    478:                        break;
                    479:                case 's':
                    480:                        beSilent = TRUE;
                    481:                        Var_Append(MAKEFLAGS, "-s", VAR_GLOBAL);
                    482:                        break;
                    483:                case 't':
                    484:                        touchFlag = TRUE;
                    485:                        Var_Append(MAKEFLAGS, "-t", VAR_GLOBAL);
                    486:                        break;
1.101     ross      487:                case '-':
                    488:                        dashDash = TRUE;
                    489:                        break;
1.1       cgd       490:                default:
                    491:                case '?':
                    492:                        usage();
                    493:                }
1.98      ross      494:                argv += arginc;
                    495:                argc -= arginc;
1.1       cgd       496:        }
                    497:
                    498:        oldVars = TRUE;
                    499:
                    500:        /*
                    501:         * See if the rest of the arguments are variable assignments and
                    502:         * perform them if so. Else take them to be targets and stuff them
                    503:         * on the end of the "create" list.
                    504:         */
1.98      ross      505:        for (; argc > 1; ++argv, --argc)
                    506:                if (Parse_IsVar(argv[1])) {
                    507:                        Parse_DoVar(argv[1], VAR_CMD);
1.67      sjg       508:                } else {
1.98      ross      509:                        if (!*argv[1])
1.1       cgd       510:                                Punt("illegal (null) argument.");
1.101     ross      511:                        if (*argv[1] == '-' && !dashDash)
1.1       cgd       512:                                goto rearg;
1.98      ross      513:                        (void)Lst_AtEnd(create, (ClientData)estrdup(argv[1]));
1.1       cgd       514:                }
                    515: }
                    516:
                    517: /*-
                    518:  * Main_ParseArgLine --
                    519:  *     Used by the parse module when a .MFLAGS or .MAKEFLAGS target
                    520:  *     is encountered and by main() when reading the .MAKEFLAGS envariable.
                    521:  *     Takes a line of arguments and breaks it into its
                    522:  *     component words and passes those words and the number of them to the
                    523:  *     MainParseArgs function.
                    524:  *     The line should have all its leading whitespace removed.
                    525:  *
1.85      wiz       526:  * Input:
                    527:  *     line            Line to fracture
                    528:  *
1.1       cgd       529:  * Results:
                    530:  *     None
                    531:  *
                    532:  * Side Effects:
                    533:  *     Only those that come from the various arguments.
                    534:  */
                    535: void
1.85      wiz       536: Main_ParseArgLine(char *line)
1.1       cgd       537: {
                    538:        char **argv;                    /* Manufactured argument vector */
                    539:        int argc;                       /* Number of arguments in argv */
1.40      christos  540:        char *args;                     /* Space used by the args */
                    541:        char *buf, *p1;
                    542:        char *argv0 = Var_Value(".MAKE", VAR_GLOBAL, &p1);
1.48      christos  543:        size_t len;
1.1       cgd       544:
                    545:        if (line == NULL)
                    546:                return;
1.13      cgd       547:        for (; *line == ' '; ++line)
                    548:                continue;
1.1       cgd       549:        if (!*line)
                    550:                return;
                    551:
1.48      christos  552:        buf = emalloc(len = strlen(line) + strlen(argv0) + 2);
                    553:        (void)snprintf(buf, len, "%s %s", argv0, line);
1.40      christos  554:        if (p1)
                    555:                free(p1);
                    556:
1.41      christos  557:        argv = brk_string(buf, &argc, TRUE, &args);
1.45      itohy     558:        free(buf);
1.1       cgd       559:        MainParseArgs(argc, argv);
1.40      christos  560:
                    561:        free(args);
                    562:        free(argv);
1.1       cgd       563: }
                    564:
1.74      tv        565: Boolean
1.85      wiz       566: Main_SetObjdir(const char *path)
1.31      christos  567: {
                    568:        struct stat sb;
1.74      tv        569:        char *p = NULL;
                    570:        char buf[MAXPATHLEN + 1];
1.76      tv        571:        Boolean rc = FALSE;
1.31      christos  572:
1.74      tv        573:        /* expand variable substitutions */
1.51      sjg       574:        if (strchr(path, '$') != 0) {
1.74      tv        575:                snprintf(buf, MAXPATHLEN, "%s", path);
                    576:                path = p = Var_Subst(NULL, buf, VAR_GLOBAL, 0);
1.51      sjg       577:        }
1.74      tv        578:
                    579:        if (path[0] != '/') {
                    580:                snprintf(buf, MAXPATHLEN, "%s/%s", curdir, path);
                    581:                path = buf;
                    582:        }
                    583:
                    584:        /* look for the directory and try to chdir there */
1.31      christos  585:        if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) {
                    586:                if (chdir(path)) {
                    587:                        (void)fprintf(stderr, "make warning: %s: %s.\n",
                    588:                                      path, strerror(errno));
1.74      tv        589:                } else {
                    590:                        strncpy(objdir, path, MAXPATHLEN);
                    591:                        Var_Set(".OBJDIR", objdir, VAR_GLOBAL, 0);
                    592:                        setenv("PWD", objdir, 1);
1.79      tv        593:                        Dir_InitDot();
1.74      tv        594:                        rc = TRUE;
1.31      christos  595:                }
                    596:        }
                    597:
1.74      tv        598:        if (p)
                    599:                free(p);
                    600:        return rc;
1.31      christos  601: }
                    602:
                    603:
1.1       cgd       604: /*-
                    605:  * main --
                    606:  *     The main function, for obvious reasons. Initializes variables
                    607:  *     and a few modules, then parses the arguments give it in the
                    608:  *     environment and on the command line. Reads the system makefile
                    609:  *     followed by either Makefile, makefile or the file given by the
                    610:  *     -f argument. Sets the .MAKEFLAGS PMake variable based on all the
                    611:  *     flags it has received by then uses either the Make or the Compat
                    612:  *     module to create the initial list of targets.
                    613:  *
                    614:  * Results:
                    615:  *     If -q was given, exits -1 if anything was out-of-date. Else it exits
                    616:  *     0.
                    617:  *
                    618:  * Side Effects:
                    619:  *     The program exits when done. Targets are created. etc. etc. etc.
                    620:  */
1.13      cgd       621: int
1.85      wiz       622: main(int argc, char **argv)
1.1       cgd       623: {
                    624:        Lst targs;      /* target nodes to create -- passed to Make_Init */
1.13      cgd       625:        Boolean outOfDate = TRUE;       /* FALSE if all targets up to date */
1.77      tv        626:        struct stat sb, sa;
                    627:        char *p1, *path, *pwd;
1.74      tv        628:        char mdpath[MAXPATHLEN];
1.18      christos  629:        char *machine = getenv("MACHINE");
1.89      christos  630:        const char *machine_arch = getenv("MACHINE_ARCH");
1.55      sjg       631:        char *syspath = getenv("MAKESYSPATH");
1.25      christos  632:        Lst sysMkPath;                  /* Path of sys.mk */
                    633:        char *cp = NULL, *start;
                    634:                                        /* avoid faults on read-only strings */
1.55      sjg       635:        static char defsyspath[] = _PATH_DEFSYSPATH;
1.97      chuck     636:        char found_path[MAXPATHLEN + 1];        /* for searching for sys.mk */
1.107     sjg       637:        struct timeval rightnow;                /* to initialize random seed */
                    638:
                    639:        /*
                    640:         * Set the seed to produce a different random sequences
                    641:         * on each program execution.
                    642:         */
                    643:        gettimeofday(&rightnow, NULL);
                    644:        srandom(rightnow.tv_sec + rightnow.tv_usec);
1.55      sjg       645:
1.53      christos  646:        if ((progname = strrchr(argv[0], '/')) != NULL)
                    647:                progname++;
                    648:        else
                    649:                progname = argv[0];
1.21      christos  650: #ifdef RLIMIT_NOFILE
                    651:        /*
                    652:         * get rid of resource limit on file descriptors
                    653:         */
                    654:        {
                    655:                struct rlimit rl;
                    656:                if (getrlimit(RLIMIT_NOFILE, &rl) != -1 &&
                    657:                    rl.rlim_cur != rl.rlim_max) {
                    658:                        rl.rlim_cur = rl.rlim_max;
1.112     christos  659:                        (void)setrlimit(RLIMIT_NOFILE, &rl);
1.21      christos  660:                }
                    661:        }
                    662: #endif
1.13      cgd       663:        /*
                    664:         * Find where we are and take care of PWD for the automounter...
                    665:         * All this code is so that we know where we are when we start up
                    666:         * on a different machine with pmake.
                    667:         */
1.16      mycroft   668:        if (getcwd(curdir, MAXPATHLEN) == NULL) {
1.63      christos  669:                (void)fprintf(stderr, "%s: %s.\n", progname, strerror(errno));
1.13      cgd       670:                exit(2);
                    671:        }
                    672:
1.77      tv        673:        if (stat(curdir, &sa) == -1) {
1.63      christos  674:            (void)fprintf(stderr, "%s: %s: %s.\n",
                    675:                 progname, curdir, strerror(errno));
1.13      cgd       676:            exit(2);
1.77      tv        677:        }
                    678:
                    679:        /*
                    680:         * Overriding getcwd() with $PWD totally breaks MAKEOBJDIRPREFIX
                    681:         * since the value of curdir can very depending on how we got
                    682:         * here.  Ie sitting at a shell prompt (shell that provides $PWD)
                    683:         * or via subdir.mk in which case its likely a shell which does
                    684:         * not provide it.
                    685:         * So, to stop it breaking this case only, we ignore PWD if
                    686:         * MAKEOBJDIRPREFIX is set or MAKEOBJDIR contains a transform.
                    687:         */
                    688:        if ((pwd = getenv("PWD")) != NULL && getenv("MAKEOBJDIRPREFIX") == NULL) {
                    689:                const char *makeobjdir = getenv("MAKEOBJDIR");
                    690:
                    691:                if (makeobjdir == NULL || !strchr(makeobjdir, '$')) {
                    692:                        if (stat(pwd, &sb) == 0 && sa.st_ino == sb.st_ino &&
                    693:                            sa.st_dev == sb.st_dev)
1.112     christos  694:                                (void)strncpy(curdir, pwd, MAXPATHLEN);
1.77      tv        695:                }
1.13      cgd       696:        }
                    697:
1.17      gwr       698:        /*
                    699:         * Get the name of this type of MACHINE from utsname
                    700:         * so we can share an executable for similar machines.
                    701:         * (i.e. m68k: amiga hp300, mac68k, sun3, ...)
                    702:         *
1.33      christos  703:         * Note that both MACHINE and MACHINE_ARCH are decided at
                    704:         * run-time.
1.17      gwr       705:         */
1.34      gwr       706:        if (!machine) {
1.102     ross      707: #ifdef MAKE_NATIVE
1.31      christos  708:            struct utsname utsname;
                    709:
1.23      christos  710:            if (uname(&utsname) == -1) {
1.63      christos  711:                (void)fprintf(stderr, "%s: uname failed (%s).\n", progname,
                    712:                    strerror(errno));
                    713:                exit(2);
1.18      christos  714:            }
                    715:            machine = utsname.machine;
1.26      christos  716: #else
1.81      tv        717: #ifdef MAKE_MACHINE
1.80      thorpej   718:            machine = MAKE_MACHINE;
1.81      tv        719: #else
                    720:            machine = "unknown";
                    721: #endif
1.26      christos  722: #endif
1.17      gwr       723:        }
1.1       cgd       724:
1.33      christos  725:        if (!machine_arch) {
                    726: #ifndef MACHINE_ARCH
1.80      thorpej   727: #ifdef MAKE_MACHINE_ARCH
                    728:             machine_arch = MAKE_MACHINE_ARCH;
1.43      wsanchez  729: #else
1.81      tv        730:            machine_arch = "unknown";
1.43      wsanchez  731: #endif
1.33      christos  732: #else
                    733:            machine_arch = MACHINE_ARCH;
                    734: #endif
                    735:        }
                    736:
1.1       cgd       737:        /*
1.51      sjg       738:         * Just in case MAKEOBJDIR wants us to do something tricky.
                    739:         */
                    740:        Var_Init();             /* Initialize the lists of variables for
                    741:                                 * parsing arguments */
1.71      sjg       742:        Var_Set(".CURDIR", curdir, VAR_GLOBAL, 0);
                    743:        Var_Set("MACHINE", machine, VAR_GLOBAL, 0);
                    744:        Var_Set("MACHINE_ARCH", machine_arch, VAR_GLOBAL, 0);
1.67      sjg       745: #ifdef MAKE_VERSION
1.71      sjg       746:        Var_Set("MAKE_VERSION", MAKE_VERSION, VAR_GLOBAL, 0);
1.67      sjg       747: #endif
1.71      sjg       748:        Var_Set(".newline", "\n", VAR_GLOBAL, 0); /* handy for :@ loops */
1.51      sjg       749:
                    750:        /*
1.74      tv        751:         * Find the .OBJDIR.  If MAKEOBJDIRPREFIX, or failing that,
                    752:         * MAKEOBJDIR is set in the environment, try only that value
                    753:         * and fall back to .CURDIR if it does not exist.
1.111     lukem     754:         *
                    755:         * Otherwise, try _PATH_OBJDIR.MACHINE, _PATH_OBJDIR, and
                    756:         * finally _PATH_OBJDIRPREFIX`pwd`, in that order.  If none
                    757:         * of these paths exist, just use .CURDIR.
1.74      tv        758:         */
1.79      tv        759:        Dir_Init(curdir);
1.112     christos  760:        (void)Main_SetObjdir(curdir);
1.79      tv        761:
1.74      tv        762:        if ((path = getenv("MAKEOBJDIRPREFIX")) != NULL) {
1.112     christos  763:                (void)snprintf(mdpath, MAXPATHLEN, "%s%s", path, curdir);
                    764:                (void)Main_SetObjdir(mdpath);
1.74      tv        765:        } else if ((path = getenv("MAKEOBJDIR")) != NULL) {
1.112     christos  766:                (void)Main_SetObjdir(path);
1.111     lukem     767:        } else {
1.112     christos  768:                (void)snprintf(mdpath, MAXPATHLEN, "%s.%s", _PATH_OBJDIR, machine);
1.111     lukem     769:                if (!Main_SetObjdir(mdpath) && !Main_SetObjdir(_PATH_OBJDIR)) {
1.112     christos  770:                        (void)snprintf(mdpath, MAXPATHLEN, "%s%s",
1.111     lukem     771:                                        _PATH_OBJDIRPREFIX, curdir);
1.112     christos  772:                        (void)Main_SetObjdir(mdpath);
1.111     lukem     773:                }
1.4       cgd       774:        }
1.13      cgd       775:
1.1       cgd       776:        create = Lst_Init(FALSE);
                    777:        makefiles = Lst_Init(FALSE);
1.31      christos  778:        printVars = FALSE;
                    779:        variables = Lst_Init(FALSE);
1.1       cgd       780:        beSilent = FALSE;               /* Print commands as executed */
                    781:        ignoreErrors = FALSE;           /* Pay attention to non-zero returns */
                    782:        noExecute = FALSE;              /* Execute all commands */
1.61      sommerfe  783:        noRecursiveExecute = FALSE;     /* Execute all .MAKE targets */
1.1       cgd       784:        keepgoing = FALSE;              /* Stop on error */
                    785:        allPrecious = FALSE;            /* Remove targets when interrupted */
                    786:        queryFlag = FALSE;              /* This is not just a check-run */
                    787:        noBuiltins = FALSE;             /* Read the built-in rules */
                    788:        touchFlag = FALSE;              /* Actually update targets */
                    789:        usePipes = TRUE;                /* Catch child output in pipes */
                    790:        debug = 0;                      /* No debug verbosity, please. */
                    791:        jobsRunning = FALSE;
                    792:
1.21      christos  793:        maxLocal = DEFMAXLOCAL;         /* Set default local max concurrency */
                    794: #ifdef REMOTE
1.1       cgd       795:        maxJobs = DEFMAXJOBS;           /* Set default max concurrency */
1.13      cgd       796: #else
1.21      christos  797:        maxJobs = maxLocal;
1.13      cgd       798: #endif
1.21      christos  799:        compatMake = FALSE;             /* No compat mode */
1.31      christos  800:
1.13      cgd       801:
1.1       cgd       802:        /*
                    803:         * Initialize the parsing, directory and variable modules to prepare
                    804:         * for the reading of inclusion paths and variable settings on the
                    805:         * command line
                    806:         */
1.36      gwr       807:
                    808:        /*
1.1       cgd       809:         * Initialize various variables.
                    810:         *      MAKE also gets this name, for compatibility
                    811:         *      .MAKEFLAGS gets set to the empty string just in case.
                    812:         *      MFLAGS also gets initialized empty, for compatibility.
                    813:         */
1.79      tv        814:        Parse_Init();
1.71      sjg       815:        Var_Set("MAKE", argv[0], VAR_GLOBAL, 0);
                    816:        Var_Set(".MAKE", argv[0], VAR_GLOBAL, 0);
                    817:        Var_Set(MAKEFLAGS, "", VAR_GLOBAL, 0);
                    818:        Var_Set(MAKEOVERRIDES, "", VAR_GLOBAL, 0);
                    819:        Var_Set("MFLAGS", "", VAR_GLOBAL, 0);
1.78      tv        820:        Var_Set(".ALLTARGETS", "", VAR_GLOBAL, 0);
1.1       cgd       821:
                    822:        /*
                    823:         * First snag any flags out of the MAKE environment variable.
                    824:         * (Note this is *not* MAKEFLAGS since /bin/make uses that and it's
                    825:         * in a different format).
                    826:         */
                    827: #ifdef POSIX
                    828:        Main_ParseArgLine(getenv("MAKEFLAGS"));
                    829: #else
                    830:        Main_ParseArgLine(getenv("MAKE"));
                    831: #endif
1.31      christos  832:
1.1       cgd       833:        MainParseArgs(argc, argv);
                    834:
                    835:        /*
1.58      sommerfe  836:         * Be compatible if user did not specify -j and did not explicitly
                    837:         * turned compatibility on
                    838:         */
                    839:        if (!compatMake && !forceJobs) {
                    840:                compatMake = TRUE;
                    841:        }
                    842:
                    843:        /*
1.1       cgd       844:         * Initialize archive, target and suffix modules in preparation for
                    845:         * parsing the makefile(s)
                    846:         */
                    847:        Arch_Init();
                    848:        Targ_Init();
                    849:        Suff_Init();
1.58      sommerfe  850:        Trace_Init(tracefile);
1.1       cgd       851:
                    852:        DEFAULT = NILGNODE;
                    853:        (void)time(&now);
                    854:
1.58      sommerfe  855:        Trace_Log(MAKESTART, NULL);
                    856:
1.1       cgd       857:        /*
                    858:         * Set up the .TARGETS variable to contain the list of targets to be
                    859:         * created. If none specified, make the variable empty -- the parser
                    860:         * will fill the thing in with the default or .MAIN target.
                    861:         */
                    862:        if (!Lst_IsEmpty(create)) {
                    863:                LstNode ln;
                    864:
                    865:                for (ln = Lst_First(create); ln != NILLNODE;
                    866:                    ln = Lst_Succ(ln)) {
                    867:                        char *name = (char *)Lst_Datum(ln);
                    868:
                    869:                        Var_Append(".TARGETS", name, VAR_GLOBAL);
                    870:                }
                    871:        } else
1.71      sjg       872:                Var_Set(".TARGETS", "", VAR_GLOBAL, 0);
1.1       cgd       873:
1.25      christos  874:
1.1       cgd       875:        /*
1.25      christos  876:         * If no user-supplied system path was given (through the -m option)
                    877:         * add the directories from the DEFSYSPATH (more than one may be given
                    878:         * as dir1:...:dirn) to the system include path.
1.1       cgd       879:         */
1.73      tv        880:        if (syspath == NULL || *syspath == '\0')
                    881:                syspath = defsyspath;
                    882:        else
                    883:                syspath = strdup(syspath);
                    884:
                    885:        for (start = syspath; *start != '\0'; start = cp) {
                    886:                for (cp = start; *cp != '\0' && *cp != ':'; cp++)
                    887:                        continue;
1.97      chuck     888:                if (*cp == ':') {
                    889:                        *cp++ = '\0';
                    890:                }
                    891:                /* look for magic parent directory search string */
                    892:                if (strncmp(".../", start, 4) != 0) {
1.112     christos  893:                        (void)Dir_AddDir(defIncPath, start);
1.73      tv        894:                } else {
1.97      chuck     895:                        if (Dir_FindHereOrAbove(curdir, start+4,
                    896:                            found_path, sizeof(found_path))) {
1.112     christos  897:                                (void)Dir_AddDir(defIncPath, found_path);
1.97      chuck     898:                        }
1.25      christos  899:                }
                    900:        }
1.73      tv        901:        if (syspath != defsyspath)
                    902:                free(syspath);
1.25      christos  903:
                    904:        /*
                    905:         * Read in the built-in rules first, followed by the specified
1.115     christos  906:         * makefile, if it was (makefile != NULL), or the default
1.99      fair      907:         * makefile and Makefile, in that order, if it wasn't.
1.25      christos  908:         */
                    909:        if (!noBuiltins) {
                    910:                LstNode ln;
                    911:
1.106     christos  912:                sysMkPath = Lst_Init(FALSE);
1.73      tv        913:                Dir_Expand(_PATH_DEFSYSMK,
                    914:                           Lst_IsEmpty(sysIncPath) ? defIncPath : sysIncPath,
                    915:                           sysMkPath);
1.25      christos  916:                if (Lst_IsEmpty(sysMkPath))
1.63      christos  917:                        Fatal("%s: no system rules (%s).", progname,
                    918:                            _PATH_DEFSYSMK);
1.25      christos  919:                ln = Lst_Find(sysMkPath, (ClientData)NULL, ReadMakefile);
                    920:                if (ln != NILLNODE)
1.63      christos  921:                        Fatal("%s: cannot open %s.", progname,
                    922:                            (char *)Lst_Datum(ln));
1.25      christos  923:        }
1.1       cgd       924:
                    925:        if (!Lst_IsEmpty(makefiles)) {
                    926:                LstNode ln;
                    927:
                    928:                ln = Lst_Find(makefiles, (ClientData)NULL, ReadMakefile);
                    929:                if (ln != NILLNODE)
1.63      christos  930:                        Fatal("%s: cannot open %s.", progname,
                    931:                            (char *)Lst_Datum(ln));
1.89      christos  932:        } else if (!ReadMakefile(UNCONST("makefile"), NULL))
                    933:                (void)ReadMakefile(UNCONST("Makefile"), NULL);
1.1       cgd       934:
1.89      christos  935:        (void)ReadMakefile(UNCONST(".depend"), NULL);
1.1       cgd       936:
1.14      jtc       937:        Var_Append("MFLAGS", Var_Value(MAKEFLAGS, VAR_GLOBAL, &p1), VAR_GLOBAL);
                    938:        if (p1)
                    939:            free(p1);
1.1       cgd       940:
1.58      sommerfe  941:        if (!jobServer && !compatMake)
                    942:            Job_ServerStart(maxJobs);
                    943:        if (DEBUG(JOB))
                    944:            printf("job_pipe %d %d, maxjobs %d maxlocal %d compat %d\n", job_pipe[0], job_pipe[1], maxJobs,
                    945:                   maxLocal, compatMake);
                    946:
1.73      tv        947:        Main_ExportMAKEFLAGS(TRUE);     /* initial export */
1.1       cgd       948:
1.54      sjg       949:        Check_Cwd_av(0, NULL, 0);       /* initialize it */
                    950:
                    951:
1.1       cgd       952:        /*
                    953:         * For compatibility, look at the directories in the VPATH variable
                    954:         * and add them to the search path, if the variable is defined. The
                    955:         * variable's value is in the same format as the PATH envariable, i.e.
                    956:         * <directory>:<directory>:<directory>...
                    957:         */
                    958:        if (Var_Exists("VPATH", VAR_CMD)) {
1.82      reinoud   959:                char *vpath, savec;
1.1       cgd       960:                /*
                    961:                 * GCC stores string constants in read-only memory, but
                    962:                 * Var_Subst will want to write this thing, so store it
                    963:                 * in an array
                    964:                 */
                    965:                static char VPATH[] = "${VPATH}";
                    966:
1.13      cgd       967:                vpath = Var_Subst(NULL, VPATH, VAR_CMD, FALSE);
1.1       cgd       968:                path = vpath;
                    969:                do {
                    970:                        /* skip to end of directory */
1.13      cgd       971:                        for (cp = path; *cp != ':' && *cp != '\0'; cp++)
                    972:                                continue;
1.1       cgd       973:                        /* Save terminator character so know when to stop */
                    974:                        savec = *cp;
                    975:                        *cp = '\0';
                    976:                        /* Add directory to search path */
1.112     christos  977:                        (void)Dir_AddDir(dirSearchPath, path);
1.1       cgd       978:                        *cp = savec;
                    979:                        path = cp + 1;
                    980:                } while (savec == ':');
1.114     christos  981:                free(vpath);
1.1       cgd       982:        }
                    983:
                    984:        /*
                    985:         * Now that all search paths have been read for suffixes et al, it's
                    986:         * time to add the default search path to their lists...
                    987:         */
                    988:        Suff_DoPaths();
1.50      mycroft   989:
                    990:        /*
                    991:         * Propagate attributes through :: dependency lists.
                    992:         */
                    993:        Targ_Propagate();
1.1       cgd       994:
                    995:        /* print the initial graph, if the user requested it */
                    996:        if (DEBUG(GRAPH1))
                    997:                Targ_PrintGraph(1);
                    998:
1.31      christos  999:        /* print the values of any variables requested by the user */
                   1000:        if (printVars) {
                   1001:                LstNode ln;
                   1002:
                   1003:                for (ln = Lst_First(variables); ln != NILLNODE;
                   1004:                    ln = Lst_Succ(ln)) {
1.92      sjg      1005:                        char *var = (char *)Lst_Datum(ln);
                   1006:                        char *value;
                   1007:
                   1008:                        if (strchr(var, '$')) {
                   1009:                                value = p1 = Var_Subst(NULL, var, VAR_GLOBAL, 0);
                   1010:                        } else {
                   1011:                                value = Var_Value(var, VAR_GLOBAL, &p1);
                   1012:                        }
1.31      christos 1013:                        printf("%s\n", value ? value : "");
                   1014:                        if (p1)
                   1015:                                free(p1);
                   1016:                }
                   1017:        }
                   1018:
1.1       cgd      1019:        /*
                   1020:         * Have now read the entire graph and need to make a list of targets
                   1021:         * to create. If none was given on the command line, we consult the
                   1022:         * parsing module to find the main target(s) to create.
                   1023:         */
                   1024:        if (Lst_IsEmpty(create))
                   1025:                targs = Parse_MainName();
                   1026:        else
                   1027:                targs = Targ_FindList(create, TARG_CREATE);
                   1028:
1.31      christos 1029:        if (!compatMake && !printVars) {
1.1       cgd      1030:                /*
                   1031:                 * Initialize job module before traversing the graph, now that
                   1032:                 * any .BEGIN and .END targets have been read.  This is done
                   1033:                 * only if the -q flag wasn't given (to prevent the .BEGIN from
                   1034:                 * being executed should it exist).
                   1035:                 */
                   1036:                if (!queryFlag) {
                   1037:                        if (maxLocal == -1)
                   1038:                                maxLocal = maxJobs;
                   1039:                        Job_Init(maxJobs, maxLocal);
                   1040:                        jobsRunning = TRUE;
                   1041:                }
                   1042:
                   1043:                /* Traverse the graph, checking on all the targets */
                   1044:                outOfDate = Make_Run(targs);
1.31      christos 1045:        } else if (!printVars) {
1.1       cgd      1046:                /*
                   1047:                 * Compat_Init will take care of creating all the targets as
                   1048:                 * well as initializing the module.
                   1049:                 */
                   1050:                Compat_Run(targs);
1.31      christos 1051:        }
                   1052:
1.49      mycroft  1053: #ifdef CLEANUP
1.14      jtc      1054:        Lst_Destroy(targs, NOFREE);
1.31      christos 1055:        Lst_Destroy(variables, NOFREE);
1.14      jtc      1056:        Lst_Destroy(makefiles, NOFREE);
1.116     christos 1057:        Lst_Destroy(create, (FreeProc *)free);
1.49      mycroft  1058: #endif
1.14      jtc      1059:
1.1       cgd      1060:        /* print the graph now it's been processed if the user requested it */
                   1061:        if (DEBUG(GRAPH2))
                   1062:                Targ_PrintGraph(2);
                   1063:
1.58      sommerfe 1064:        Trace_Log(MAKEEND, 0);
                   1065:
1.14      jtc      1066:        Suff_End();
                   1067:         Targ_End();
                   1068:        Arch_End();
                   1069:        Var_End();
                   1070:        Parse_End();
                   1071:        Dir_End();
1.40      christos 1072:        Job_End();
1.58      sommerfe 1073:        Trace_End();
1.14      jtc      1074:
1.1       cgd      1075:        if (queryFlag && outOfDate)
1.13      cgd      1076:                return(1);
1.1       cgd      1077:        else
1.13      cgd      1078:                return(0);
1.1       cgd      1079: }
                   1080:
                   1081: /*-
                   1082:  * ReadMakefile  --
                   1083:  *     Open and parse the given makefile.
                   1084:  *
                   1085:  * Results:
                   1086:  *     TRUE if ok. FALSE if couldn't open file.
                   1087:  *
                   1088:  * Side Effects:
                   1089:  *     lots
                   1090:  */
                   1091: static Boolean
1.104     jmc      1092: ReadMakefile(ClientData p, ClientData q __unused)
1.1       cgd      1093: {
1.31      christos 1094:        char *fname = p;                /* makefile to read */
1.1       cgd      1095:        FILE *stream;
1.48      christos 1096:        size_t len = MAXPATHLEN;
                   1097:        char *name, *path = emalloc(len);
1.67      sjg      1098:        int setMAKEFILE;
1.1       cgd      1099:
                   1100:        if (!strcmp(fname, "-")) {
                   1101:                Parse_File("(stdin)", stdin);
1.71      sjg      1102:                Var_Set("MAKEFILE", "", VAR_GLOBAL, 0);
1.1       cgd      1103:        } else {
1.67      sjg      1104:                setMAKEFILE = strcmp(fname, ".depend");
                   1105:
1.1       cgd      1106:                /* if we've chdir'd, rebuild the path name */
1.74      tv       1107:                if (strcmp(curdir, objdir) && *fname != '/') {
1.48      christos 1108:                        size_t plen = strlen(curdir) + strlen(fname) + 2;
                   1109:                        if (len < plen)
                   1110:                                path = erealloc(path, len = 2 * plen);
                   1111:
                   1112:                        (void)snprintf(path, len, "%s/%s", curdir, fname);
1.13      cgd      1113:                        if ((stream = fopen(path, "r")) != NULL) {
1.1       cgd      1114:                                fname = path;
                   1115:                                goto found;
                   1116:                        }
1.95      jmc      1117:
                   1118:                        /* If curdir failed, try objdir (ala .depend) */
                   1119:                        plen = strlen(objdir) + strlen(fname) + 2;
                   1120:                        if (len < plen)
                   1121:                                path = erealloc(path, len = 2 * plen);
                   1122:                        (void)snprintf(path, len, "%s/%s", objdir, fname);
                   1123:                        if ((stream = fopen(path, "r")) != NULL) {
                   1124:                                fname = path;
                   1125:                                goto found;
                   1126:                        }
1.62      sjg      1127:                } else if ((stream = fopen(fname, "r")) != NULL)
                   1128:                        goto found;
1.1       cgd      1129:                /* look in -I and system include directories. */
                   1130:                name = Dir_FindFile(fname, parseIncPath);
                   1131:                if (!name)
1.73      tv       1132:                        name = Dir_FindFile(fname,
                   1133:                                Lst_IsEmpty(sysIncPath) ? defIncPath : sysIncPath);
1.48      christos 1134:                if (!name || !(stream = fopen(name, "r"))) {
                   1135:                        free(path);
1.1       cgd      1136:                        return(FALSE);
1.48      christos 1137:                }
1.1       cgd      1138:                fname = name;
                   1139:                /*
                   1140:                 * set the MAKEFILE variable desired by System V fans -- the
                   1141:                 * placement of the setting here means it gets set to the last
                   1142:                 * makefile specified, as it is set by SysV make.
                   1143:                 */
1.67      sjg      1144: found:
                   1145:                if (setMAKEFILE)
1.71      sjg      1146:                        Var_Set("MAKEFILE", fname, VAR_GLOBAL, 0);
1.1       cgd      1147:                Parse_File(fname, stream);
                   1148:                (void)fclose(stream);
                   1149:        }
1.48      christos 1150:        free(path);
1.1       cgd      1151:        return(TRUE);
1.54      sjg      1152: }
                   1153:
                   1154:
                   1155: /*
                   1156:  * If MAKEOBJDIRPREFIX is in use, make ends up not in .CURDIR
                   1157:  * in situations that would not arrise with ./obj (links or not).
                   1158:  * This tends to break things like:
                   1159:  *
                   1160:  * build:
                   1161:  *     ${MAKE} includes
                   1162:  *
                   1163:  * This function spots when ${.MAKE:T} or ${.MAKE} is a command (as
                   1164:  * opposed to an argument) in a command line and if so returns
                   1165:  * ${.CURDIR} so caller can chdir() so that the assumptions made by
                   1166:  * the Makefile hold true.
                   1167:  *
                   1168:  * If ${.MAKE} does not contain any '/', then ${.MAKE:T} is skipped.
                   1169:  *
                   1170:  * The chdir() only happens in the child process, and does nothing if
                   1171:  * MAKEOBJDIRPREFIX and MAKEOBJDIR are not in the environment so it
                   1172:  * should not break anything.  Also if NOCHECKMAKECHDIR is set we
                   1173:  * do nothing - to ensure historic semantics can be retained.
                   1174:  */
                   1175: static int  Check_Cwd_Off = 0;
                   1176:
                   1177: static char *
1.85      wiz      1178: Check_Cwd_av(int ac, char **av, int copy)
1.54      sjg      1179: {
                   1180:     static char *make[4];
1.82      reinoud  1181:     static char *cur_dir = NULL;
1.89      christos 1182:     char **mp;
                   1183:     char *cp;
1.54      sjg      1184:     int is_cmd, next_cmd;
                   1185:     int i;
                   1186:     int n;
                   1187:
                   1188:     if (Check_Cwd_Off)
                   1189:        return NULL;
                   1190:
                   1191:     if (make[0] == NULL) {
                   1192:        if (Var_Exists("NOCHECKMAKECHDIR", VAR_GLOBAL)) {
                   1193:            Check_Cwd_Off = 1;
                   1194:            return NULL;
                   1195:        }
                   1196:
                   1197:         make[1] = Var_Value(".MAKE", VAR_GLOBAL, &cp);
                   1198:         if ((make[0] = strrchr(make[1], '/')) == NULL) {
                   1199:             make[0] = make[1];
                   1200:             make[1] = NULL;
                   1201:         } else
                   1202:             ++make[0];
                   1203:         make[2] = NULL;
1.82      reinoud  1204:         cur_dir = Var_Value(".CURDIR", VAR_GLOBAL, &cp);
1.54      sjg      1205:     }
                   1206:     if (ac == 0 || av == NULL)
                   1207:         return NULL;                   /* initialization only */
                   1208:
                   1209:     if (getenv("MAKEOBJDIR") == NULL &&
                   1210:         getenv("MAKEOBJDIRPREFIX") == NULL)
                   1211:         return NULL;
                   1212:
                   1213:
                   1214:     next_cmd = 1;
                   1215:     for (i = 0; i < ac; ++i) {
                   1216:        is_cmd = next_cmd;
                   1217:
                   1218:        n = strlen(av[i]);
                   1219:        cp = &(av[i])[n - 1];
                   1220:        if (strspn(av[i], "|&;") == n) {
                   1221:            next_cmd = 1;
                   1222:            continue;
                   1223:        } else if (*cp == ';' || *cp == '&' || *cp == '|' || *cp == ')') {
                   1224:            next_cmd = 1;
                   1225:            if (copy) {
                   1226:                do {
                   1227:                    *cp-- = '\0';
                   1228:                } while (*cp == ';' || *cp == '&' || *cp == '|' ||
                   1229:                         *cp == ')' || *cp == '}') ;
                   1230:            } else {
                   1231:                /*
                   1232:                 * XXX this should not happen.
                   1233:                 */
                   1234:                fprintf(stderr, "WARNING: raw arg ends in shell meta '%s'\n",
                   1235:                        av[i]);
                   1236:            }
                   1237:        } else
                   1238:            next_cmd = 0;
                   1239:
                   1240:        cp = av[i];
                   1241:        if (*cp == ';' || *cp == '&' || *cp == '|')
                   1242:            is_cmd = 1;
                   1243:
                   1244: #ifdef check_cwd_debug
                   1245:        fprintf(stderr, "av[%d] == %s '%s'",
                   1246:                i, (is_cmd) ? "cmd" : "arg", av[i]);
                   1247: #endif
                   1248:        if (is_cmd != 0) {
1.57      sjg      1249:            if (*cp == '(' || *cp == '{' ||
                   1250:                *cp == ';' || *cp == '&' || *cp == '|') {
                   1251:                do {
                   1252:                    ++cp;
                   1253:                } while (*cp == '(' || *cp == '{' ||
                   1254:                         *cp == ';' || *cp == '&' || *cp == '|');
                   1255:                if (*cp == '\0') {
                   1256:                    next_cmd = 1;
                   1257:                    continue;
                   1258:                }
                   1259:            }
1.54      sjg      1260:            if (strcmp(cp, "cd") == 0 || strcmp(cp, "chdir") == 0) {
                   1261: #ifdef check_cwd_debug
                   1262:                fprintf(stderr, " == cd, done.\n");
                   1263: #endif
                   1264:                return NULL;
                   1265:            }
                   1266:            for (mp = make; *mp != NULL; ++mp) {
                   1267:                n = strlen(*mp);
                   1268:                if (strcmp(cp, *mp) == 0) {
                   1269: #ifdef check_cwd_debug
                   1270:                    fprintf(stderr, " %s == '%s', chdir(%s)\n",
1.82      reinoud  1271:                            cp, *mp, cur_dir);
1.54      sjg      1272: #endif
1.82      reinoud  1273:                    return cur_dir;
1.54      sjg      1274:                }
                   1275:            }
                   1276:        }
                   1277: #ifdef check_cwd_debug
                   1278:        fprintf(stderr, "\n");
                   1279: #endif
                   1280:     }
                   1281:     return NULL;
                   1282: }
                   1283:
                   1284: char *
1.89      christos 1285: Check_Cwd_Cmd(const char *cmd)
1.54      sjg      1286: {
1.89      christos 1287:     char *cp, *bp;
                   1288:     char **av;
1.54      sjg      1289:     int ac;
                   1290:
                   1291:     if (Check_Cwd_Off)
                   1292:        return NULL;
                   1293:
                   1294:     if (cmd) {
                   1295:        av = brk_string(cmd, &ac, TRUE, &bp);
                   1296: #ifdef check_cwd_debug
                   1297:        fprintf(stderr, "splitting: '%s' -> %d words\n",
                   1298:                cmd, ac);
                   1299: #endif
                   1300:     } else {
                   1301:        ac = 0;
                   1302:        av = NULL;
                   1303:        bp = NULL;
                   1304:     }
                   1305:     cp = Check_Cwd_av(ac, av, 1);
                   1306:     if (bp) {
                   1307:        free(av);
                   1308:        free(bp);
                   1309:     }
                   1310:     return cp;
                   1311: }
                   1312:
                   1313: void
1.89      christos 1314: Check_Cwd(const char **argv)
1.54      sjg      1315: {
                   1316:     char *cp;
                   1317:     int ac;
                   1318:
                   1319:     if (Check_Cwd_Off)
                   1320:        return;
                   1321:
                   1322:     for (ac = 0; argv[ac] != NULL; ++ac)
                   1323:        /* NOTHING */;
                   1324:     if (ac == 3 && *argv[1] == '-') {
                   1325:        cp =  Check_Cwd_Cmd(argv[2]);
                   1326:     } else {
1.89      christos 1327:        cp = Check_Cwd_av(ac, UNCONST(argv), 0);
1.54      sjg      1328:     }
                   1329:     if (cp) {
                   1330:        chdir(cp);
                   1331:     }
1.29      christos 1332: }
                   1333:
                   1334: /*-
                   1335:  * Cmd_Exec --
                   1336:  *     Execute the command in cmd, and return the output of that command
                   1337:  *     in a string.
                   1338:  *
                   1339:  * Results:
                   1340:  *     A string containing the output of the command, or the empty string
                   1341:  *     If err is not NULL, it contains the reason for the command failure
                   1342:  *
                   1343:  * Side Effects:
                   1344:  *     The string must be freed by the caller.
                   1345:  */
                   1346: char *
1.89      christos 1347: Cmd_Exec(const char *cmd, const char **err)
1.29      christos 1348: {
1.89      christos 1349:     const char *args[4];       /* Args for invoking the shell */
1.29      christos 1350:     int        fds[2];         /* Pipe streams */
                   1351:     int        cpid;           /* Child PID */
                   1352:     int        pid;            /* PID from wait() */
                   1353:     char       *res;           /* result */
                   1354:     int                status;         /* command exit status */
                   1355:     Buffer     buf;            /* buffer to store the result */
                   1356:     char       *cp;
                   1357:     int                cc;
                   1358:
                   1359:
                   1360:     *err = NULL;
                   1361:
1.90      sjg      1362:     if (!shellName)
                   1363:        Shell_Init();
1.29      christos 1364:     /*
                   1365:      * Set up arguments for shell
                   1366:      */
1.90      sjg      1367:     args[0] = shellName;
1.29      christos 1368:     args[1] = "-c";
                   1369:     args[2] = cmd;
                   1370:     args[3] = NULL;
                   1371:
                   1372:     /*
                   1373:      * Open a pipe for fetching its output
                   1374:      */
                   1375:     if (pipe(fds) == -1) {
                   1376:        *err = "Couldn't create pipe for \"%s\"";
                   1377:        goto bad;
                   1378:     }
                   1379:
                   1380:     /*
                   1381:      * Fork
                   1382:      */
                   1383:     switch (cpid = vfork()) {
                   1384:     case 0:
                   1385:        /*
                   1386:         * Close input side of pipe
                   1387:         */
1.112     christos 1388:        (void)close(fds[0]);
1.29      christos 1389:
                   1390:        /*
                   1391:         * Duplicate the output stream to the shell's output, then
                   1392:         * shut the extra thing down. Note we don't fetch the error
                   1393:         * stream...why not? Why?
                   1394:         */
1.112     christos 1395:        (void)dup2(fds[1], 1);
                   1396:        (void)close(fds[1]);
1.31      christos 1397:
1.112     christos 1398:        (void)execv(shellPath, UNCONST(args));
1.29      christos 1399:        _exit(1);
                   1400:        /*NOTREACHED*/
                   1401:
                   1402:     case -1:
                   1403:        *err = "Couldn't exec \"%s\"";
                   1404:        goto bad;
                   1405:
                   1406:     default:
                   1407:        /*
                   1408:         * No need for the writing half
                   1409:         */
1.112     christos 1410:        (void)close(fds[1]);
1.31      christos 1411:
1.106     christos 1412:        buf = Buf_Init(MAKE_BSIZE);
1.29      christos 1413:
                   1414:        do {
                   1415:            char   result[BUFSIZ];
                   1416:            cc = read(fds[0], result, sizeof(result));
1.31      christos 1417:            if (cc > 0)
1.115     christos 1418:                Buf_AddBytes(buf, cc, (Byte *)result);
1.29      christos 1419:        }
                   1420:        while (cc > 0 || (cc == -1 && errno == EINTR));
                   1421:
                   1422:        /*
                   1423:         * Close the input side of the pipe.
                   1424:         */
1.112     christos 1425:        (void)close(fds[0]);
1.29      christos 1426:
                   1427:        /*
                   1428:         * Wait for the process to exit.
                   1429:         */
                   1430:        while(((pid = wait(&status)) != cpid) && (pid >= 0))
                   1431:            continue;
                   1432:
1.112     christos 1433:        res = (char *)Buf_GetAll(buf, &cc);
1.106     christos 1434:        Buf_Destroy(buf, FALSE);
1.29      christos 1435:
1.31      christos 1436:        if (cc == 0)
1.29      christos 1437:            *err = "Couldn't read shell's output for \"%s\"";
                   1438:
                   1439:        if (status)
                   1440:            *err = "\"%s\" returned non-zero status";
                   1441:
                   1442:        /*
                   1443:         * Null-terminate the result, convert newlines to spaces and
                   1444:         * install it in the variable.
                   1445:         */
                   1446:        res[cc] = '\0';
1.44      itohy    1447:        cp = &res[cc];
1.29      christos 1448:
1.44      itohy    1449:        if (cc > 0 && *--cp == '\n') {
1.29      christos 1450:            /*
                   1451:             * A final newline is just stripped
                   1452:             */
                   1453:            *cp-- = '\0';
                   1454:        }
                   1455:        while (cp >= res) {
                   1456:            if (*cp == '\n') {
                   1457:                *cp = ' ';
                   1458:            }
                   1459:            cp--;
                   1460:        }
                   1461:        break;
                   1462:     }
                   1463:     return res;
                   1464: bad:
                   1465:     res = emalloc(1);
                   1466:     *res = '\0';
                   1467:     return res;
1.1       cgd      1468: }
                   1469:
                   1470: /*-
                   1471:  * Error --
                   1472:  *     Print an error message given its format.
                   1473:  *
                   1474:  * Results:
                   1475:  *     None.
                   1476:  *
                   1477:  * Side Effects:
                   1478:  *     The message is printed.
                   1479:  */
                   1480: /* VARARGS */
                   1481: void
1.89      christos 1482: Error(const char *fmt, ...)
1.1       cgd      1483: {
                   1484:        va_list ap;
1.85      wiz      1485:
1.13      cgd      1486:        va_start(ap, fmt);
1.53      christos 1487:        fprintf(stderr, "%s: ", progname);
1.1       cgd      1488:        (void)vfprintf(stderr, fmt, ap);
                   1489:        va_end(ap);
                   1490:        (void)fprintf(stderr, "\n");
                   1491:        (void)fflush(stderr);
                   1492: }
                   1493:
                   1494: /*-
                   1495:  * Fatal --
                   1496:  *     Produce a Fatal error message. If jobs are running, waits for them
                   1497:  *     to finish.
                   1498:  *
                   1499:  * Results:
                   1500:  *     None
                   1501:  *
                   1502:  * Side Effects:
                   1503:  *     The program exits
                   1504:  */
                   1505: /* VARARGS */
                   1506: void
1.89      christos 1507: Fatal(const char *fmt, ...)
1.1       cgd      1508: {
                   1509:        va_list ap;
1.85      wiz      1510:
1.13      cgd      1511:        va_start(ap, fmt);
1.1       cgd      1512:        if (jobsRunning)
                   1513:                Job_Wait();
                   1514:
                   1515:        (void)vfprintf(stderr, fmt, ap);
                   1516:        va_end(ap);
                   1517:        (void)fprintf(stderr, "\n");
                   1518:        (void)fflush(stderr);
                   1519:
1.67      sjg      1520:        PrintOnError(NULL);
                   1521:
1.94      dsl      1522:        if (DEBUG(GRAPH2) || DEBUG(GRAPH3))
1.1       cgd      1523:                Targ_PrintGraph(2);
1.58      sommerfe 1524:        Trace_Log(MAKEERROR, 0);
1.1       cgd      1525:        exit(2);                /* Not 1 so -q can distinguish error */
                   1526: }
                   1527:
                   1528: /*
                   1529:  * Punt --
                   1530:  *     Major exception once jobs are being created. Kills all jobs, prints
                   1531:  *     a message and exits.
                   1532:  *
                   1533:  * Results:
1.31      christos 1534:  *     None
1.1       cgd      1535:  *
                   1536:  * Side Effects:
                   1537:  *     All children are killed indiscriminately and the program Lib_Exits
                   1538:  */
                   1539: /* VARARGS */
                   1540: void
1.89      christos 1541: Punt(const char *fmt, ...)
1.1       cgd      1542: {
                   1543:        va_list ap;
1.85      wiz      1544:
1.13      cgd      1545:        va_start(ap, fmt);
1.63      christos 1546:        (void)fprintf(stderr, "%s: ", progname);
1.1       cgd      1547:        (void)vfprintf(stderr, fmt, ap);
                   1548:        va_end(ap);
                   1549:        (void)fprintf(stderr, "\n");
                   1550:        (void)fflush(stderr);
                   1551:
1.67      sjg      1552:        PrintOnError(NULL);
                   1553:
1.1       cgd      1554:        DieHorribly();
                   1555: }
                   1556:
                   1557: /*-
                   1558:  * DieHorribly --
                   1559:  *     Exit without giving a message.
                   1560:  *
                   1561:  * Results:
                   1562:  *     None
                   1563:  *
                   1564:  * Side Effects:
                   1565:  *     A big one...
                   1566:  */
                   1567: void
1.85      wiz      1568: DieHorribly(void)
1.1       cgd      1569: {
                   1570:        if (jobsRunning)
                   1571:                Job_AbortAll();
                   1572:        if (DEBUG(GRAPH2))
                   1573:                Targ_PrintGraph(2);
1.58      sommerfe 1574:        Trace_Log(MAKEERROR, 0);
1.1       cgd      1575:        exit(2);                /* Not 1, so -q can distinguish error */
                   1576: }
                   1577:
                   1578: /*
                   1579:  * Finish --
                   1580:  *     Called when aborting due to errors in child shell to signal
1.31      christos 1581:  *     abnormal exit.
1.1       cgd      1582:  *
                   1583:  * Results:
1.31      christos 1584:  *     None
1.1       cgd      1585:  *
                   1586:  * Side Effects:
                   1587:  *     The program exits
                   1588:  */
                   1589: void
1.85      wiz      1590: Finish(int errors)
                   1591:                        /* number of errors encountered in Make_Make */
1.1       cgd      1592: {
                   1593:        Fatal("%d error%s", errors, errors == 1 ? "" : "s");
                   1594: }
                   1595:
                   1596: /*
                   1597:  * emalloc --
                   1598:  *     malloc, but die on error.
                   1599:  */
1.28      christos 1600: void *
1.85      wiz      1601: emalloc(size_t len)
1.1       cgd      1602: {
1.28      christos 1603:        void *p;
1.1       cgd      1604:
1.28      christos 1605:        if ((p = malloc(len)) == NULL)
1.30      christos 1606:                enomem();
                   1607:        return(p);
                   1608: }
                   1609:
                   1610: /*
1.31      christos 1611:  * estrdup --
1.30      christos 1612:  *     strdup, but die on error.
                   1613:  */
                   1614: char *
1.85      wiz      1615: estrdup(const char *str)
1.30      christos 1616: {
                   1617:        char *p;
                   1618:
                   1619:        if ((p = strdup(str)) == NULL)
1.27      jtc      1620:                enomem();
                   1621:        return(p);
                   1622: }
                   1623:
                   1624: /*
                   1625:  * erealloc --
                   1626:  *     realloc, but die on error.
                   1627:  */
1.28      christos 1628: void *
1.85      wiz      1629: erealloc(void *ptr, size_t size)
1.27      jtc      1630: {
1.28      christos 1631:        if ((ptr = realloc(ptr, size)) == NULL)
1.1       cgd      1632:                enomem();
1.28      christos 1633:        return(ptr);
1.1       cgd      1634: }
                   1635:
                   1636: /*
                   1637:  * enomem --
                   1638:  *     die when out of memory.
                   1639:  */
1.13      cgd      1640: void
1.85      wiz      1641: enomem(void)
1.1       cgd      1642: {
1.63      christos 1643:        (void)fprintf(stderr, "%s: %s.\n", progname, strerror(errno));
1.1       cgd      1644:        exit(2);
1.21      christos 1645: }
                   1646:
                   1647: /*
                   1648:  * enunlink --
                   1649:  *     Remove a file carefully, avoiding directories.
                   1650:  */
                   1651: int
1.85      wiz      1652: eunlink(const char *file)
1.21      christos 1653: {
                   1654:        struct stat st;
                   1655:
                   1656:        if (lstat(file, &st) == -1)
                   1657:                return -1;
                   1658:
                   1659:        if (S_ISDIR(st.st_mode)) {
                   1660:                errno = EISDIR;
                   1661:                return -1;
                   1662:        }
                   1663:        return unlink(file);
1.1       cgd      1664: }
                   1665:
                   1666: /*
1.66      christos 1667:  * execError --
                   1668:  *     Print why exec failed, avoiding stdio.
                   1669:  */
                   1670: void
1.85      wiz      1671: execError(const char *af, const char *av)
1.66      christos 1672: {
                   1673: #ifdef USE_IOVEC
                   1674:        int i = 0;
1.83      pk       1675:        struct iovec iov[8];
1.66      christos 1676: #define IOADD(s) \
1.89      christos 1677:        (void)(iov[i].iov_base = UNCONST(s), \
1.66      christos 1678:            iov[i].iov_len = strlen(iov[i].iov_base), \
                   1679:            i++)
                   1680: #else
1.112     christos 1681: #define        IOADD(void)write(2, s, strlen(s))
1.66      christos 1682: #endif
                   1683:
                   1684:        IOADD(progname);
1.83      pk       1685:        IOADD(": ");
1.89      christos 1686:        IOADD(af);
1.83      pk       1687:        IOADD("(");
1.89      christos 1688:        IOADD(av);
1.83      pk       1689:        IOADD(") failed (");
1.66      christos 1690:        IOADD(strerror(errno));
                   1691:        IOADD(")\n");
                   1692:
                   1693: #ifdef USE_IOVEC
1.83      pk       1694:        (void)writev(2, iov, 8);
1.66      christos 1695: #endif
                   1696: }
                   1697:
                   1698: /*
1.1       cgd      1699:  * usage --
                   1700:  *     exit with usage message
                   1701:  */
1.13      cgd      1702: static void
1.85      wiz      1703: usage(void)
1.1       cgd      1704: {
                   1705:        (void)fprintf(stderr,
1.105     wiz      1706: "usage: %s [-BeikNnqrstWX] [-D variable] [-d flags] [-f makefile]\n\
                   1707:             [-I directory] [-J private] [-j max_jobs] [-m directory] [-T file]\n\
                   1708:             [-V variable] [variable=value] [target ...]\n", progname);
1.1       cgd      1709:        exit(2);
1.14      jtc      1710: }
                   1711:
                   1712:
                   1713: int
1.85      wiz      1714: PrintAddr(ClientData a, ClientData b)
1.14      jtc      1715: {
                   1716:     printf("%lx ", (unsigned long) a);
                   1717:     return b ? 0 : 0;
1.67      sjg      1718: }
                   1719:
                   1720:
                   1721:
                   1722: void
1.89      christos 1723: PrintOnError(const char *s)
1.67      sjg      1724: {
                   1725:     char tmp[64];
                   1726:
                   1727:     if (s)
                   1728:            printf("%s", s);
                   1729:
                   1730:     printf("\n%s: stopped in %s\n", progname, curdir);
                   1731:     strncpy(tmp, "${MAKE_PRINT_VAR_ON_ERROR:@v@$v='${$v}'\n@}",
                   1732:            sizeof(tmp) - 1);
                   1733:     s = Var_Subst(NULL, tmp, VAR_GLOBAL, 0);
                   1734:     if (s && *s)
                   1735:        printf("%s", s);
1.68      sjg      1736: }
                   1737:
                   1738: void
1.85      wiz      1739: Main_ExportMAKEFLAGS(Boolean first)
1.68      sjg      1740: {
                   1741:     static int once = 1;
                   1742:     char tmp[64];
                   1743:     char *s;
                   1744:
                   1745:     if (once != first)
                   1746:        return;
                   1747:     once = 0;
                   1748:
1.70      sjg      1749:     strncpy(tmp, "${.MAKEFLAGS} ${.MAKEOVERRIDES:O:u:@v@$v=${$v:Q}@}",
                   1750:            sizeof(tmp));
                   1751:     s = Var_Subst(NULL, tmp, VAR_CMD, 0);
1.68      sjg      1752:     if (s && *s) {
                   1753: #ifdef POSIX
                   1754:        setenv("MAKEFLAGS", s, 1);
                   1755: #else
                   1756:        setenv("MAKE", s, 1);
                   1757: #endif
                   1758:     }
1.1       cgd      1759: }

CVSweb <webmaster@jp.NetBSD.org>