~ubuntu-branches/ubuntu/trusty/bmake/trusty-proposed

« back to all changes in this revision

Viewing changes to main.c

  • Committer: Package Import Robot
  • Author(s): Andrew Shadura
  • Date: 2013-09-22 16:07:33 UTC
  • Revision ID: package-import@ubuntu.com-20130922160733-9cvmsi7z0jswtrbi
Tags: upstream-20130904
ImportĀ upstreamĀ versionĀ 20130904

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*      $NetBSD: main.c,v 1.224 2013/09/04 15:38:26 sjg Exp $   */
 
2
 
 
3
/*
 
4
 * Copyright (c) 1988, 1989, 1990, 1993
 
5
 *      The Regents of the University of California.  All rights reserved.
 
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
/*
 
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
 
 
71
#ifndef MAKE_NATIVE
 
72
static char rcsid[] = "$NetBSD: main.c,v 1.224 2013/09/04 15:38:26 sjg Exp $";
 
73
#else
 
74
#include <sys/cdefs.h>
 
75
#ifndef lint
 
76
__COPYRIGHT("@(#) Copyright (c) 1988, 1989, 1990, 1993\
 
77
 The Regents of the University of California.  All rights reserved.");
 
78
#endif /* not lint */
 
79
 
 
80
#ifndef lint
 
81
#if 0
 
82
static char sccsid[] = "@(#)main.c      8.3 (Berkeley) 3/19/94";
 
83
#else
 
84
__RCSID("$NetBSD: main.c,v 1.224 2013/09/04 15:38:26 sjg Exp $");
 
85
#endif
 
86
#endif /* not lint */
 
87
#endif
 
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
 
112
 *                              errors which occurred, as passed to it, and
 
113
 *                              exiting.
 
114
 */
 
115
 
 
116
#include <sys/types.h>
 
117
#include <sys/time.h>
 
118
#include <sys/param.h>
 
119
#include <sys/resource.h>
 
120
#include <sys/stat.h>
 
121
#include <sys/utsname.h>
 
122
#include "wait.h"
 
123
 
 
124
#include <errno.h>
 
125
#include <fcntl.h>
 
126
#include <signal.h>
 
127
#include <stdarg.h>
 
128
#include <stdio.h>
 
129
#include <stdlib.h>
 
130
#include <time.h>
 
131
#include <ctype.h>
 
132
 
 
133
#include "make.h"
 
134
#include "hash.h"
 
135
#include "dir.h"
 
136
#include "job.h"
 
137
#include "pathnames.h"
 
138
#include "trace.h"
 
139
 
 
140
#ifdef USE_IOVEC
 
141
#include <sys/uio.h>
 
142
#endif
 
143
 
 
144
#ifndef DEFMAXLOCAL
 
145
#define DEFMAXLOCAL DEFMAXJOBS
 
146
#endif  /* DEFMAXLOCAL */
 
147
 
 
148
Lst                     create;         /* Targets to be made */
 
149
time_t                  now;            /* Time at start of make */
 
150
GNode                   *DEFAULT;       /* .DEFAULT node */
 
151
Boolean                 allPrecious;    /* .PRECIOUS given on line by itself */
 
152
 
 
153
static Boolean          noBuiltins;     /* -r flag */
 
154
static Lst              makefiles;      /* ordered list of makefiles to read */
 
155
static Boolean          printVars;      /* print value of one or more vars */
 
156
static Lst              variables;      /* list of variables to print */
 
157
int                     maxJobs;        /* -j argument */
 
158
static int              maxJobTokens;   /* -j argument */
 
159
Boolean                 compatMake;     /* -B argument */
 
160
int                     debug;          /* -d argument */
 
161
Boolean                 debugVflag;     /* -dV */
 
162
Boolean                 noExecute;      /* -n flag */
 
163
Boolean                 noRecursiveExecute;     /* -N flag */
 
164
Boolean                 keepgoing;      /* -k flag */
 
165
Boolean                 queryFlag;      /* -q flag */
 
166
Boolean                 touchFlag;      /* -t flag */
 
167
Boolean                 enterFlag;      /* -w flag */
 
168
Boolean                 ignoreErrors;   /* -i flag */
 
169
Boolean                 beSilent;       /* -s flag */
 
170
Boolean                 oldVars;        /* variable substitution style */
 
171
Boolean                 checkEnvFirst;  /* -e flag */
 
172
Boolean                 parseWarnFatal; /* -W flag */
 
173
Boolean                 jobServer;      /* -J flag */
 
174
static int jp_0 = -1, jp_1 = -1;        /* ends of parent job pipe */
 
175
Boolean                 varNoExportEnv; /* -X flag */
 
176
Boolean                 doing_depend;   /* Set while reading .depend */
 
177
static Boolean          jobsRunning;    /* TRUE if the jobs might be running */
 
178
static const char *     tracefile;
 
179
static void             MainParseArgs(int, char **);
 
180
static int              ReadMakefile(const void *, const void *);
 
181
static void             usage(void) MAKE_ATTR_DEAD;
 
182
 
 
183
static Boolean          ignorePWD;      /* if we use -C, PWD is meaningless */
 
184
static char objdir[MAXPATHLEN + 1];     /* where we chdir'ed to */
 
185
char curdir[MAXPATHLEN + 1];            /* Startup directory */
 
186
char *progname;                         /* the program name */
 
187
char *makeDependfile;
 
188
pid_t myPid;
 
189
int makelevel;
 
190
 
 
191
Boolean forceJobs = FALSE;
 
192
 
 
193
/*
 
194
 * On some systems MACHINE is defined as something other than
 
195
 * what we want.
 
196
 */
 
197
#ifdef FORCE_MACHINE
 
198
# undef MACHINE
 
199
# define MACHINE FORCE_MACHINE
 
200
#endif
 
201
 
 
202
extern Lst parseIncPath;
 
203
 
 
204
/*
 
205
 * For compatibility with the POSIX version of MAKEFLAGS that includes
 
206
 * all the options with out -, convert flags to -f -l -a -g -s.
 
207
 */
 
208
static char *
 
209
explode(const char *flags)
 
210
{
 
211
    size_t len;
 
212
    char *nf, *st;
 
213
    const char *f;
 
214
 
 
215
    if (flags == NULL)
 
216
        return NULL;
 
217
 
 
218
    for (f = flags; *f; f++)
 
219
        if (!isalpha((unsigned char)*f))
 
220
            break;
 
221
 
 
222
    if (*f)
 
223
        return bmake_strdup(flags);
 
224
 
 
225
    len = strlen(flags);
 
226
    st = nf = bmake_malloc(len * 3 + 1);
 
227
    while (*flags) {
 
228
        *nf++ = '-';
 
229
        *nf++ = *flags++;
 
230
        *nf++ = ' ';
 
231
    }
 
232
    *nf = '\0';
 
233
    return st;
 
234
}
 
235
            
 
236
static void
 
237
parse_debug_options(const char *argvalue)
 
238
{
 
239
        const char *modules;
 
240
        const char *mode;
 
241
        char *fname;
 
242
        int len;
 
243
 
 
244
        for (modules = argvalue; *modules; ++modules) {
 
245
                switch (*modules) {
 
246
                case 'A':
 
247
                        debug = ~0;
 
248
                        break;
 
249
                case 'a':
 
250
                        debug |= DEBUG_ARCH;
 
251
                        break;
 
252
                case 'C':
 
253
                        debug |= DEBUG_CWD;
 
254
                        break;
 
255
                case 'c':
 
256
                        debug |= DEBUG_COND;
 
257
                        break;
 
258
                case 'd':
 
259
                        debug |= DEBUG_DIR;
 
260
                        break;
 
261
                case 'e':
 
262
                        debug |= DEBUG_ERROR;
 
263
                        break;
 
264
                case 'f':
 
265
                        debug |= DEBUG_FOR;
 
266
                        break;
 
267
                case 'g':
 
268
                        if (modules[1] == '1') {
 
269
                                debug |= DEBUG_GRAPH1;
 
270
                                ++modules;
 
271
                        }
 
272
                        else if (modules[1] == '2') {
 
273
                                debug |= DEBUG_GRAPH2;
 
274
                                ++modules;
 
275
                        }
 
276
                        else if (modules[1] == '3') {
 
277
                                debug |= DEBUG_GRAPH3;
 
278
                                ++modules;
 
279
                        }
 
280
                        break;
 
281
                case 'j':
 
282
                        debug |= DEBUG_JOB;
 
283
                        break;
 
284
                case 'l':
 
285
                        debug |= DEBUG_LOUD;
 
286
                        break;
 
287
                case 'M':
 
288
                        debug |= DEBUG_META;
 
289
                        break;
 
290
                case 'm':
 
291
                        debug |= DEBUG_MAKE;
 
292
                        break;
 
293
                case 'n':
 
294
                        debug |= DEBUG_SCRIPT;
 
295
                        break;
 
296
                case 'p':
 
297
                        debug |= DEBUG_PARSE;
 
298
                        break;
 
299
                case 's':
 
300
                        debug |= DEBUG_SUFF;
 
301
                        break;
 
302
                case 't':
 
303
                        debug |= DEBUG_TARG;
 
304
                        break;
 
305
                case 'V':
 
306
                        debugVflag = TRUE;
 
307
                        break;
 
308
                case 'v':
 
309
                        debug |= DEBUG_VAR;
 
310
                        break;
 
311
                case 'x':
 
312
                        debug |= DEBUG_SHELL;
 
313
                        break;
 
314
                case 'F':
 
315
                        if (debug_file != stdout && debug_file != stderr)
 
316
                                fclose(debug_file);
 
317
                        if (*++modules == '+') {
 
318
                                modules++;
 
319
                                mode = "a";
 
320
                        } else
 
321
                                mode = "w";
 
322
                        if (strcmp(modules, "stdout") == 0) {
 
323
                                debug_file = stdout;
 
324
                                goto debug_setbuf;
 
325
                        }
 
326
                        if (strcmp(modules, "stderr") == 0) {
 
327
                                debug_file = stderr;
 
328
                                goto debug_setbuf;
 
329
                        }
 
330
                        len = strlen(modules);
 
331
                        fname = malloc(len + 20);
 
332
                        memcpy(fname, modules, len + 1);
 
333
                        /* Let the filename be modified by the pid */
 
334
                        if (strcmp(fname + len - 3, ".%d") == 0)
 
335
                                snprintf(fname + len - 2, 20, "%d", getpid());
 
336
                        debug_file = fopen(fname, mode);
 
337
                        if (!debug_file) {
 
338
                                fprintf(stderr, "Cannot open debug file %s\n",
 
339
                                    fname);
 
340
                                usage();
 
341
                        }
 
342
                        free(fname);
 
343
                        goto debug_setbuf;
 
344
                default:
 
345
                        (void)fprintf(stderr,
 
346
                            "%s: illegal argument to d option -- %c\n",
 
347
                            progname, *modules);
 
348
                        usage();
 
349
                }
 
350
        }
 
351
debug_setbuf:
 
352
        /*
 
353
         * Make the debug_file unbuffered, and make
 
354
         * stdout line buffered (unless debugfile == stdout).
 
355
         */
 
356
        setvbuf(debug_file, NULL, _IONBF, 0);
 
357
        if (debug_file != stdout) {
 
358
                setvbuf(stdout, NULL, _IOLBF, 0);
 
359
        }
 
360
}
 
