cleanup exit status handling
[dragonfly.git] / usr.bin / make / main.c
1 /*-
2  * Copyright (c) 1988, 1989, 1990, 1993
3  *      The Regents of the University of California.  All rights reserved.
4  * Copyright (c) 1989 by Berkeley Softworks
5  * 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. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *      This product includes software developed by the University of
21  *      California, Berkeley and its contributors.
22  * 4. Neither the name of the University nor the names of its contributors
23  *    may be used to endorse or promote products derived from this software
24  *    without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36  * SUCH DAMAGE.
37  *
38  * @(#) Copyright (c) 1988, 1989, 1990, 1993 The Regents of the University of California.  All rights reserved.
39  * @(#)main.c   8.3 (Berkeley) 3/19/94
40  * $FreeBSD: src/usr.bin/make/main.c,v 1.118 2005/02/13 13:33:56 harti Exp $
41  * $DragonFly: src/usr.bin/make/main.c,v 1.119 2005/06/19 14:31:03 okumoto Exp $
42  */
43
44 /*
45  * main.c
46  *      The main file for this entire program. Exit routines etc
47  *      reside here.
48  *
49  * Utility functions defined in this file:
50  *      Main_ParseArgLine
51  *                      Takes a line of arguments, breaks them and
52  *                      treats them as if they were given when first
53  *                      invoked. Used by the parse module to implement
54  *                      the .MFLAGS target.
55  */
56
57 #ifndef MACHINE
58 #include <sys/utsname.h>
59 #endif
60 #include <sys/param.h>
61 #include <sys/stat.h>
62 #include <sys/time.h>
63 #include <sys/queue.h>
64 #include <sys/resource.h>
65 #include <sys/wait.h>
66 #include <err.h>
67 #include <errno.h>
68 #include <stdlib.h>
69 #include <string.h>
70 #include <unistd.h>
71
72 #include "arch.h"
73 #include "buf.h"
74 #include "config.h"
75 #include "dir.h"
76 #include "globals.h"
77 #include "job.h"
78 #include "make.h"
79 #include "parse.h"
80 #include "pathnames.h"
81 #include "shell.h"
82 #include "str.h"
83 #include "suff.h"
84 #include "targ.h"
85 #include "util.h"
86 #include "var.h"
87
88 extern char **environ;  /* XXX what header declares this variable? */
89
90 /*
91  * DEFMAXJOBS
92  *      This control the default concurrency. On no occasion will more
93  *      than DEFMAXJOBS targets be created at once.
94  */
95 #define DEFMAXJOBS      1
96
97 typedef struct MakeFlags {
98         /** ordered list of makefiles to read */
99         Lst makefiles;
100
101         /** list of variables to print */
102         Lst variables;
103
104         /** Targets to be made */
105         Lst create;
106
107         /** directories to search when looking for includes */
108         struct Path     parseIncPath;
109
110         /** directories to search when looking for system includes */
111         struct Path     sysIncPath;
112
113         Boolean expandVars;     /* fully expand printed variables */
114         Boolean builtins;       /* -r flag */
115         Boolean forceJobs;      /* -j argument given */
116
117         /**
118          * -q flag:
119          * TRUE if we aren't supposed to really make anything, just
120          * see if the targets are out-of-date
121          */
122         Boolean         queryFlag;
123 } MakeFlags;
124
125 /* (-E) vars to override from env */
126 Lst envFirstVars = Lst_Initializer(envFirstVars);
127
128 Boolean         allPrecious;    /* .PRECIOUS given on line by itself */
129 Boolean         beSilent;       /* -s flag */
130 Boolean         beVerbose;      /* -v flag */
131 Boolean         compatMake;     /* -B argument */
132 Boolean         debug;          /* -d flag */
133 Boolean         ignoreErrors;   /* -i flag */
134 int             jobLimit;       /* -j argument */
135 Boolean         jobsRunning;    /* TRUE if the jobs might be running */
136 Boolean         keepgoing;      /* -k flag */
137 Boolean         noExecute;      /* -n flag */
138 Boolean         touchFlag;      /* -t flag */
139 Boolean         usePipes;       /* !-P flag */
140 uint32_t        warn_cmd;       /* command line warning flags */
141 uint32_t        warn_flags;     /* actual warning flags */
142 uint32_t        warn_nocmd;     /* command line no-warning flags */
143
144 time_t          now;            /* Time at start of make */
145 struct GNode    *DEFAULT;       /* .DEFAULT node */
146
147
148 /**
149  * Exit with usage message.
150  */
151 static void
152 usage(void)
153 {
154         fprintf(stderr,
155             "usage: make [-BPSXeiknqrstv] [-C directory] [-D variable]\n"
156             "\t[-d flags] [-E variable] [-f makefile] [-I directory]\n"
157             "\t[-j max_jobs] [-m directory] [-V variable]\n"
158             "\t[variable=value] [target ...]\n");
159         exit(2);
160 }
161
162 /**
163  * MFLAGS_append
164  *      Append a flag with an optional argument to MAKEFLAGS and MFLAGS
165  */
166 static void
167 MFLAGS_append(const char *flag, char *arg)
168 {
169         char *str;
170
171         Var_Append(".MAKEFLAGS", flag, VAR_GLOBAL);
172         if (arg != NULL) {
173                 str = MAKEFLAGS_quote(arg);
174                 Var_Append(".MAKEFLAGS", str, VAR_GLOBAL);
175                 free(str);
176         }
177
178         Var_Append("MFLAGS", flag, VAR_GLOBAL);
179         if (arg != NULL) {
180                 str = MAKEFLAGS_quote(arg);
181                 Var_Append("MFLAGS", str, VAR_GLOBAL);
182                 free(str);
183         }
184 }
185
186 /**
187  * Open and parse the given makefile.
188  *
189  * Results:
190  *      TRUE if ok. FALSE if couldn't open file.
191  */
192 static Boolean
193 ReadMakefile(Parser *parser, MakeFlags *mf, const char file[], const char curdir[], const char objdir[])
194 {
195         char    path[MAXPATHLEN];
196         FILE    *stream;
197         char    *fname;
198         char    *name;
199
200         if (!strcmp(file, "-")) {
201                 Parse_File(parser, mf, "(stdin)", stdin);
202                 Var_SetGlobal("MAKEFILE", "");
203                 return (TRUE);
204         }
205
206         if (strcmp(curdir, objdir) == 0 || file[0] == '/') {
207                 strcpy(path, file);
208         } else {
209                 /*
210                  * we've chdir'd, rebuild the path name
211                  */
212                 snprintf(path, MAXPATHLEN, "%s/%s", curdir, file);
213         }
214 #if THIS_BREAKS_THINGS
215         /*
216          * XXX The realpath stuff breaks relative includes
217          * XXX in some cases.   The problem likely is in
218          * XXX parse.c where it does special things in
219          * XXX ParseDoInclude if the file is relateive
220          * XXX or absolute and not a system file.  There
221          * XXX it assumes that if the current file that's
222          * XXX being included is absolute, that any files
223          * XXX that it includes shouldn't do the -I path
224          * XXX stuff, which is inconsistant with historical
225          * XXX behavior.  However, I can't pentrate the mists
226          * XXX further, so I'm putting this workaround in
227          * XXX here until such time as the underlying bug
228          * XXX can be fixed.
229          */
230         if (realpath(path, path) == NULL) {
231                 stream = NULL;
232         } else {
233                 stream = fopen(path, "r");
234         }
235 #else
236         stream = fopen(path, "r");
237 #endif
238         if (stream != NULL) {
239                 if (strcmp(file, ".depend") != 0)
240                         Var_SetGlobal("MAKEFILE", file);
241                 Parse_File(parser, mf, path, stream);
242                 fclose(stream);
243                 return (TRUE);
244         }
245
246         /* look in -I and system include directories. */
247         fname = estrdup(file);
248         name = NULL;
249         if (name == NULL)
250                 name = Path_FindFile(fname, &mf->parseIncPath);
251         if (name == NULL)
252                 name = Path_FindFile(fname, &mf->sysIncPath);
253
254         if (name != NULL) {
255                 stream = fopen(name, "r");
256                 if (stream != NULL) {
257                         /*
258                          * set the MAKEFILE variable desired by System V fans
259                          * -- the placement of the setting here means it gets
260                          * set to the last makefile specified, as it is set
261                          * by SysV make.
262                          */
263                         if (strcmp(file, ".depend") != 0)
264                                 Var_SetGlobal("MAKEFILE", name);
265                         Parse_File(parser, mf, name, stream);
266                         fclose(stream);
267                         return (TRUE);
268                 }
269         }
270
271         return (FALSE); /* no makefile found */
272 }
273
274 /**
275  * Read in the built-in rules first, followed by the specified
276  * makefiles or the one of the default makefiles.  Finally .depend
277  * makefile.
278  */
279 static void
280 ReadInputFiles(Parser *parser, MakeFlags *mf, const char curdir[], const char objdir[])
281 {
282         if (mf->builtins) {
283                 /* Path of sys.mk */
284                 Lst     sysMkPath = Lst_Initializer(sysMkPath);
285                 LstNode *ln;
286                 char    defsysmk[] = PATH_DEFSYSMK;
287
288                 Path_Expand(defsysmk, &mf->sysIncPath, &sysMkPath);
289                 if (Lst_IsEmpty(&sysMkPath))
290                         Fatal("make: no system rules (%s).", PATH_DEFSYSMK);
291                 LST_FOREACH(ln, &sysMkPath) {
292                         if (!ReadMakefile(parser, mf, Lst_Datum(ln), curdir, objdir))
293                                 break;
294                 }
295                 if (ln != NULL)
296                         Fatal("make: cannot open %s.", (char *)Lst_Datum(ln));
297                 Lst_Destroy(&sysMkPath, free);
298         }
299
300         if (!Lst_IsEmpty(&mf->makefiles)) {
301                 LstNode *ln;
302
303                 LST_FOREACH(ln, &mf->makefiles) {
304                         if (!ReadMakefile(parser, mf, Lst_Datum(ln), curdir, objdir))
305                                 break;
306                 }
307                 if (ln != NULL)
308                         Fatal("make: cannot open %s.", (char *)Lst_Datum(ln));
309         } else if (ReadMakefile(parser, mf, "BSDmakefile", curdir, objdir)) {
310                 /* read BSDmakefile */
311         } else if (ReadMakefile(parser, mf, "makefile", curdir, objdir)) {
312                 /* read makefile */
313         } else if (ReadMakefile(parser, mf, "Makefile", curdir, objdir)) {
314                 /* read Makefile */
315         } else {
316                 /* No Makefile found */
317         }
318
319         ReadMakefile(parser, mf, ".depend", curdir, objdir);
320 }
321
322 /**
323  * Main_ParseWarn
324  *
325  *      Handle argument to warning option.
326  */
327 int
328 Main_ParseWarn(const char *arg, int iscmd)
329 {
330         int i, neg;
331
332         static const struct {
333                 const char      *option;
334                 uint32_t        flag;
335         } options[] = {
336                 { "dirsyntax",  WARN_DIRSYNTAX },
337                 { NULL,         0 }
338         };
339
340         neg = 0;
341         if (arg[0] == 'n' && arg[1] == 'o') {
342                 neg = 1;
343                 arg += 2;
344         }
345
346         for (i = 0; options[i].option != NULL; i++)
347                 if (strcmp(arg, options[i].option) == 0)
348                         break;
349
350         if (options[i].option == NULL)
351                 /* unknown option */
352                 return (-1);
353
354         if (iscmd) {
355                 if (!neg) {
356                         warn_cmd |= options[i].flag;
357                         warn_nocmd &= ~options[i].flag;
358                         warn_flags |= options[i].flag;
359                 } else {
360                         warn_nocmd |= options[i].flag;
361                         warn_cmd &= ~options[i].flag;
362                         warn_flags &= ~options[i].flag;
363                 }
364         } else {
365                 if (!neg) {
366                         warn_flags |= (options[i].flag & ~warn_nocmd);
367                 } else {
368                         warn_flags &= ~(options[i].flag | warn_cmd);
369                 }
370         }
371         return (0);
372 }
373
374 /**
375  * MainParseArgs
376  *      Parse a given argument vector. Called from main() and from
377  *      Main_ParseArgLine() when the .MAKEFLAGS target is used.
378  *
379  *      XXX: Deal with command line overriding .MAKEFLAGS in makefile
380  *
381  * Side Effects:
382  *      Various global and local flags will be set depending on the flags
383  *      given
384  */
385 static void
386 MainParseArgs(MakeFlags *mf, int argc, char **argv)
387 {
388         int c;
389         Boolean found_dd = FALSE;
390
391 rearg:
392         optind = 1;     /* since we're called more than once */
393         optreset = 1;
394 #define OPTFLAGS "ABC:D:E:I:PSV:Xd:ef:ij:km:nqrstvx:"
395         for (;;) {
396                 if ((optind < argc) && strcmp(argv[optind], "--") == 0) {
397                         found_dd = TRUE;
398                 }
399                 if ((c = getopt(argc, argv, OPTFLAGS)) == -1) {
400                         break;
401                 }
402                 switch(c) {
403
404                 case 'A':
405                         arch_fatal = FALSE;
406                         MFLAGS_append("-A", NULL);
407                         break;
408                 case 'C':
409                         if (chdir(optarg) == -1)
410                                 err(1, "chdir %s", optarg);
411                         break;
412                 case 'D':
413                         Var_SetGlobal(optarg, "1");
414                         MFLAGS_append("-D", optarg);
415                         break;
416                 case 'I':
417                         Path_AddDir(&mf->parseIncPath, optarg);
418                         MFLAGS_append("-I", optarg);
419                         break;
420                 case 'V':
421                         Lst_AtEnd(&mf->variables, estrdup(optarg));
422                         MFLAGS_append("-V", optarg);
423                         break;
424                 case 'X':
425                         mf->expandVars = FALSE;
426                         break;
427                 case 'B':
428                         compatMake = TRUE;
429                         MFLAGS_append("-B", NULL);
430                         unsetenv("MAKE_JOBS_FIFO");
431                         break;
432                 case 'P':
433                         usePipes = FALSE;
434                         MFLAGS_append("-P", NULL);
435                         break;
436                 case 'S':
437                         keepgoing = FALSE;
438                         MFLAGS_append("-S", NULL);
439                         break;
440                 case 'd': {
441                         char *modules = optarg;
442
443                         for (; *modules; ++modules)
444                                 switch (*modules) {
445                                 case 'A':
446                                         debug = ~0;
447                                         break;
448                                 case 'a':
449                                         debug |= DEBUG_ARCH;
450                                         break;
451                                 case 'c':
452                                         debug |= DEBUG_COND;
453                                         break;
454                                 case 'd':
455                                         debug |= DEBUG_DIR;
456                                         break;
457                                 case 'f':
458                                         debug |= DEBUG_FOR;
459                                         break;
460                                 case 'g':
461                                         if (modules[1] == '1') {
462                                                 debug |= DEBUG_GRAPH1;
463                                                 ++modules;
464                                         }
465                                         else if (modules[1] == '2') {
466                                                 debug |= DEBUG_GRAPH2;
467                                                 ++modules;
468                                         }
469                                         break;
470                                 case 'j':
471                                         debug |= DEBUG_JOB;
472                                         break;
473                                 case 'l':
474                                         debug |= DEBUG_LOUD;
475                                         break;
476                                 case 'm':
477                                         debug |= DEBUG_MAKE;
478                                         break;
479                                 case 's':
480                                         debug |= DEBUG_SUFF;
481                                         break;
482                                 case 't':
483                                         debug |= DEBUG_TARG;
484                                         break;
485                                 case 'v':
486                                         debug |= DEBUG_VAR;
487                                         break;
488                                 default:
489                                         warnx("illegal argument to d option "
490                                             "-- %c", *modules);
491                                         usage();
492                                 }
493                         MFLAGS_append("-d", optarg);
494                         break;
495                 }
496                 case 'E':
497                         Lst_AtEnd(&envFirstVars, estrdup(optarg));
498                         MFLAGS_append("-E", optarg);
499                         break;
500                 case 'e':
501                         checkEnvFirst = TRUE;
502                         MFLAGS_append("-e", NULL);
503                         break;
504                 case 'f':
505                         Lst_AtEnd(&mf->makefiles, estrdup(optarg));
506                         break;
507                 case 'i':
508                         ignoreErrors = TRUE;
509                         MFLAGS_append("-i", NULL);
510                         break;
511                 case 'j': {
512                         char *endptr;
513
514                         mf->forceJobs = TRUE;
515                         jobLimit = strtol(optarg, &endptr, 10);
516                         if (jobLimit <= 0 || *endptr != '\0') {
517                                 warnx("illegal number, -j argument -- %s",
518                                     optarg);
519                                 usage();
520                         }
521                         MFLAGS_append("-j", optarg);
522                         break;
523                 }
524                 case 'k':
525                         keepgoing = TRUE;
526                         MFLAGS_append("-k", NULL);
527                         break;
528                 case 'm':
529                         Path_AddDir(&mf->sysIncPath, optarg);
530                         MFLAGS_append("-m", optarg);
531                         break;
532                 case 'n':
533                         noExecute = TRUE;
534                         MFLAGS_append("-n", NULL);
535                         break;
536                 case 'q':
537                         mf->queryFlag = TRUE;
538                         /* Kind of nonsensical, wot? */
539                         MFLAGS_append("-q", NULL);
540                         break;
541                 case 'r':
542                         mf->builtins = FALSE;
543                         MFLAGS_append("-r", NULL);
544                         break;
545                 case 's':
546                         beSilent = TRUE;
547                         MFLAGS_append("-s", NULL);
548                         break;
549                 case 't':
550                         touchFlag = TRUE;
551                         MFLAGS_append("-t", NULL);
552                         break;
553                 case 'v':
554                         beVerbose = TRUE;
555                         MFLAGS_append("-v", NULL);
556                         break;
557                 case 'x':
558                         if (Main_ParseWarn(optarg, 1) != -1)
559                                 MFLAGS_append("-x", optarg);
560                         break;
561                 default:
562                 case '?':
563                         usage();
564                 }
565         }
566         argv += optind;
567         argc -= optind;
568
569         oldVars = TRUE;
570
571         /*
572          * Parse the rest of the arguments.
573          *      o Check for variable assignments and perform them if so.
574          *      o Check for more flags and restart getopt if so.
575          *      o Anything else is taken to be a target and added
576          *        to the end of the "create" list.
577          */
578         for (; *argv != NULL; ++argv, --argc) {
579                 if (Parse_IsVar(*argv)) {
580                         char *ptr = MAKEFLAGS_quote(*argv);
581
582                         Var_Append(".MAKEFLAGS", ptr, VAR_GLOBAL);
583                         Parse_DoVar(*argv, VAR_CMD);
584                         free(ptr);
585
586                 } else if ((*argv)[0] == '-') {
587                         if ((*argv)[1] == '\0') {
588                                 /*
589                                  * (*argv) is a single dash, so we
590                                  * just ignore it.
591                                  */
592                         } else if (found_dd) {
593                                 /*
594                                  * Double dash has been found, ignore
595                                  * any more options.  But what do we do
596                                  * with it?  For now treat it like a target.
597                                  */
598                                 Lst_AtEnd(&mf->create, estrdup(*argv));
599                         } else {
600                                 /*
601                                  * (*argv) is a -flag, so backup argv and
602                                  * argc.  getopt() expects options to start
603                                  * in the 2nd position.
604                                  */
605                                 argc++;
606                                 argv--;
607                                 goto rearg;
608                         }
609
610                 } else if ((*argv)[0] == '\0') {
611                         Punt("illegal (null) argument.");
612
613                 } else {
614                         Lst_AtEnd(&mf->create, estrdup(*argv));
615                 }
616         }
617 }
618
619 /**
620  * Main_ParseArgLine
621  *      Used by the parse module when a .MFLAGS or .MAKEFLAGS target
622  *      is encountered and by main() when reading the .MAKEFLAGS envariable.
623  *      Takes a line of arguments and breaks it into its
624  *      component words and passes those words and the number of them to the
625  *      MainParseArgs function.
626  *      The line should have all its leading whitespace removed.
627  *
628  * Side Effects:
629  *      Only those that come from the various arguments.
630  */
631 void
632 Main_ParseArgLine(MakeFlags *mf, char line[], int mflags)
633 {
634         ArgArray        aa;
635
636         if (line == NULL)
637                 return;
638         for (; *line == ' '; ++line)
639                 continue;
640         if (!*line)
641                 return;
642
643         if (mflags) {
644                 MAKEFLAGS_break(&aa, line);
645         } else {
646                 brk_string(&aa, line, TRUE);
647         }
648         MainParseArgs(mf, aa.argc, aa.argv);
649         ArgArray_Done(&aa);
650 }
651
652 /**
653  * Try to change the current working directory to path, and return
654  * the whole path using getcwd().
655  *
656  * @note for amd managed mount points we really should use pawd(1).
657  */
658 static int
659 chdir_verify_path(const char path[], char newdir[])
660 {
661         struct stat sb;
662
663         /*
664          * Check if the path is a directory.  If not fail without reporting
665          * an error.
666          */
667         if (stat(path, &sb) < 0) {
668                 return (0);
669         }
670         if (S_ISDIR(sb.st_mode) == 0) {
671                 return (0);
672         }
673
674         /*
675          * The path refers to a directory, so we try to change into it. If we
676          * fail, or we fail to obtain the path from root to the directory,
677          * then report an error and fail.
678          */
679         if (chdir(path) < 0) {
680                 warn("warning: %s", path);
681                 return (0);
682         }
683         if (getcwd(newdir, MAXPATHLEN) == NULL) {
684                 warn("warning: %s", path);
685                 return (0);
686         }
687         return (1);
688 }
689
690 static void
691 determine_objdir(const char machine[], char curdir[], char objdir[])
692 {
693         struct stat     sa;
694         char            newdir[MAXPATHLEN];
695         char            mdpath[MAXPATHLEN];
696         const char      *env;
697
698         /*
699          * Find a path to where we are... [-C directory] might have changed
700          * our current directory.
701          */
702         if (getcwd(curdir, MAXPATHLEN) == NULL)
703                 err(2, NULL);
704
705         if (stat(curdir, &sa) == -1)
706                 err(2, "%s", curdir);
707
708         /*
709          * The object directory location is determined using the
710          * following order of preference:
711          *
712          *      1. MAKEOBJDIRPREFIX`cwd`
713          *      2. MAKEOBJDIR
714          *      3. PATH_OBJDIR.${MACHINE}
715          *      4. PATH_OBJDIR
716          *      5. PATH_OBJDIRPREFIX`cwd`
717          *
718          * If one of the first two fails, use the current directory.
719          * If the remaining three all fail, use the current directory.
720          */
721         if ((env = getenv("MAKEOBJDIRPREFIX")) != NULL) {
722                 snprintf(mdpath, MAXPATHLEN, "%s%s", env, curdir);
723                 if (chdir_verify_path(mdpath, newdir)) {
724                         strcpy(objdir, newdir);
725                         return;
726                 }
727                 strcpy(objdir, curdir);
728                 return;
729         }
730
731         if ((env = getenv("MAKEOBJDIR")) != NULL) {
732                 if (chdir_verify_path(env, newdir)) {
733                         strcpy(objdir, newdir);
734                         return;
735                 }
736                 strcpy(objdir, curdir);
737                 return;
738         }
739
740         snprintf(mdpath, MAXPATHLEN, "%s.%s", PATH_OBJDIR, machine);
741         if (chdir_verify_path(mdpath, newdir)) {
742                 strcpy(objdir, newdir);
743                 return;
744         }
745
746         if (chdir_verify_path(PATH_OBJDIR, newdir)) {
747                 strcpy(objdir, newdir);
748                 return;
749         }
750
751         snprintf(mdpath, MAXPATHLEN, "%s%s", PATH_OBJDIRPREFIX, curdir);
752         if (chdir_verify_path(mdpath, newdir)) {
753                 strcpy(objdir, newdir);
754                 return;
755         }
756
757         strcpy(objdir, curdir);
758 }
759
760 /**
761  * Initialize various make variables.
762  *      MAKE also gets this name, for compatibility
763  *      .MAKEFLAGS gets set to the empty string just in case.
764  *      MFLAGS also gets initialized empty, for compatibility.
765  */
766 static void
767 InitVariables(MakeFlags *mf, int argc, char *argv[], char curdir[], char objdir[])
768 {
769         const char      *machine;
770         const char      *machine_arch;
771         const char      *machine_cpu;
772
773
774         Var_Init(environ);
775
776         Var_SetGlobal("MAKE", argv[0]);
777         Var_SetGlobal(".MAKEFLAGS", "");
778         Var_SetGlobal("MFLAGS", "");
779
780         Var_SetGlobal(".DIRECTIVE_MAKEENV", "YES");
781         Var_SetGlobal(".ST_EXPORTVAR", "YES");
782 #ifdef MAKE_VERSION
783         Var_SetGlobal("MAKE_VERSION", MAKE_VERSION);
784 #endif
785
786         /*
787          * Get the name of this type of MACHINE from utsname
788          * so we can share an executable for similar machines.
789          * (i.e. m68k: amiga hp300, mac68k, sun3, ...)
790          *
791          * Note that while MACHINE is decided at run-time,
792          * MACHINE_ARCH is always known at compile time.
793          */
794         if ((machine = getenv("MACHINE")) == NULL) {
795 #ifdef MACHINE
796                 machine = MACHINE;
797 #else
798                 static struct utsname   utsname;
799                 if (uname(&utsname) == -1)
800                         err(2, "uname");
801                 machine = utsname.machine;
802 #endif
803         }
804
805         if ((machine_arch = getenv("MACHINE_ARCH")) == NULL) {
806 #ifdef MACHINE_ARCH
807                 machine_arch = MACHINE_ARCH;
808 #else
809                 machine_arch = "unknown";
810 #endif
811         }
812
813         /*
814          * Set machine_cpu to the minumum supported CPU revision based
815          * on the target architecture, if not already set.
816          */
817         if ((machine_cpu = getenv("MACHINE_CPU")) == NULL) {
818                 if (!strcmp(machine_arch, "i386"))
819                         machine_cpu = "i386";
820                 else if (!strcmp(machine_arch, "alpha"))
821                         machine_cpu = "ev4";
822                 else
823                         machine_cpu = "unknown";
824         }
825
826         Var_SetGlobal("MACHINE", machine);
827         Var_SetGlobal("MACHINE_ARCH", machine_arch);
828         Var_SetGlobal("MACHINE_CPU", machine_cpu);
829
830         /*
831          * First snag things out of the MAKEFLAGS environment
832          * variable.  Then parse the command line arguments.
833          */
834         Main_ParseArgLine(mf, getenv("MAKEFLAGS"), 1);
835
836         MainParseArgs(mf, argc, argv);
837
838         determine_objdir(machine, curdir, objdir);
839         Var_SetGlobal(".CURDIR", curdir);
840         Var_SetGlobal(".OBJDIR", objdir);
841
842         /*
843          * Set up the .TARGETS variable to contain the list of targets to be
844          * created. If none specified, make the variable empty -- the parser
845          * will fill the thing in with the default or .MAIN target.
846          */
847         if (Lst_IsEmpty(&mf->create)) {
848                 Var_SetGlobal(".TARGETS", "");
849         } else {
850                 LstNode *ln;
851
852                 for (ln = Lst_First(&mf->create); ln != NULL; ln = Lst_Succ(ln)) {
853                         char *name = Lst_Datum(ln);
854
855                         Var_Append(".TARGETS", name, VAR_GLOBAL);
856                 }
857         }
858 }
859
860 static int
861 build_stuff(MakeFlags *mf)
862 {
863         Boolean outOfDate;      /* FALSE if all targets up to date */
864
865         /*
866          * Build targets.
867          *
868          * We have read the entire graph and need to make
869          * a list of targets to create.  If none were given
870          * on the command line, we consult the parsing
871          * module to find the main target(s) to create.
872          */
873         Lst targs = Lst_Initializer(targs);
874
875         if (Lst_IsEmpty(&mf->create))
876                 Parse_MainName(&targs);
877         else
878                 Targ_FindList(&targs, &mf->create, TARG_CREATE);
879
880         /* Traverse the graph, checking on all the targets */
881         if (compatMake) {
882                 outOfDate = Compat_Run(&targs, mf->queryFlag);
883         } else {
884                 outOfDate = Make_Run(&targs, mf->queryFlag);
885         }
886         Lst_Destroy(&targs, NOFREE);
887
888         return (mf->queryFlag && outOfDate) ? 1 : 0;
889 }
890
891 /**
892  * main
893  *      The main function, for obvious reasons. Initializes variables
894  *      and a few modules, then parses the arguments give it in the
895  *      environment and on the command line. Reads the system makefile
896  *      followed by either Makefile, makefile or the file given by the
897  *      -f argument. Sets the .MAKEFLAGS PMake variable based on all the
898  *      flags it has received by then uses either the Make or the Compat
899  *      module to create the initial list of targets.
900  *
901  * Results:
902  *      If -q was given, exits -1 if anything was out-of-date. Else it exits
903  *      0.
904  *
905  * Side Effects:
906  *      The program exits when done. Targets are created. etc. etc. etc.
907  */
908 int
909 main(int argc, char **argv)
910 {
911         MakeFlags       mf;
912         Parser          parser;
913         int             status;         /* exit status */
914         char            curdir[MAXPATHLEN];     /* startup directory */
915         char            objdir[MAXPATHLEN];     /* where we chdir'ed to */
916
917         /*------------------------------------------------------------*
918          * This section initializes variables that require no input.
919          *------------------------------------------------------------*/
920         /*
921          * Initialize program global variables.
922          */
923         beSilent = FALSE;               /* Print commands as executed */
924         ignoreErrors = FALSE;           /* Pay attention to non-zero returns */
925         noExecute = FALSE;              /* Execute all commands */
926         keepgoing = FALSE;              /* Stop on error */
927         allPrecious = FALSE;            /* Remove targets when interrupted */
928         touchFlag = FALSE;              /* Actually update targets */
929         usePipes = TRUE;                /* Catch child output in pipes */
930         debug = 0;                      /* No debug verbosity, please. */
931         jobsRunning = FALSE;
932
933         jobLimit = DEFMAXJOBS;
934         compatMake = FALSE;             /* No compat mode */
935
936         /*
937          * Initialize make flags variable.
938          */
939         Lst_Init(&mf.makefiles);
940         Lst_Init(&mf.variables);
941         Lst_Init(&mf.create);
942         TAILQ_INIT(&mf.parseIncPath);
943         TAILQ_INIT(&mf.sysIncPath);
944
945         mf.expandVars = TRUE;
946         mf.builtins = TRUE;             /* Read the built-in rules */
947         mf.queryFlag = FALSE;
948
949         /*------------------------------------------------------------*
950          * This section initializes variables that depend on things
951          * in the enviornment, command line, or a input file.
952          *------------------------------------------------------------*/
953         if (getenv("MAKE_JOBS_FIFO") == NULL)
954                 mf.forceJobs = FALSE;
955         else
956                 mf.forceJobs = TRUE;
957
958         parser.create = &mf.create;
959         parser.parseIncPath = &mf.parseIncPath;
960         parser.sysIncPath = &mf.sysIncPath;
961
962         /*
963          * Initialize the parsing, directory and variable modules to prepare
964          * for the reading of inclusion paths and variable settings on the
965          * command line
966          */
967         Proc_Init();
968         Shell_Init(DEFSHELLNAME);
969
970         InitVariables(&mf, argc, argv, curdir, objdir);
971
972         /*
973          * Once things are initialized, add the original directory to the
974          * search path. The current directory is also placed as a variable
975          * for make scripts.
976          */
977
978         Dir_Init();
979         Dir_InitDot();          /* Initialize the "." directory */
980
981         if (strcmp(objdir, curdir) != 0)
982                 Path_AddDir(&dirSearchPath, curdir);
983
984         /*
985          * Be compatible if user did not specify -j and did not explicitly
986          * turned compatibility on
987          */
988         if (!compatMake && !mf.forceJobs)
989                 compatMake = TRUE;
990
991         /*
992          * Initialize target and suffix modules in preparation for
993          * parsing the makefile(s)
994          */
995         Targ_Init();
996         Suff_Init();
997
998         DEFAULT = NULL;
999         time(&now);
1000
1001         /*
1002          * If no user-supplied system path was given (through the -m option)
1003          * add the directories from the DEFSYSPATH (more than one may be given
1004          * as dir1:...:dirn) to the system include path.
1005          */
1006         if (TAILQ_EMPTY(&mf.sysIncPath)) {
1007                 char syspath[] = PATH_DEFSYSPATH;
1008                 char *cp = NULL;
1009                 char *start;
1010
1011                 for (start = syspath; *start != '\0'; start = cp) {
1012                         for (cp = start; *cp != '\0' && *cp != ':'; cp++)
1013                                 continue;
1014                         if (*cp == '\0') {
1015                                 Path_AddDir(&mf.sysIncPath, start);
1016                         } else {
1017                                 *cp++ = '\0';
1018                                 Path_AddDir(&mf.sysIncPath, start);
1019                         }
1020                 }
1021         }
1022
1023         ReadInputFiles(&parser, &mf, curdir, objdir);
1024
1025         /*------------------------------------------------------------*
1026          * We are finished processing inputs.
1027          *------------------------------------------------------------*/
1028
1029         /* Install all the flags into the MAKE envariable. */
1030         {
1031                 const char *p;
1032
1033                 if (((p = Var_Value(".MAKEFLAGS", VAR_GLOBAL)) != NULL) && *p)
1034                         setenv("MAKEFLAGS", p, 1);
1035         }
1036
1037         /*
1038          * For compatibility, look at the directories in the VPATH variable
1039          * and add them to the search path, if the variable is defined. The
1040          * variable's value is in the same format as the PATH envariable, i.e.
1041          * <directory>:<directory>:<directory>...
1042          */
1043         if (Var_Exists("VPATH", VAR_CMD)) {
1044                 Buffer  *buf;
1045                 char    *vpath;
1046                 char    savec;
1047
1048                 buf = Var_Subst("${VPATH}", VAR_CMD, FALSE);
1049                 vpath = Buf_Data(buf);
1050                 do {
1051                         char    *ptr;
1052                         /* skip to end of directory */
1053                         for (ptr = vpath; *ptr != ':' && *ptr != '\0'; ptr++)
1054                                 ;
1055
1056                         /* Save terminator character so know when to stop */
1057                         savec = *ptr;
1058                         *ptr = '\0';
1059
1060                         /* Add directory to search path */
1061                         Path_AddDir(&dirSearchPath, vpath);
1062
1063                         vpath = ptr + 1;
1064                 } while (savec != '\0');
1065
1066                 Buf_Destroy(buf, TRUE);
1067         }
1068
1069         /*
1070          * Now that all search paths have been read for suffixes et al, it's
1071          * time to add the default search path to their lists...
1072          */
1073         Suff_DoPaths();
1074
1075         /* print the initial graph, if the user requested it */
1076         if (DEBUG(GRAPH1))
1077                 Targ_PrintGraph(1);
1078
1079         if (Lst_IsEmpty(&mf.variables)) {
1080                 status = build_stuff(&mf);
1081         } else {
1082                 /* Print the values of variables requested by the user. */
1083                 Var_Print(&mf.variables, mf.expandVars);
1084
1085                 /*
1086                  * XXX
1087                  * This should be a "don't care", we do not check
1088                  * the status of any files.  It might make sense to
1089                  * modify Var_Print() to indicate that one of the
1090                  * requested variables did not exist, and use that
1091                  * as the return status.
1092                  * XXX
1093                  */
1094                 status = mf.queryFlag ? 1 : 0;
1095         }
1096
1097         /* print the graph now it's been processed if the user requested it */
1098         if (DEBUG(GRAPH2))
1099                 Targ_PrintGraph(2);
1100
1101 #if 0
1102         TAILQ_DESTROY(&mf.sysIncPath);
1103         TAILQ_DESTROY(&mf.parseIncPath);
1104 #endif
1105         Lst_Destroy(&mf.create, free);
1106         Lst_Destroy(&mf.makefiles, free);
1107         Lst_Destroy(&mf.variables, free);
1108
1109         return (status);
1110 }
1111