361
 
 
362
/*-
 
363
 * MainParseArgs --
 
364
 *      Parse a given argument vector. Called from main() and from
 
365
 *      Main_ParseArgLine() when the .MAKEFLAGS target is used.
 
366
 *
 
367
 *      XXX: Deal with command line overriding .MAKEFLAGS in makefile
 
368
 *
 
369
 * Results:
 
370
 *      None
 
371
 *
 
372
 * Side Effects:
 
373
 *      Various global and local flags will be set depending on the flags
 
374
 *      given
 
375
 */
 
376
static void
 
377
MainParseArgs(int argc, char **argv)
 
378
{
 
379
        char *p;
 
380
        int c = '?';
 
381
        int arginc;
 
382
        char *argvalue;
 
383
        const char *getopt_def;
 
384
        char *optscan;
 
385
        Boolean inOption, dashDash = FALSE;
 
386
        char found_path[MAXPATHLEN + 1];        /* for searching for sys.mk */
 
387
 
 
388
#define OPTFLAGS "BC:D:I:J:NST:V:WXd:ef:ij:km:nqrstw"
 
389
/* Can't actually use getopt(3) because rescanning is not portable */
 
390
 
 
391
        getopt_def = OPTFLAGS;
 
392
rearg:  
 
393
        inOption = FALSE;
 
394
        optscan = NULL;
 
395
        while(argc > 1) {
 
396
                char *getopt_spec;
 
397
                if(!inOption)
 
398
                        optscan = argv[1];
 
399
                c = *optscan++;
 
400
                arginc = 0;
 
401
                if(inOption) {
 
402
                        if(c == '\0') {
 
403
                                ++argv;
 
404
                                --argc;
 
405
                                inOption = FALSE;
 
406
                                continue;
 
407
                        }
 
408
                } else {
 
409
                        if (c != '-' || dashDash)
 
410
                                break;
 
411
                        inOption = TRUE;
 
412
                        c = *optscan++;
 
413
                }
 
414
                /* '-' found at some earlier point */
 
415
                getopt_spec = strchr(getopt_def, c);
 
416
                if(c != '\0' && getopt_spec != NULL && getopt_spec[1] == ':') {
 
417
                        /* -<something> found, and <something> should have an arg */
 
418
                        inOption = FALSE;
 
419
                        arginc = 1;
 
420
                        argvalue = optscan;
 
421
                        if(*argvalue == '\0') {
 
422
                                if (argc < 3)
 
423
                                        goto noarg;
 
424
                                argvalue = argv[2];
 
425
                                arginc = 2;
 
426
                        }
 
427
                } else {
 
428
                        argvalue = NULL; 
 
429
                }
 
430
                switch(c) {
 
431
                case '\0':
 
432
                        arginc = 1;
 
433
                        inOption = FALSE;
 
434
                        break;
 
435
                case 'B':
 
436
                        compatMake = TRUE;
 
437
                        Var_Append(MAKEFLAGS, "-B", VAR_GLOBAL);
 
438
                        Var_Set(MAKE_MODE, "compat", VAR_GLOBAL, 0);
 
439
                        break;
 
440
                case 'C':
 
441
                        if (chdir(argvalue) == -1) {
 
442
                                (void)fprintf(stderr,
 
443
                                              "%s: chdir %s: %s\n",
 
444
                                              progname, argvalue,
 
445
                                              strerror(errno));
 
446
                                exit(1);
 
447
                        }
 
448
                        if (getcwd(curdir, MAXPATHLEN) == NULL) {
 
449
                                (void)fprintf(stderr, "%s: %s.\n", progname, strerror(errno));
 
450
                                exit(2);
 
451
                        }
 
452
                        ignorePWD = TRUE;
 
453
                        break;
 
454
                case 'D':
 
455
                        if (argvalue == NULL || argvalue[0] == 0) goto noarg;
 
456
                        Var_Set(argvalue, "1", VAR_GLOBAL, 0);
 
457
                        Var_Append(MAKEFLAGS, "-D", VAR_GLOBAL);
 
458
                        Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL);
 
459
                        break;
 
460
                case 'I':
 
461
                        if (argvalue == NULL) goto noarg;
 
462
                        Parse_AddIncludeDir(argvalue);
 
463
                        Var_Append(MAKEFLAGS, "-I", VAR_GLOBAL);
 
464
                        Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL);
 
465
                        break;
 
466
                case 'J':
 
467
                        if (argvalue == NULL) goto noarg;
 
468
                        if (sscanf(argvalue, "%d,%d", &jp_0, &jp_1) != 2) {
 
469
                            (void)fprintf(stderr,
 
470
                                "%s: internal error -- J option malformed (%s)\n",
 
471
                                progname, argvalue);
 
472
                                usage();
 
473
                        }
 
474
                        if ((fcntl(jp_0, F_GETFD, 0) < 0) ||
 
475
                            (fcntl(jp_1, F_GETFD, 0) < 0)) {
 
476
#if 0
 
477
                            (void)fprintf(stderr,
 
478
                                "%s: ###### warning -- J descriptors were closed!\n",
 
479
                                progname);
 
480
                            exit(2);
 
481
#endif
 
482
                            jp_0 = -1;
 
483
                            jp_1 = -1;
 
484
                            compatMake = TRUE;
 
485
                        } else {
 
486
                            Var_Append(MAKEFLAGS, "-J", VAR_GLOBAL);
 
487
                            Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL);
 
488
                            jobServer = TRUE;
 
489
                        }
 
490
                        break;
 
491
                case 'N':
 
492
                        noExecute = TRUE;
 
493
                        noRecursiveExecute = TRUE;
 
494
                        Var_Append(MAKEFLAGS, "-N", VAR_GLOBAL);
 
495
                        break;
 
496
                case 'S':
 
497
                        keepgoing = FALSE;
 
498
                        Var_Append(MAKEFLAGS, "-S", VAR_GLOBAL);
 
499
                        break;
 
500
                case 'T':
 
501
                        if (argvalue == NULL) goto noarg;
 
502
                        tracefile = bmake_strdup(argvalue);
 
503
                        Var_Append(MAKEFLAGS, "-T", VAR_GLOBAL);
 
504
                        Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL);
 
505
                        break;
 
506
                case 'V':
 
507
                        if (argvalue == NULL) goto noarg;
 
508
                        printVars = TRUE;
 
509
                        (void)Lst_AtEnd(variables, argvalue);
 
510
                        Var_Append(MAKEFLAGS, "-V", VAR_GLOBAL);
 
511
                        Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL);
 
512
                        break;
 
513
                case 'W':
 
514
                        parseWarnFatal = TRUE;
 
515
                        break;
 
516
                case 'X':
 
517
                        varNoExportEnv = TRUE;
 
518
                        Var_Append(MAKEFLAGS, "-X", VAR_GLOBAL);
 
519
                        break;
 
520
                case 'd':
 
521
                        if (argvalue == NULL) goto noarg;
 
522
                        /* If '-d-opts' don't pass to children */
 
523
                        if (argvalue[0] == '-')
 
524
                            argvalue++;
 
525
                        else {
 
526
                            Var_Append(MAKEFLAGS, "-d", VAR_GLOBAL);
 
527
                            Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL);
 
528
                        }
 
529
                        parse_debug_options(argvalue);
 
530
                        break;
 
531
                case 'e':
 
532
                        checkEnvFirst = TRUE;
 
533
                        Var_Append(MAKEFLAGS, "-e", VAR_GLOBAL);
 
534
                        break;
 
535
                case 'f':
 
536
                        if (argvalue == NULL) goto noarg;
 
537
                        (void)Lst_AtEnd(makefiles, argvalue);
 
538
                        break;
 
539
                case 'i':
 
540
                        ignoreErrors = TRUE;
 
541
                        Var_Append(MAKEFLAGS, "-i", VAR_GLOBAL);
 
542
                        break;
 
543
                case 'j':
 
544
                        if (argvalue == NULL) goto noarg;
 
545
                        forceJobs = TRUE;
 
546
                        maxJobs = strtol(argvalue, &p, 0);
 
547
                        if (*p != '\0' || maxJobs < 1) {
 
548
                                (void)fprintf(stderr, "%s: illegal argument to -j -- must be positive integer!\n",
 
549
                                    progname);
 
550
                                exit(1);
 
551
                        }
 
552
                        Var_Append(MAKEFLAGS, "-j", VAR_GLOBAL);
 
553
                        Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL);
 
554
                        Var_Set(".MAKE.JOBS", argvalue, VAR_GLOBAL, 0);
 
555
                        maxJobTokens = maxJobs;
 
556
                        break;
 
557
                case 'k':
 
558
                        keepgoing = TRUE;
 
559
                        Var_Append(MAKEFLAGS, "-k", VAR_GLOBAL);
 
560
                        break;
 
561
                case 'm':
 
562
                        if (argvalue == NULL) goto noarg;
 
563
                        /* look for magic parent directory search string */
 
564
                        if (strncmp(".../", argvalue, 4) == 0) {
 
565
                                if (!Dir_FindHereOrAbove(curdir, argvalue+4,
 
566
                                    found_path, sizeof(found_path)))
 
567
                                        break;          /* nothing doing */
 
568
                                (void)Dir_AddDir(sysIncPath, found_path);
 
569
                        } else {
 
570
                                (void)Dir_AddDir(sysIncPath, argvalue);
 
571
                        }
 
572
                        Var_Append(MAKEFLAGS, "-m", VAR_GLOBAL);
 
573
                        Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL);
 
574
                        break;
 
575
                case 'n':
 
576
                        noExecute = TRUE;
 
577
                        Var_Append(MAKEFLAGS, "-n", VAR_GLOBAL);
 
578
                        break;
 
579
                case 'q':
 
580
                        queryFlag = TRUE;
 
581
                        /* Kind of nonsensical, wot? */
 
582
                        Var_Append(MAKEFLAGS, "-q", VAR_GLOBAL);
 
583
                        break;
 
584
                case 'r':
 
585
                        noBuiltins = TRUE;
 
586
                        Var_Append(MAKEFLAGS, "-r", VAR_GLOBAL);
 
587
                        break;
 
588
                case 's':
 
589
                        beSilent = TRUE;
 
590
                        Var_Append(MAKEFLAGS, "-s", VAR_GLOBAL);
 
591
                        break;
 
592
                case 't':
 
593
                        touchFlag = TRUE;
 
594
                        Var_Append(MAKEFLAGS, "-t", VAR_GLOBAL);
 
595
                        break;
 
596
                case 'w':
 
597
                        enterFlag = TRUE;
 
598
                        Var_Append(MAKEFLAGS, "-w", VAR_GLOBAL);
 
599
                        break;
 
600
                case '-':
 
601
                        dashDash = TRUE;
 
602
                        break;
 
603
                default:
 
604
                case '?':
 
605
#ifndef MAKE_NATIVE
 
606
                        fprintf(stderr, "getopt(%s) -> %d (%c)\n",
 
607
                                OPTFLAGS, c, c);
 
608
#endif
 
609
                        usage();
 
610
                }
 
611
                argv += arginc;
 
612
                argc -= arginc;
 
613
        }
 
614
 
 
615
        oldVars = TRUE;
 
616
 
 
617
        /*
 
618
         * See if the rest of the arguments are variable assignments and
 
619
         * perform them if so. Else take them to be targets and stuff them
 
620
         * on the end of the "create" list.
 
621
         */
 
622
        for (; argc > 1; ++argv, --argc)
 
623
                if (Parse_IsVar(argv[1])) {
 
624
                        Parse_DoVar(argv[1], VAR_CMD);
 
625
                } else {
 
626
                        if (!*argv[1])
 
627
                                Punt("illegal (null) argument.");
 
628
                        if (*argv[1] == '-' && !dashDash)
 
629
                                goto rearg;
 
630
                        (void)Lst_AtEnd(create, bmake_strdup(argv[1]));
 
631
                }
 
632
 
 
633
        return;
 
634
noarg:
 
635
        (void)fprintf(stderr, "%s: option requires an argument -- %c\n",
 
636
            progname, c);
 
637
        usage();
 
638
}
 
639
 
 
640
/*-
 
641
 * Main_ParseArgLine --
 
642
 *      Used by the parse module when a .MFLAGS or .MAKEFLAGS target
 
643
 *      is encountered and by main() when reading the .MAKEFLAGS envariable.
 
644
 *      Takes a line of arguments and breaks it into its
 
645
 *      component words and passes those words and the number of them to the
 
646
 *      MainParseArgs function.
 
647
 *      The line should have all its leading whitespace removed.
 
648
 *
 
649
 * Input:
 
650
 *      line            Line to fracture
 
651
 *
 
652
 * Results:
 
653
 *      None
 
654
 *
 
655
 * Side Effects:
 
656
 *      Only those that come from the various arguments.
 
657
 */
 
658
void
 
659
Main_ParseArgLine(const char *line)
 
660
{
 
661
        char **argv;                    /* Manufactured argument vector */
 
662
        int argc;                       /* Number of arguments in argv */
 
663
        char *args;                     /* Space used by the args */
 
664
        char *buf, *p1;
 
665
        char *argv0 = Var_Value(".MAKE", VAR_GLOBAL, &p1);
 
666
        size_t len;
 
667
 
 
668
        if (line == NULL)
 
669
                return;
 
670
        for (; *line == ' '; ++line)
 
671
                continue;
 
672
        if (!*line)
 
673
                return;
 
674
 
 
675
#ifndef POSIX
 
676
        {
 
677
                /*
 
678
                 * $MAKE may simply be naming the make(1) binary
 
679
                 */
 
680
                char *cp;
 
681
 
 
682
                if (!(cp = strrchr(line, '/')))
 
683
                        cp = line;
 
684
                if ((cp = strstr(cp, "make")) &&
 
685
                    strcmp(cp, "make") == 0)
 
686
                        return;
 
687
        }
 
688
#endif
 
689
        buf = bmake_malloc(len = strlen(line) + strlen(argv0) + 2);
 
690
        (void)snprintf(buf, len, "%s %s", argv0, line);
 
691
        if (p1)
 
692
                free(p1);
 
693
 
 
694
        argv = brk_string(buf, &argc, TRUE, &args);
 
695
        if (argv == NULL) {
 
696
                Error("Unterminated quoted string [%s]", buf);
 
697
                free(buf);
 
698
                return;
 
699
        }
 
700
        free(buf);
 
701
        MainParseArgs(argc, argv);
 
702
 
 
703
        free(args);
 
704
        free(argv);
 
705
}
 
706
 
 
707
Boolean
 
708
Main_SetObjdir(const char *path)
 
709
{
 
710
        struct stat sb;
 
711
        char *p = NULL;
 
712
        char buf[MAXPATHLEN + 1];
 
713
        Boolean rc = FALSE;
 
714
 
 
715
        /* expand variable substitutions */
 
716
        if (strchr(path, '$') != 0) {
 
717
                snprintf(buf, MAXPATHLEN, "%s", path);
 
718
                path = p = Var_Subst(NULL, buf, VAR_GLOBAL, 0);
 
719
        }
 
720
 
 
721
        if (path[0] != '/') {
 
722
                snprintf(buf, MAXPATHLEN, "%s/%s", curdir, path);
 
723
                path = buf;
 
724
        }
 
725
 
 
726
        /* look for the directory and try to chdir there */
 
727
        if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) {
 
728
                if (chdir(path)) {
 
729
                        (void)fprintf(stderr, "make warning: %s: %s.\n",
 
730
                                      path, strerror(errno));
 
731
                } else {
 
732
                        strncpy(objdir, path, MAXPATHLEN);
 
733
                        Var_Set(".OBJDIR", objdir, VAR_GLOBAL, 0);
 
734
                        setenv("PWD", objdir, 1);
 
735
                        Dir_InitDot();
 
736
                        rc = TRUE;
 
737
                }
 
738
        }
 
739
 
 
740
        if (p)
 
741
                free(p);
 
742
        return rc;
 
743
}
 
744
 
 
745
/*-
 
746
 * ReadAllMakefiles --
 
747
 *      wrapper around ReadMakefile() to read all.
 
748
 *
 
749
 * Results:
 
750
 *      TRUE if ok, FALSE on error
 
751
 */
 
752
static int
 
753
ReadAllMakefiles(const void *p, const void *q)
 
754
{
 
755
        return (ReadMakefile(p, q) == 0);
 
756
}
 
757
 
 
758
int
 
759
str2Lst_Append(Lst lp, char *str, const char *sep)
 
760
{
 
761
    char *cp;
 
762
    int n;
 
763
 
 
764
    if (!sep)
 
765
        sep = " \t";
 
766
 
 
767
    for (n = 0, cp = strtok(str, sep); cp; cp = strtok(NULL, sep)) {
 
768
        (void)Lst_AtEnd(lp, cp);
 
769
        n++;
 
770
    }
 
771
    return (n);
 
772
}
 
773
 
 
774
#ifdef SIGINFO
 
775
/*ARGSUSED*/
 
776
static void
 
777
siginfo(int signo MAKE_ATTR_UNUSED)
 
778
{
 
779
        char dir[MAXPATHLEN];
 
780
        char str[2 * MAXPATHLEN];
 
781
        int len;
 
782
        if (getcwd(dir, sizeof(dir)) == NULL)
 
783
                return;
 
784
        len = snprintf(str, sizeof(str), "%s: Working in: %s\n", progname, dir);
 
785
        if (len > 0)
 
786
                (void)write(STDERR_FILENO, str, (size_t)len);
 
787
}
 
788
#endif
 
789
 
 
790
/*
 
791
 * Allow makefiles some control over the mode we run in.
 
792
 */
 
793
void
 
794
MakeMode(const char *mode)
 
795
{
 
796
    char *mp = NULL;
 
797
 
 
798
    if (!mode)
 
799
        mode = mp = Var_Subst(NULL, "${" MAKE_MODE ":tl}", VAR_GLOBAL, 0);
 
800
 
 
801
    if (mode && *mode) {
 
802
        if (strstr(mode, "compat")) {
 
803
            compatMake = TRUE;
 
804
            forceJobs = FALSE;
 
805
        }
 
806
#if USE_META
 
807
        if (strstr(mode, "meta"))
 
808
            meta_mode_init(mode);
 
809
#endif
 
810
    }
 
811
    if (mp)
 
812
        free(mp);
 
813
}
 
814
 
 
815
/*-
 
816
 * main --
 
817
 *      The main function, for obvious reasons. Initializes variables
 
818
 *      and a few modules, then parses the arguments give it in the
 
819
 *      environment and on the command line. Reads the system makefile
 
820
 *      followed by either Makefile, makefile or the file given by the
 
821
 *      -f argument. Sets the .MAKEFLAGS PMake variable based on all the
 
822
 *      flags it has received by then uses either the Make or the Compat
 
823
 *      module to create the initial list of targets.
 
824
 *
 
825
 * Results:
 
826
 *      If -q was given, exits -1 if anything was out-of-date. Else it exits
 
827
 *      0.
 
828
 *
 
829
 * Side Effects:
 
830
 *      The program exits when done. Targets are created. etc. etc. etc.
 
831
 */
 
832
int
 
833
main(int argc, char **argv)
 
834
{
 
835
        Lst targs;      /* target nodes to create -- passed to Make_Init */
 
836
        Boolean outOfDate = FALSE;      /* FALSE if all targets up to date */
 
837
        struct stat sb, sa;
 
838
        char *p1, *path;
 
839
        char mdpath[MAXPATHLEN];
 
840
#ifdef FORCE_MACHINE
 
841
        const char *machine = FORCE_MACHINE;
 
842
#else
 
843
        const char *machine = getenv("MACHINE");
 
844
#endif
 
845
        const char *machine_arch = getenv("MACHINE_ARCH");
 
846
        char *syspath = getenv("MAKESYSPATH");
 
847
        Lst sysMkPath;                  /* Path of sys.mk */
 
848
        char *cp = NULL, *start;
 
849
                                        /* avoid faults on read-only strings */
 
850
        static char defsyspath[] = _PATH_DEFSYSPATH;
 
851
        char found_path[MAXPATHLEN + 1];        /* for searching for sys.mk */
 
852
        struct timeval rightnow;                /* to initialize random seed */
 
853
        struct utsname utsname;
 
854
 
 
855
        /* default to writing debug to stderr */
 
856
        debug_file = stderr;
 
857
 
 
858
#ifdef SIGINFO
 
859
        (void)bmake_signal(SIGINFO, siginfo);
 
860
#endif
 
861
        /*
 
862
         * Set the seed to produce a different random sequence
 
863
         * on each program execution.
 
864
         */
 
865
        gettimeofday(&rightnow, NULL);
 
866
        srandom(rightnow.tv_sec + rightnow.tv_usec);
 
867
        
 
868
        if ((progname = strrchr(argv[0], '/')) != NULL)
 
869
                progname++;
 
870
        else
 
871
                progname = argv[0];
 
872
#if defined(MAKE_NATIVE) || (defined(HAVE_SETRLIMIT) && defined(RLIMIT_NOFILE))
 
873
        /*
 
874
         * get rid of resource limit on file descriptors
 
875
         */
 
876
        {
 
877
                struct rlimit rl;
 
878
                if (getrlimit(RLIMIT_NOFILE, &rl) != -1 &&
 
879
                    rl.rlim_cur != rl.rlim_max) {
 
880
                        rl.rlim_cur = rl.rlim_max;
 
881
                        (void)setrlimit(RLIMIT_NOFILE, &rl);
 
882
                }
 
883
        }
 
884
#endif
 
885
 
 
886
        if (uname(&utsname) == -1) {
 
887
            (void)fprintf(stderr, "%s: uname failed (%s).\n", progname,
 
888
                strerror(errno));
 
889
            exit(2);
 
890
        }
 
891
 
 
892
        /*
 
893
         * Get the name of this type of MACHINE from utsname
 
894
         * so we can share an executable for similar machines.
 
895
         * (i.e. m68k: amiga hp300, mac68k, sun3, ...)
 
896
         *
 
897
         * Note that both MACHINE and MACHINE_ARCH are decided at
 
898
         * run-time.
 
899
         */
 
900
        if (!machine) {
 
901
#ifdef MAKE_NATIVE
 
902
            machine = utsname.machine;
 
903
#else
 
904
#ifdef MAKE_MACHINE
 
905
            machine = MAKE_MACHINE;
 
906
#else
 
907
            machine = "unknown";
 
908
#endif
 
909
#endif
 
910
        }
 
911
 
 
912
        if (!machine_arch) {
 
913
#ifndef MACHINE_ARCH
 
914
#ifdef MAKE_MACHINE_ARCH
 
915
            machine_arch = MAKE_MACHINE_ARCH;
 
916
#else
 
917
            machine_arch = "unknown";
 
918
#endif
 
919
#else
 
920
            machine_arch = MACHINE_ARCH;
 
921
#endif
 
922
        }
 
923
 
 
924
        myPid = getpid();               /* remember this for vFork() */
 
925
 
 
926
        /*
 
927
         * Just in case MAKEOBJDIR wants us to do something tricky.
 
928
         */
 
929
        Var_Init();             /* Initialize the lists of variables for
 
930
                                 * parsing arguments */
 
931
        Var_Set(".MAKE.OS", utsname.sysname, VAR_GLOBAL, 0);
 
932
        Var_Set("MACHINE", machine, VAR_GLOBAL, 0);
 
933
        Var_Set("MACHINE_ARCH", machine_arch, VAR_GLOBAL, 0);
 
934
#ifdef MAKE_VERSION
 
935
        Var_Set("MAKE_VERSION", MAKE_VERSION, VAR_GLOBAL, 0);
 
936
#endif
 
937
        Var_Set(".newline", "\n", VAR_GLOBAL, 0); /* handy for :@ loops */
 
938
        /*
 
939
         * This is the traditional preference for makefiles.
 
940
         */
 
941
#ifndef MAKEFILE_PREFERENCE_LIST
 
942
# define MAKEFILE_PREFERENCE_LIST "makefile Makefile"
 
943
#endif
 
944
        Var_Set(MAKEFILE_PREFERENCE, MAKEFILE_PREFERENCE_LIST,
 
945
                VAR_GLOBAL, 0);
 
946
        Var_Set(MAKE_DEPENDFILE, ".depend", VAR_GLOBAL, 0);
 
947
 
 
948
        create = Lst_Init(FALSE);
 
949
        makefiles = Lst_Init(FALSE);
 
950
        printVars = FALSE;
 
951
        debugVflag = FALSE;
 
952
        variables = Lst_Init(FALSE);
 
953
        beSilent = FALSE;               /* Print commands as executed */
 
954
        ignoreErrors = FALSE;           /* Pay attention to non-zero returns */
 
955
        noExecute = FALSE;              /* Execute all commands */
 
956
        noRecursiveExecute = FALSE;     /* Execute all .MAKE targets */
 
957
        keepgoing = FALSE;              /* Stop on error */
 
958
        allPrecious = FALSE;            /* Remove targets when interrupted */
 
959
        queryFlag = FALSE;              /* This is not just a check-run */
 
960
        noBuiltins = FALSE;             /* Read the built-in rules */
 
961
        touchFlag = FALSE;              /* Actually update targets */
 
962
        debug = 0;                      /* No debug verbosity, please. */
 
963
        jobsRunning = FALSE;
 
964
 
 
965
        maxJobs = DEFMAXLOCAL;          /* Set default local max concurrency */
 
966
        maxJobTokens = maxJobs;
 
967
        compatMake = FALSE;             /* No compat mode */
 
968
        ignorePWD = FALSE;
 
969
 
 
970
        /*
 
971
         * Initialize the parsing, directory and variable modules to prepare
 
972
         * for the reading of inclusion paths and variable settings on the
 
973
         * command line
 
974
         */
 
975
 
 
976
        /*
 
977
         * Initialize various variables.
 
978
         *      MAKE also gets this name, for compatibility
 
979
         *      .MAKEFLAGS gets set to the empty string just in case.
 
980
         *      MFLAGS also gets initialized empty, for compatibility.
 
981
         */
 
982
        Parse_Init();
 
983
        if (argv[0][0] == '/' || strchr(argv[0], '/') == NULL) {
 
984
            /*
 
985
             * Leave alone if it is an absolute path, or if it does
 
986
             * not contain a '/' in which case we need to find it in
 
987
             * the path, like execvp(3) and the shells do.
 
988
             */
 
989
            p1 = argv[0];
 
990
        } else {
 
991
            /*
 
992
             * A relative path, canonicalize it.
 
993
             */
 
994
            p1 = realpath(argv[0], mdpath);
 
995
            if (!p1 || *p1 != '/' || stat(p1, &sb) < 0) {
 
996
                p1 = argv[0];           /* realpath failed */
 
997
            }
 
998
        }
 
999
        Var_Set("MAKE", p1, VAR_GLOBAL, 0);
 
1000
        Var_Set(".MAKE", p1, VAR_GLOBAL, 0);
 
1001
        Var_Set(MAKEFLAGS, "", VAR_GLOBAL, 0);
 
1002
        Var_Set(MAKEOVERRIDES, "", VAR_GLOBAL, 0);
 
1003
        Var_Set("MFLAGS", "", VAR_GLOBAL, 0);
 
1004
        Var_Set(".ALLTARGETS", "", VAR_GLOBAL, 0);
 
1005
        /* some makefiles need to know this */
 
1006
        Var_Set(MAKE_LEVEL ".ENV", MAKE_LEVEL_ENV, VAR_CMD, 0);
 
1007
 
 
1008
        /*
 
1009
         * Set some other useful macros
 
1010
         */
 
1011
        {
 
1012
            char tmp[64], *ep;
 
1013
 
 
1014
            makelevel = ((ep = getenv(MAKE_LEVEL_ENV)) && *ep) ? atoi(ep) : 0;
 
1015
            if (makelevel < 0)
 
1016
                makelevel = 0;
 
1017
            snprintf(tmp, sizeof(tmp), "%d", makelevel);
 
1018
            Var_Set(MAKE_LEVEL, tmp, VAR_GLOBAL, 0);
 
1019
            snprintf(tmp, sizeof(tmp), "%u", myPid);
 
1020
            Var_Set(".MAKE.PID", tmp, VAR_GLOBAL, 0);
 
1021
            snprintf(tmp, sizeof(tmp), "%u", getppid());
 
1022
            Var_Set(".MAKE.PPID", tmp, VAR_GLOBAL, 0);
 
1023
        }
 
1024
        if (makelevel > 0) {
 
1025
                char pn[1024];
 
1026
                snprintf(pn, sizeof(pn), "%s[%d]", progname, makelevel);
 
1027
                progname = bmake_strdup(pn);
 
1028
        }
 
1029
 
 
1030
#ifdef USE_META
 
1031
        meta_init();
 
1032
#endif
 
1033
        /*
 
1034
         * First snag any flags out of the MAKE environment variable.
 
1035
         * (Note this is *not* MAKEFLAGS since /bin/make uses that and it's
 
1036
         * in a different format).
 
1037
         */
 
1038
#ifdef POSIX
 
1039
        p1 = explode(getenv("MAKEFLAGS"));
 
1040
        Main_ParseArgLine(p1);
 
1041
        free(p1);
 
1042
#else
 
1043
        Main_ParseArgLine(getenv("MAKE"));
 
1044
#endif
 
1045
 
 
1046
        /*
 
1047
         * Find where we are (now).
 
1048
         * We take care of PWD for the automounter below...
 
1049
         */
 
1050
        if (getcwd(curdir, MAXPATHLEN) == NULL) {
 
1051
                (void)fprintf(stderr, "%s: getcwd: %s.\n",
 
1052
                    progname, strerror(errno));
 
1053
                exit(2);
 
1054
        }
 
1055
 
 
1056
        MainParseArgs(argc, argv);
 
1057
 
 
1058
        if (enterFlag)
 
1059
                printf("%s: Entering directory `%s'\n", progname, curdir);
 
1060
 
 
1061
        /*
 
1062
         * Verify that cwd is sane.
 
1063
         */
 
1064
        if (stat(curdir, &sa) == -1) {
 
1065
            (void)fprintf(stderr, "%s: %s: %s.\n",
 
1066
                 progname, curdir, strerror(errno));
 
1067
            exit(2);
 
1068
        }
 
1069
 
 
1070
        /*
 
1071
         * All this code is so that we know where we are when we start up
 
1072
         * on a different machine with pmake.
 
1073
         * Overriding getcwd() with $PWD totally breaks MAKEOBJDIRPREFIX
 
1074
         * since the value of curdir can vary depending on how we got
 
1075
         * here.  Ie sitting at a shell prompt (shell that provides $PWD)
 
1076
         * or via subdir.mk in which case its likely a shell which does
 
1077
         * not provide it.
 
1078
         * So, to stop it breaking this case only, we ignore PWD if
 
1079
         * MAKEOBJDIRPREFIX is set or MAKEOBJDIR contains a transform.
 
1080
         */
 
1081
#ifndef NO_PWD_OVERRIDE
 
1082
        if (!ignorePWD) {
 
1083
                char *pwd;
 
1084
 
 
1085
                if ((pwd = getenv("PWD")) != NULL &&
 
1086
                    getenv("MAKEOBJDIRPREFIX") == NULL) {
 
1087
                        const char *makeobjdir = getenv("MAKEOBJDIR");
 
1088
 
 
1089
                        if (makeobjdir == NULL || !strchr(makeobjdir, '$')) {
 
1090
                                if (stat(pwd, &sb) == 0 &&
 
1091
                                    sa.st_ino == sb.st_ino &&
 
1092
                                    sa.st_dev == sb.st_dev)
 
1093
                                        (void)strncpy(curdir, pwd, MAXPATHLEN);
 
1094
                        }
 
1095
                }
 
1096
        }
 
1097
#endif
 
1098
        Var_Set(".CURDIR", curdir, VAR_GLOBAL, 0);
 
1099
 
 
1100
        /*
 
1101
         * Find the .OBJDIR.  If MAKEOBJDIRPREFIX, or failing that,
 
1102
         * MAKEOBJDIR is set in the environment, try only that value
 
1103
         * and fall back to .CURDIR if it does not exist.
 
1104
         *
 
1105
         * Otherwise, try _PATH_OBJDIR.MACHINE, _PATH_OBJDIR, and
 
1106
         * finally _PATH_OBJDIRPREFIX`pwd`, in that order.  If none
 
1107
         * of these paths exist, just use .CURDIR.
 
1108
         */
 
1109
        Dir_Init(curdir);
 
1110
        (void)Main_SetObjdir(curdir);
 
1111
 
 
1112
        if ((path = getenv("MAKEOBJDIRPREFIX")) != NULL) {
 
1113
                (void)snprintf(mdpath, MAXPATHLEN, "%s%s", path, curdir);
 
1114
                (void)Main_SetObjdir(mdpath);
 
1115
        } else if ((path = getenv("MAKEOBJDIR")) != NULL) {
 
1116
                (void)Main_SetObjdir(path);
 
1117
        } else {
 
1118
                (void)snprintf(mdpath, MAXPATHLEN, "%s.%s", _PATH_OBJDIR, machine);
 
1119
                if (!Main_SetObjdir(mdpath) && !Main_SetObjdir(_PATH_OBJDIR)) {
 
1120
                        (void)snprintf(mdpath, MAXPATHLEN, "%s%s", 
 
1121
                                        _PATH_OBJDIRPREFIX, curdir);
 
1122
                        (void)Main_SetObjdir(mdpath);
 
1123
                }
 
1124
        }
 
1125
 
 
1126
        /*
 
1127
         * Be compatible if user did not specify -j and did not explicitly
 
1128
         * turned compatibility on
 
1129
         */
 
1130
        if (!compatMake && !forceJobs) {
 
1131
                compatMake = TRUE;
 
1132
        }
 
1133
        
 
1134
        /*
 
1135
         * Initialize archive, target and suffix modules in preparation for
 
1136
         * parsing the makefile(s)
 
1137
         */
 
1138
        Arch_Init();
 
1139
        Targ_Init();
 
1140
        Suff_Init();
 
1141
        Trace_Init(tracefile);
 
1142
 
 
1143
        DEFAULT = NULL;
 
1144
        (void)time(&now);
 
1145
 
 
1146
        Trace_Log(MAKESTART, NULL);
 
1147
        
 
1148
        /*
 
1149
         * Set up the .TARGETS variable to contain the list of targets to be
 
1150
         * created. If none specified, make the variable empty -- the parser
 
1151
         * will fill the thing in with the default or .MAIN target.
 
1152
         */
 
1153
        if (!Lst_IsEmpty(create)) {
 
1154
                LstNode ln;
 
1155
 
 
1156
                for (ln = Lst_First(create); ln != NULL;
 
1157
                    ln = Lst_Succ(ln)) {
 
1158
                        char *name = (char *)Lst_Datum(ln);
 
1159
 
 
1160
                        Var_Append(".TARGETS", name, VAR_GLOBAL);
 
1161
                }
 
1162
        } else
 
1163
                Var_Set(".TARGETS", "", VAR_GLOBAL, 0);
 
1164
 
 
1165
 
 
1166
        /*
 
1167
         * If no user-supplied system path was given (through the -m option)
 
1168
         * add the directories from the DEFSYSPATH (more than one may be given
 
1169
         * as dir1:...:dirn) to the system include path.
 
1170
         */
 
1171
        if (syspath == NULL || *syspath == '\0')
 
1172
                syspath = defsyspath;
 
1173
        else
 
1174
                syspath = bmake_strdup(syspath);
 
1175
 
 
1176
        for (start = syspath; *start != '\0'; start = cp) {
 
1177
                for (cp = start; *cp != '\0' && *cp != ':'; cp++)
 
1178
                        continue;
 
1179
                if (*cp == ':') {
 
1180
                        *cp++ = '\0';
 
1181
                }
 
1182
                /* look for magic parent directory search string */
 
1183
                if (strncmp(".../", start, 4) != 0) {
 
1184
                        (void)Dir_AddDir(defIncPath, start);
 
1185
                } else {
 
1186
                        if (Dir_FindHereOrAbove(curdir, start+4, 
 
1187
                            found_path, sizeof(found_path))) {
 
1188
                                (void)Dir_AddDir(defIncPath, found_path);
 
1189
                        }
 
1190
                }
 
1191
        }
 
1192
        if (syspath != defsyspath)
 
1193
                free(syspath);
 
1194
 
 
1195
        /*
 
1196
         * Read in the built-in rules first, followed by the specified
 
1197
         * makefile, if it was (makefile != NULL), or the default
 
1198
         * makefile and Makefile, in that order, if it wasn't.
 
1199
         */
 
1200
        if (!noBuiltins) {
 
1201
                LstNode ln;
 
1202
 
 
1203
                sysMkPath = Lst_Init(FALSE);
 
1204
                Dir_Expand(_PATH_DEFSYSMK,
 
1205
                           Lst_IsEmpty(sysIncPath) ? defIncPath : sysIncPath,
 
1206
                           sysMkPath);
 
1207
                if (Lst_IsEmpty(sysMkPath))
 
1208
                        Fatal("%s: no system rules (%s).", progname,
 
1209
                            _PATH_DEFSYSMK);
 
1210
                ln = Lst_Find(sysMkPath, NULL, ReadMakefile);
 
1211
                if (ln == NULL)
 
1212
                        Fatal("%s: cannot open %s.", progname,
 
1213
                            (char *)Lst_Datum(ln));
 
1214
        }
 
1215
 
 
1216
        if (!Lst_IsEmpty(makefiles)) {
 
1217
                LstNode ln;
 
1218
 
 
1219
                ln = Lst_Find(makefiles, NULL, ReadAllMakefiles);
 
1220
                if (ln != NULL)
 
1221
                        Fatal("%s: cannot open %s.", progname, 
 
1222
                            (char *)Lst_Datum(ln));
 
1223
        } else {
 
1224
            p1 = Var_Subst(NULL, "${" MAKEFILE_PREFERENCE "}",
 
1225
                VAR_CMD, 0);
 
1226
            if (p1) {
 
1227
                (void)str2Lst_Append(makefiles, p1, NULL);
 
1228
                (void)Lst_Find(makefiles, NULL, ReadMakefile);
 
1229
                free(p1);
 
1230
            }
 
1231
        }
 
1232
 
 
1233
        /* In particular suppress .depend for '-r -V .OBJDIR -f /dev/null' */
 
1234
        if (!noBuiltins || !printVars) {
 
1235
            makeDependfile = Var_Subst(NULL, "${.MAKE.DEPENDFILE:T}",
 
1236
                VAR_CMD, 0);
 
1237
            doing_depend = TRUE;
 
1238
            (void)ReadMakefile(makeDependfile, NULL);
 
1239
            doing_depend = FALSE;
 
1240
        }
 
1241
 
 
1242
        MakeMode(NULL);
 
1243
 
 
1244
        Var_Append("MFLAGS", Var_Value(MAKEFLAGS, VAR_GLOBAL, &p1), VAR_GLOBAL);
 
1245
        if (p1)
 
1246
            free(p1);
 
1247
 
 
1248
        if (!compatMake)
 
1249
            Job_ServerStart(maxJobTokens, jp_0, jp_1);
 
1250
        if (DEBUG(JOB))
 
1251
            fprintf(debug_file, "job_pipe %d %d, maxjobs %d, tokens %d, compat %d\n",
 
1252
                jp_0, jp_1, maxJobs, maxJobTokens, compatMake);
 
1253
 
 
1254
        Main_ExportMAKEFLAGS(TRUE);     /* initial export */
 
1255
 
 
1256
        /*
 
1257
         * For compatibility, look at the directories in the VPATH variable
 
1258
         * and add them to the search path, if the variable is defined. The
 
1259
         * variable's value is in the same format as the PATH envariable, i.e.
 
1260
         * <directory>:<directory>:<directory>...
 
1261
         */
 
1262
        if (Var_Exists("VPATH", VAR_CMD)) {
 
1263
                char *vpath, savec;
 
1264
                /*
 
1265
                 * GCC stores string constants in read-only memory, but
 
1266
                 * Var_Subst will want to write this thing, so store it
 
1267
                 * in an array
 
1268
                 */
 
1269
                static char VPATH[] = "${VPATH}";
 
1270
 
 
1271
                vpath = Var_Subst(NULL, VPATH, VAR_CMD, FALSE);
 
1272
                path = vpath;
 
1273
                do {
 
1274
                        /* skip to end of directory */
 
1275
                        for (cp = path; *cp != ':' && *cp != '\0'; cp++)
 
1276
                                continue;
 
1277
                        /* Save terminator character so know when to stop */
 
1278
                        savec = *cp;
 
1279
                        *cp = '\0';
 
1280
                        /* Add directory to search path */
 
1281
                        (void)Dir_AddDir(dirSearchPath, path);
 
1282
                        *cp = savec;
 
1283
                        path = cp + 1;
 
1284
                } while (savec == ':');
 
1285
                free(vpath);
 
1286
        }
 
1287
 
 
1288
        /*
 
1289
         * Now that all search paths have been read for suffixes et al, it's
 
1290
         * time to add the default search path to their lists...
 
1291
         */
 
1292
        Suff_DoPaths();
 
1293
 
 
1294
        /*
 
1295
         * Propagate attributes through :: dependency lists.
 
1296
         */
 
1297
        Targ_Propagate();
 
1298
 
 
1299
        /* print the initial graph, if the user requested it */
 
1300
        if (DEBUG(GRAPH1))
 
1301
                Targ_PrintGraph(1);
 
1302
 
 
1303
        /* print the values of any variables requested by the user */
 
1304
        if (printVars) {
 
1305
                LstNode ln;
 
1306
                Boolean expandVars;
 
1307
 
 
1308
                if (debugVflag)
 
1309
                        expandVars = FALSE;
 
1310
                else
 
1311
                        expandVars = getBoolean(".MAKE.EXPAND_VARIABLES", FALSE);
 
1312
                for (ln = Lst_First(variables); ln != NULL;
 
1313
                    ln = Lst_Succ(ln)) {
 
1314
                        char *var = (char *)Lst_Datum(ln);
 
1315
                        char *value;
 
1316
                        
 
1317
                        if (strchr(var, '$')) {
 
1318
                                value = p1 = Var_Subst(NULL, var, VAR_GLOBAL, 0);
 
1319
                        } else if (expandVars) {
 
1320
                                char tmp[128];
 
1321
                                                                
 
1322
                                if (snprintf(tmp, sizeof(tmp), "${%s}", var) >= (int)(sizeof(tmp)))
 
1323
                                        Fatal("%s: variable name too big: %s",
 
1324
                                              progname, var);
 
1325
                                value = p1 = Var_Subst(NULL, tmp, VAR_GLOBAL, 0);
 
1326
                        } else {
 
1327
                                value = Var_Value(var, VAR_GLOBAL, &p1);
 
1328
                        }
 
1329
                        printf("%s\n", value ? value : "");
 
1330
                        if (p1)
 
1331
                                free(p1);
 
1332
                }
 
1333
        } else {
 
1334
                /*
 
1335
                 * Have now read the entire graph and need to make a list of
 
1336
                 * targets to create. If none was given on the command line,
 
1337
                 * we consult the parsing module to find the main target(s)
 
1338
                 * to create.
 
1339
                 */
 
1340
                if (Lst_IsEmpty(create))
 
1341
                        targs = Parse_MainName();
 
1342
                else
 
1343
                        targs = Targ_FindList(create, TARG_CREATE);
 
1344
 
 
1345
                if (!compatMake) {
 
1346
                        /*
 
1347
                         * Initialize job module before traversing the graph
 
1348
                         * now that any .BEGIN and .END targets have been read.
 
1349
                         * This is done only if the -q flag wasn't given
 
1350
                         * (to prevent the .BEGIN from being executed should
 
1351
                         * it exist).
 
1352
                         */
 
1353
                        if (!queryFlag) {
 
1354
                                Job_Init();
 
1355
                                jobsRunning = TRUE;
 
1356
                        }
 
1357
 
 
1358
                        /* Traverse the graph, checking on all the targets */
 
1359
                        outOfDate = Make_Run(targs);
 
1360
                } else {
 
1361
                        /*
 
1362
                         * Compat_Init will take care of creating all the
 
1363
                         * targets as well as initializing the module.
 
1364
                         */
 
1365
                        Compat_Run(targs);
 
1366
                }
 
1367
        }
 
1368
 
 
1369
#ifdef CLEANUP
 
1370
        Lst_Destroy(targs, NULL);
 
1371
        Lst_Destroy(variables, NULL);
 
1372
        Lst_Destroy(makefiles, NULL);
 
1373
        Lst_Destroy(create, (FreeProc *)free);
 
1374
#endif
 
1375
 
 
1376
        /* print the graph now it's been processed if the user requested it */
 
1377
        if (DEBUG(GRAPH2))
 
1378
                Targ_PrintGraph(2);
 
1379
 
 
1380
        Trace_Log(MAKEEND, 0);
 
1381
 
 
1382
        if (enterFlag)
 
1383
                printf("%s: Leaving directory `%s'\n", progname, curdir);
 
1384
 
 
1385
        Suff_End();
 
1386
        Targ_End();
 
1387
        Arch_End();
 
1388
        Var_End();
 
1389
        Parse_End();
 
1390
        Dir_End();
 
1391
        Job_End();
 
1392
        Trace_End();
 
1393
 
 
1394
        return outOfDate ? 1 : 0;
 
1395
}
 
1396
 
 
1397
/*-
 
1398
 * ReadMakefile  --
 
1399
 *      Open and parse the given makefile.
 
1400
 *
 
1401
 * Results:
 
1402
 *      0 if ok. -1 if couldn't open file.
 
1403
 *
 
1404
 * Side Effects:
 
1405
 *      lots
 
1406
 */
 
1407
static int
 
1408
ReadMakefile(const void *p, const void *q MAKE_ATTR_UNUSED)
 
1409
{
 
1410
        const char *fname = p;          /* makefile to read */
 
1411
        int fd;
 
1412
        size_t len = MAXPATHLEN;
 
1413
        char *name, *path = bmake_malloc(len);
 
1414
 
 
1415
        if (!strcmp(fname, "-")) {
 
1416
                Parse_File(NULL /*stdin*/, -1);
 
1417
                Var_Set("MAKEFILE", "", VAR_INTERNAL, 0);
 
1418
        } else {
 
1419
                /* if we've chdir'd, rebuild the path name */
 
1420
                if (strcmp(curdir, objdir) && *fname != '/') {
 
1421
                        size_t plen = strlen(curdir) + strlen(fname) + 2;
 
1422
                        if (len < plen)
 
1423
                                path = bmake_realloc(path, len = 2 * plen);
 
1424
                        
 
1425
                        (void)snprintf(path, len, "%s/%s", curdir, fname);
 
1426
                        fd = open(path, O_RDONLY);
 
1427
                        if (fd != -1) {
 
1428
                                fname = path;
 
1429
                                goto found;
 
1430
                        }
 
1431
                        
 
1432
                        /* If curdir failed, try objdir (ala .depend) */
 
1433
                        plen = strlen(objdir) + strlen(fname) + 2;
 
1434
                        if (len < plen)
 
1435
                                path = bmake_realloc(path, len = 2 * plen);
 
1436
                        (void)snprintf(path, len, "%s/%s", objdir, fname);
 
1437
                        fd = open(path, O_RDONLY);
 
1438
                        if (fd != -1) {
 
1439
                                fname = path;
 
1440
                                goto found;
 
1441
                        }
 
1442
                } else {
 
1443
                        fd = open(fname, O_RDONLY);
 
1444
                        if (fd != -1)
 
1445
                                goto found;
 
1446
                }
 
1447
                /* look in -I and system include directories. */
 
1448
                name = Dir_FindFile(fname, parseIncPath);
 
1449
                if (!name)
 
1450
                        name = Dir_FindFile(fname,
 
1451
                                Lst_IsEmpty(sysIncPath) ? defIncPath : sysIncPath);
 
1452
                if (!name || (fd = open(name, O_RDONLY)) == -1) {
 
1453
                        if (name)
 
1454
                                free(name);
 
1455
                        free(path);
 
1456
                        return(-1);
 
1457
                }
 
1458
                fname = name;
 
1459
                /*
 
1460
                 * set the MAKEFILE variable desired by System V fans -- the
 
1461
                 * placement of the setting here means it gets set to the last
 
1462
                 * makefile specified, as it is set by SysV make.
 
1463
                 */
 
1464
found:
 
1465
                if (!doing_depend)
 
1466
                        Var_Set("MAKEFILE", fname, VAR_INTERNAL, 0);
 
1467
                Parse_File(fname, fd);
 
1468
        }
 
1469
        free(path);
 
1470
        return(0);
 
1471
}
 
1472
 
 
1473
 
 
1474
 
 
1475
/*-
 
1476
 * Cmd_Exec --
 
1477
 *      Execute the command in cmd, and return the output of that command
 
1478
 *      in a string.
 
1479
 *
 
1480
 * Results:
 
1481
 *      A string containing the output of the command, or the empty string
 
1482
 *      If errnum is not NULL, it contains the reason for the command failure
 
1483
 *
 
1484
 * Side Effects:
 
1485
 *      The string must be freed by the caller.
 
1486
 */
 
1487
char *
 
1488
Cmd_Exec(const char *cmd, const char **errnum)
 
1489
{
 
1490
    const char  *args[4];       /* Args for invoking the shell */
 
1491
    int         fds[2];         /* Pipe streams */
 
1492
    int         cpid;           /* Child PID */
 
1493
    int         pid;            /* PID from wait() */
 
1494
    char        *res;           /* result */
 
1495
    WAIT_T      status;         /* command exit status */
 
1496
    Buffer      buf;            /* buffer to store the result */
 
1497
    char        *cp;
 
1498
    int         cc;
 
1499
 
 
1500
 
 
1501
    *errnum = NULL;
 
1502
 
 
1503
    if (!shellName)
 
1504
        Shell_Init();
 
1505
    /*
 
1506
     * Set up arguments for shell
 
1507
     */
 
1508
    args[0] = shellName;
 
1509
    args[1] = "-c";
 
1510
    args[2] = cmd;
 
1511
    args[3] = NULL;
 
1512
 
 
1513
    /*
 
1514
     * Open a pipe for fetching its output
 
1515
     */
 
1516
    if (pipe(fds) == -1) {
 
1517
        *errnum = "Couldn't create pipe for \"%s\"";
 
1518
        goto bad;
 
1519
    }
 
1520
 
 
1521
    /*
 
1522
     * Fork
 
1523
     */
 
1524
    switch (cpid = vFork()) {
 
1525
    case 0:
 
1526
        /*
 
1527
         * Close input side of pipe
 
1528
         */
 
1529
        (void)close(fds[0]);
 
1530
 
 
1531
        /*
 
1532
         * Duplicate the output stream to the shell's output, then
 
1533
         * shut the extra thing down. Note we don't fetch the error
 
1534
         * stream...why not? Why?
 
1535
         */
 
1536
        (void)dup2(fds[1], 1);
 
1537
        (void)close(fds[1]);
 
1538
 
 
1539
        Var_ExportVars();
 
1540
 
 
1541
        (void)execv(shellPath, UNCONST(args));
 
1542
        _exit(1);
 
1543
        /*NOTREACHED*/
 
1544
 
 
1545
    case -1:
 
1546
        *errnum = "Couldn't exec \"%s\"";
 
1547
        goto bad;
 
1548
 
 
1549
    default:
 
1550
        /*
 
1551
         * No need for the writing half
 
1552
         */
 
1553
        (void)close(fds[1]);
 
1554
 
 
1555
        Buf_Init(&buf, 0);
 
1556
 
 
1557
        do {
 
1558
            char   result[BUFSIZ];
 
1559
            cc = read(fds[0], result, sizeof(result));
 
1560
            if (cc > 0)
 
1561
                Buf_AddBytes(&buf, cc, result);
 
1562
        }
 
1563
        while (cc > 0 || (cc == -1 && errno == EINTR));
 
1564
 
 
1565
        /*
 
1566
         * Close the input side of the pipe.
 
1567
         */
 
1568
        (void)close(fds[0]);
 
1569
 
 
1570
        /*
 
1571
         * Wait for the process to exit.
 
1572
         */
 
1573
        while(((pid = waitpid(cpid, &status, 0)) != cpid) && (pid >= 0)) {
 
1574
            JobReapChild(pid, status, FALSE);
 
1575
            continue;
 
1576
        }
 
1577
        cc = Buf_Size(&buf);
 
1578
        res = Buf_Destroy(&buf, FALSE);
 
1579
 
 
1580
        if (cc == 0)
 
1581
            *errnum = "Couldn't read shell's output for \"%s\"";
 
1582
 
 
1583
        if (WIFSIGNALED(status))
 
1584
            *errnum = "\"%s\" exited on a signal";
 
1585
        else if (WEXITSTATUS(status) != 0)
 
1586
            *errnum = "\"%s\" returned non-zero status";
 
1587
 
 
1588
        /*
 
1589
         * Null-terminate the result, convert newlines to spaces and
 
1590
         * install it in the variable.
 
1591
         */
 
1592
        res[cc] = '\0';
 
1593
        cp = &res[cc];
 
1594
 
 
1595
        if (cc > 0 && *--cp == '\n') {
 
1596
            /*
 
1597
             * A final newline is just stripped
 
1598
             */
 
1599
            *cp-- = '\0';
 
1600
        }
 
1601
        while (cp >= res) {
 
1602
            if (*cp == '\n') {
 
1603
                *cp = ' ';
 
1604
            }
 
1605
            cp--;
 
1606
        }
 
1607
        break;
 
1608
    }
 
1609
    return res;
 
1610
bad:
 
1611
    res = bmake_malloc(1);
 
1612
    *res = '\0';
 
1613
    return res;
 
1614
}
 
1615
 
 
1616
/*-
 
1617
 * Error --
 
1618
 *      Print an error message given its format.
 
1619
 *
 
1620
 * Results:
 
1621
 *      None.
 
1622
 *
 
1623
 * Side Effects:
 
1624
 *      The message is printed.
 
1625
 */
 
1626
/* VARARGS */
 
1627
void
 
1628
Error(const char *fmt, ...)
 
1629
{
 
1630
        va_list ap;
 
1631
        FILE *err_file;
 
1632
 
 
1633
        err_file = debug_file;
 
1634
        if (err_file == stdout)
 
1635
                err_file = stderr;
 
1636
        (void)fflush(stdout);
 
1637
        for (;;) {
 
1638
                va_start(ap, fmt);
 
1639
                fprintf(err_file, "%s: ", progname);
 
1640
                (void)vfprintf(err_file, fmt, ap);
 
1641
                va_end(ap);
 
1642
                (void)fprintf(err_file, "\n");
 
1643
                (void)fflush(err_file);
 
1644
                if (err_file == stderr)
 
1645
                        break;
 
1646
                err_file = stderr;
 
1647
        }
 
1648
}
 
1649
 
 
1650
/*-
 
1651
 * Fatal --
 
1652
 *      Produce a Fatal error message. If jobs are running, waits for them
 
1653
 *      to finish.
 
1654
 *
 
1655
 * Results:
 
1656
 *      None
 
1657
 *
 
1658
 * Side Effects:
 
1659
 *      The program exits
 
1660
 */
 
1661
/* VARARGS */
 
1662
void
 
1663
Fatal(const char *fmt, ...)
 
1664
{
 
1665
        va_list ap;
 
1666
 
 
1667
        va_start(ap, fmt);
 
1668
        if (jobsRunning)
 
1669
                Job_Wait();
 
1670
 
 
1671
        (void)fflush(stdout);
 
1672
        (void)vfprintf(stderr, fmt, ap);
 
1673
        va_end(ap);
 
1674
        (void)fprintf(stderr, "\n");
 
1675
        (void)fflush(stderr);
 
1676
 
 
1677
        PrintOnError(NULL, NULL);
 
1678
 
 
1679
        if (DEBUG(GRAPH2) || DEBUG(GRAPH3))
 
1680
                Targ_PrintGraph(2);
 
1681
        Trace_Log(MAKEERROR, 0);
 
1682
        exit(2);                /* Not 1 so -q can distinguish error */
 
1683
}
 
1684
 
 
1685
/*
 
1686
 * Punt --
 
1687
 *      Major exception once jobs are being created. Kills all jobs, prints
 
1688
 *      a message and exits.
 
1689
 *
 
1690
 * Results:
 
1691
 *      None
 
1692
 *
 
1693
 * Side Effects:
 
1694
 *      All children are killed indiscriminately and the program Lib_Exits
 
1695
 */
 
1696
/* VARARGS */
 
1697
void
 
1698
Punt(const char *fmt, ...)
 
1699
{
 
1700
        va_list ap;
 
1701
 
 
1702
        va_start(ap, fmt);
 
1703
        (void)fflush(stdout);
 
1704
        (void)fprintf(stderr, "%s: ", progname);
 
1705
        (void)vfprintf(stderr, fmt, ap);
 
1706
        va_end(ap);
 
1707
        (void)fprintf(stderr, "\n");
 
1708
        (void)fflush(stderr);
 
1709
 
 
1710
        PrintOnError(NULL, NULL);
 
1711
 
 
1712
        DieHorribly();
 
1713
}
 
1714
 
 
1715
/*-
 
1716
 * DieHorribly --
 
1717
 *      Exit without giving a message.
 
1718
 *
 
1719
 * Results:
 
1720
 *      None
 
1721
 *
 
1722
 * Side Effects:
 
1723
 *      A big one...
 
1724
 */
 
1725
void
 
1726
DieHorribly(void)
 
1727
{
 
1728
        if (jobsRunning)
 
1729
                Job_AbortAll();
 
1730
        if (DEBUG(GRAPH2))
 
1731
                Targ_PrintGraph(2);
 
1732
        Trace_Log(MAKEERROR, 0);
 
1733
        exit(2);                /* Not 1, so -q can distinguish error */
 
1734
}
 
1735
 
 
1736
/*
 
1737
 * Finish --
 
1738
 *      Called when aborting due to errors in child shell to signal
 
1739
 *      abnormal exit.
 
1740
 *
 
1741
 * Results:
 
1742
 *      None
 
1743
 *
 
1744
 * Side Effects:
 
1745
 *      The program exits
 
1746
 */
 
1747
void
 
1748
Finish(int errors)
 
1749
                        /* number of errors encountered in Make_Make */
 
1750
{
 
1751
        Fatal("%d error%s", errors, errors == 1 ? "" : "s");
 
1752
}
 
1753
 
 
1754
/*
 
1755
 * eunlink --
 
1756
 *      Remove a file carefully, avoiding directories.
 
1757
 */
 
1758
int
 
1759
eunlink(const char *file)
 
1760
{
 
1761
        struct stat st;
 
1762
 
 
1763
        if (lstat(file, &st) == -1)
 
1764
                return -1;
 
1765
 
 
1766
        if (S_ISDIR(st.st_mode)) {
 
1767
                errno = EISDIR;
 
1768
                return -1;
 
1769
        }
 
1770
        return unlink(file);
 
1771
}
 
1772
 
 
1773
/*
 
1774
 * execError --
 
1775
 *      Print why exec failed, avoiding stdio.
 
1776
 */
 
1777
void
 
1778
execError(const char *af, const char *av)
 
1779
{
 
1780
#ifdef USE_IOVEC
 
1781
        int i = 0;
 
1782
        struct iovec iov[8];
 
1783
#define IOADD(s) \
 
1784
        (void)(iov[i].iov_base = UNCONST(s), \
 
1785
            iov[i].iov_len = strlen(iov[i].iov_base), \
 
1786
            i++)
 
1787
#else
 
1788
#define IOADD(s) (void)write(2, s, strlen(s))
 
1789
#endif
 
1790
 
 
1791
        IOADD(progname);
 
1792
        IOADD(": ");
 
1793
        IOADD(af);
 
1794
        IOADD("(");
 
1795
        IOADD(av);
 
1796
        IOADD(") failed (");
 
1797
        IOADD(strerror(errno));
 
1798
        IOADD(")\n");
 
1799
 
 
1800
#ifdef USE_IOVEC
 
1801
        while (writev(2, iov, 8) == -1 && errno == EAGAIN)
 
1802
            continue;
 
1803
#endif
 
1804
}
 
1805
 
 
1806
/*
 
1807
 * usage --
 
1808
 *      exit with usage message
 
1809
 */
 
1810
static void
 
1811
usage(void)
 
1812
{
 
1813
        char *p;
 
1814
        if ((p = strchr(progname, '[')) != NULL)
 
1815
            *p = '\0';
 
1816
 
 
1817
        (void)fprintf(stderr,
 
1818
"usage: %s [-BeikNnqrstWwX] \n\
 
1819
            [-C directory] [-D variable] [-d flags] [-f makefile]\n\
 
1820
            [-I directory] [-J private] [-j max_jobs] [-m directory] [-T file]\n\
 
1821
            [-V variable] [variable=value] [target ...]\n", progname);
 
1822
        exit(2);
 
1823
}
 
1824
 
 
1825
 
 
1826
int
 
1827
PrintAddr(void *a, void *b)
 
1828
{
 
1829
    printf("%lx ", (unsigned long) a);
 
1830
    return b ? 0 : 0;
 
1831
}
 
1832
 
 
1833
 
 
1834
 
 
1835
void
 
1836
PrintOnError(GNode *gn, const char *s)
 
1837
{
 
1838
    static GNode *en = NULL;
 
1839
    char tmp[64];
 
1840
    char *cp;
 
1841
 
 
1842
    if (s)
 
1843
        printf("%s", s);
 
1844
        
 
1845
    printf("\n%s: stopped in %s\n", progname, curdir);
 
1846
 
 
1847
    if (en)
 
1848
        return;                         /* we've been here! */
 
1849
    if (gn) {
 
1850
        /*
 
1851
         * We can print this even if there is no .ERROR target.
 
1852
         */
 
1853
        Var_Set(".ERROR_TARGET", gn->name, VAR_GLOBAL, 0);
 
1854
    }
 
1855
    strncpy(tmp, "${MAKE_PRINT_VAR_ON_ERROR:@v@$v='${$v}'\n@}",
 
1856
            sizeof(tmp) - 1);
 
1857
    cp = Var_Subst(NULL, tmp, VAR_GLOBAL, 0);
 
1858
    if (cp) {
 
1859
        if (*cp)
 
1860
            printf("%s", cp);
 
1861
        free(cp);
 
1862
    }
 
1863
    /*
 
1864
     * Finally, see if there is a .ERROR target, and run it if so.
 
1865
     */
 
1866
    en = Targ_FindNode(".ERROR", TARG_NOCREATE);
 
1867
    if (en) {
 
1868
        en->type |= OP_SPECIAL;
 
1869
        Compat_Make(en, en);
 
1870
    }
 
1871
}
 
1872
 
 
1873
void
 
1874
Main_ExportMAKEFLAGS(Boolean first)
 
1875
{
 
1876
    static int once = 1;
 
1877
    char tmp[64];
 
1878
    char *s;
 
1879
 
 
1880
    if (once != first)
 
1881
        return;
 
1882
    once = 0;
 
1883
    
 
1884
    strncpy(tmp, "${.MAKEFLAGS} ${.MAKEOVERRIDES:O:u:@v@$v=${$v:Q}@}",
 
1885
            sizeof(tmp));
 
1886
    s = Var_Subst(NULL, tmp, VAR_CMD, 0);
 
1887
    if (s && *s) {
 
1888
#ifdef POSIX
 
1889
        setenv("MAKEFLAGS", s, 1);
 
1890
#else
 
1891
        setenv("MAKE", s, 1);
 
1892
#endif
 
1893
    }
 
1894
}
 
1895
 
 
1896
char *
 
1897
getTmpdir(void)
 
1898
{
 
1899
    static char *tmpdir = NULL;
 
1900
 
 
1901
    if (!tmpdir) {
 
1902
        struct stat st;
 
1903
 
 
1904
        /*
 
1905
         * Honor $TMPDIR but only if it is valid.
 
1906
         * Ensure it ends with /.
 
1907
         */
 
1908
        tmpdir = Var_Subst(NULL, "${TMPDIR:tA:U" _PATH_TMP "}/", VAR_GLOBAL, 0);
 
1909
        if (stat(tmpdir, &st) < 0 || !S_ISDIR(st.st_mode)) {
 
1910
            free(tmpdir);
 
1911
            tmpdir = bmake_strdup(_PATH_TMP);
 
1912
        }
 
1913
    }
 
1914
    return tmpdir;
 
1915
}
 
1916
 
 
1917
/*
 
1918
 * Create and open a temp file using "pattern".
 
1919
 * If "fnamep" is provided set it to a copy of the filename created.
 
1920
 * Otherwise unlink the file once open.
 
1921
 */
 
1922
int
 
1923
mkTempFile(const char *pattern, char **fnamep)
 
1924
{
 
1925
    static char *tmpdir = NULL;
 
1926
    char tfile[MAXPATHLEN];
 
1927
    int fd;
 
1928
    
 
1929
    if (!pattern)
 
1930
        pattern = TMPPAT;
 
1931
    if (!tmpdir)
 
1932
        tmpdir = getTmpdir();
 
1933
    if (pattern[0] == '/') {
 
1934
        snprintf(tfile, sizeof(tfile), "%s", pattern);
 
1935
    } else {
 
1936
        snprintf(tfile, sizeof(tfile), "%s%s", tmpdir, pattern);
 
1937
    }
 
1938
    if ((fd = mkstemp(tfile)) < 0)
 
1939
        Punt("Could not create temporary file %s: %s", tfile, strerror(errno));
 
1940
    if (fnamep) {
 
1941
        *fnamep = bmake_strdup(tfile);
 
1942
    } else {
 
1943
        unlink(tfile);                  /* we just want the descriptor */
 
1944
    }
 
1945
    return fd;
 
1946
}
 
1947
 
 
1948
 
 
1949
/*
 
1950
 * Return a Boolean based on setting of a knob.
 
1951
 *
 
1952
 * If the knob is not set, the supplied default is the return value.
 
1953
 * If set, anything that looks or smells like "No", "False", "Off", "0" etc,
 
1954
 * is FALSE, otherwise TRUE.
 
1955
 */
 
1956
Boolean
 
1957
getBoolean(const char *name, Boolean bf)
 
1958
{
 
1959
    char tmp[64];
 
1960
    char *cp;
 
1961
 
 
1962
    if (snprintf(tmp, sizeof(tmp), "${%s:tl}", name) < (int)(sizeof(tmp))) {
 
1963
        cp = Var_Subst(NULL, tmp, VAR_GLOBAL, 0);
 
1964
 
 
1965
        if (cp) {
 
1966
            switch(*cp) {
 
1967
            case '\0':                  /* not set - the default wins */
 
1968
                break;
 
1969
            case '0':
 
1970
            case 'f':
 
1971
            case 'n':
 
1972
                bf = FALSE;
 
1973
                break;
 
1974
            case 'o':
 
1975
                switch (cp[1]) {
 
1976
                case 'f':
 
1977
                    bf = FALSE;
 
1978
                    break;
 
1979
                default:
 
1980
                    bf = TRUE;
 
1981
                    break;
 
1982
                }
 
1983
                break;
 
1984
            default:
 
1985
                bf = TRUE;
 
1986
                break;
 
1987
            }
 
1988
            free(cp);
 
1989
        }
 
1990
    }
 
1991
    return (bf);
 
1992
}