1 /* @(#)make.c 1.228 21/08/20 Copyright 1985, 87, 88, 91, 1995-2021 J. Schilling */
2 #include <schily/mconfig.h>
3 #ifndef lint
4 static UConst char sccsid[] =
5 "@(#)make.c 1.228 21/08/20 Copyright 1985, 87, 88, 91, 1995-2021 J. Schilling";
6 #endif
7 /*
8 * Make program
9 *
10 * Copyright (c) 1985, 87, 88, 91, 1995-2021 by J. Schilling
11 */
12 /*
13 * The contents of this file are subject to the terms of the
14 * Common Development and Distribution License, Version 1.0 only
15 * (the "License"). You may not use this file except in compliance
16 * with the License.
17 *
18 * See the file CDDL.Schily.txt in this distribution for details.
19 * A copy of the CDDL is also available via the Internet at
20 * http://www.opensource.org/licenses/cddl1.txt
21 *
22 * When distributing Covered Code, include this CDDL HEADER in each
23 * file and include the License file CDDL.Schily.txt from this distribution.
24 */
25
26 #include <schily/stdio.h>
27 #include <schily/standard.h>
28 #include <schily/getargs.h>
29 #include <schily/errno.h>
30 #include <schily/fcntl.h>
31 #include <schily/stdlib.h>
32 #include <schily/string.h>
33 #include <schily/unistd.h>
34 #include <schily/time.h>
35 #include <schily/signal.h>
36
37 #include <schily/dirent.h>
38 #include <schily/maxpath.h>
39 #include <schily/getcwd.h>
40 #ifdef USE_NLS
41 #define GT_COMERR /* #define comerr gtcomerr */
42 #define GT_ERROR /* #define error gterror */
43 #else
44 #define NO_NLS
45 #endif
46 #include <schily/schily.h>
47 #include <schily/libport.h>
48 #include <schily/utime.h>
49 #include <schily/nlsdefs.h>
50
51 #include "make.h"
52 #include "job.h"
53 #include "version.h"
54
55 #ifndef USE_NLS
56 #undef gtprintf
57 #define gtprintf printf
58 #endif
59
60 char make_version[] = VERSION;
61
62 #ifdef NO_DEFAULTS_PATH
63 #undef DEFAULTS_PATH
64 #define DEFAULTS_PATH_SEARCH_FIRST
65 #endif
66
67 #ifdef _FASCII
68 LOCAL void setup_env __PR((void));
69 #endif
70 EXPORT void usage __PR((int exitcode));
71 LOCAL void initmakefiles __PR((void));
72 LOCAL int dochdir __PR((char *name));
73 LOCAL int addmakefile __PR((char *name));
74 LOCAL void read_defs __PR((void));
75 LOCAL void read_makefiles __PR((void));
76 EXPORT void setup_dotvars __PR((void));
77 LOCAL void setup_vars __PR((void));
78 LOCAL void setup_MAKE __PR((char *name));
79 EXPORT char *searchtype __PR((int mode));
80 LOCAL void printdirs __PR((void));
81 LOCAL int addcommandline __PR((char * name));
82 LOCAL void addcmdlinedef __PR((char * name));
83 LOCAL void scan_cmdline __PR((int ac, char **av));
84 LOCAL void read_cmdline __PR((void));
85 EXPORT void doexport __PR((char *));
86 EXPORT void dounexport __PR((char *));
87 LOCAL void read_environ __PR((void));
88 EXPORT int main __PR((int ac, char ** av));
89 LOCAL void check_old_makefiles __PR((void));
90 LOCAL void getmakeflags __PR((void));
91 LOCAL void read_makemacs __PR((void));
92 LOCAL char *nextmakemac __PR((char *s));
93 LOCAL BOOL read_mac __PR((char *mf));
94 LOCAL void setmakeflags __PR((void));
95 LOCAL char *stripmacros __PR((char *macbase, char *new));
96 LOCAL void setmakeenv __PR((char *envbase, char *envp));
97 EXPORT BOOL move_tgt __PR((obj_t * from));
98 LOCAL int copy_file __PR((char * from, char * objname));
99 EXPORT BOOL touch_file __PR((char * name));
100 LOCAL date_t gcurtime __PR((void));
101 LOCAL date_t gnewtime __PR((void));
102 EXPORT date_t gftime __PR((char * file));
103 LOCAL BOOL isdir __PR((char * file));
104 EXPORT Llong gfileid __PR((char * file));
105 EXPORT char *prtime __PR((date_t date));
106 LOCAL void handler __PR((int signo));
107 LOCAL void exhandler __PR((int excode, void *arg));
108 EXPORT char *curwdir __PR((void));
109 LOCAL char *getdefaultsfile __PR((void));
110 LOCAL int put_env __PR((char *new));
111 LOCAL int unset_env __PR((char *name));
112
113 BOOL posixmode = FALSE; /* We found a .POSIX target */
114 BOOL Aflag = FALSE; /* -a Do not run setup_arch() */
115 BOOL Eflag = FALSE; /* -e Environment overrides vars*/
116 BOOL Iflag = FALSE; /* -i Ignore command errors */
117 BOOL Kflag = FALSE; /* -k Continue on unrelated tgts */
118 BOOL Stopflag = FALSE; /* -S Stop on make errors */
119 BOOL NSflag = FALSE; /* -N Ignore no Source on dep. */
120 BOOL Nflag = FALSE; /* -n Only show what to do */
121 BOOL Qflag = FALSE; /* -q If up to date exit (0) */
122 BOOL Rflag = FALSE; /* -r Turn off internal rules */
123 BOOL Sflag = FALSE; /* -s Be silent */
124 BOOL Tflag = FALSE; /* -t Touch objects */
125 int Mlevel = 0; /* MAKE_LEVEL from environment */
126 int Debug = 0; /* -d Print reason for rebuild */
127 int XDebug = 0; /* -xd Print extended debug info*/
128 BOOL Prdep = FALSE; /* -xM Print include dependency */
129 BOOL Pr_obj = FALSE; /* -probj Print object tree */
130 BOOL Print = FALSE; /* -p Print macro/target definitions*/
131 int Dmake = 0; /* -D Display makefile */
132 BOOL help = FALSE; /* -help Show Usage */
133 BOOL pversion = FALSE; /* -version Show version string */
134 BOOL No_Warn = FALSE; /* -w No warnings */
135 int Do_Warn = 0; /* -W Print extra warnings */
136 char Makeflags[] = "MAKEFLAGS";
137 char Make_Flags[] = "MAKE_FLAGS";
138 char Make_Macs[] = "MAKE_MACS";
139 char Make_Level[] = "MAKE_LEVEL";
140 char Envdefs[] = "Environment defs";
141 char Makedefs[] = "Internal Makefile";
142 char Ldefaults[] = "defaults.smk";
143 #ifdef SVR4
144 char Defaults[] = "/opt/schily/share/lib/smake/defaults.smk";
145 #else
146 char Defaults[] = "/usr/bert/share/lib/smake/defaults.smk";
147 #endif
148 #define MAKEFILECOUNT 32 /* Max number of Makefiles */
149 char SMakefile[] = "SMakefile"; /* smake's default Makefile */
150 char Makefile[] = "Makefile"; /* Primary default Makefile */
151 char _makefile[] = "makefile"; /* Secondary default Makefile */
152 char **MakeFileNames; /* To hold all Makefilenames */
153 int Mfileindex; /* Current Makefile index */
154 int Mfilesize; /* Size of Makefile array */
155 int Mfilecount; /* Number of Makefiles found+2 */
156 char CmdLMac[] = "Command Line Macro"; /* Makefile Name for .. */
157 char **CmdLDefs; /* To hold all Cmdline Macros */
158 int Cmdlinecount; /* Number of Cmdline Macros */
159 int Cmdlinesize; /* Size of Cmdline Macro array */
160 char *MFCmdline; /* Pointer to Cmdl. Macs fr. env*/
161
162 int Mflags;
163
164 char *ObjDir; /* .OBJDIR: pathname Target destination dir */
165 int ObjDirlen; /* strlen(.OBJDIR) */
166 Llong ObjDirfid; /* gfileid(.OBJDIR) */
167 Llong dotfid; /* gfileid(".") */
168 int ObjSearch = SALL; /* .OBJSEARCH: searchtype for explicit rules*/
169 list_t *SearchList; /* .SEARCHLIST: list of src/obj dir pairs */
170 list_t *Suffixes; /* .SUFFIXES: list of suffixes (POSIX) */
171 BOOL SSuffrules;
172 obj_t *Init; /* .INIT: command to execute at startup */
173 obj_t *Done; /* .DONE: command do execute on success */
174 obj_t *Failed; /* .FAILED: command to execute on failure */
175 obj_t *IncludeFailed; /* .INCLUDE_FAILED: cmd to exec if missing */
176 obj_t *Deflt; /* .DEFAULT: command to execute if no rule */
177 obj_t *Precious; /* .PRECIOUS: list of targets not to remove */
178 obj_t *Phony; /* .PHONY: list of false targets, no check */
179 obj_t *curtarget; /* current target of actually running cmd */
180 date_t curtime; /* Current time */
181 date_t newtime; /* Special time newer than all */
182
183 #define MINSECS 60
184 #define HOURSECS (MINSECS*60)
185 #define DAYSECS (HOURSECS*24)
186 #define MONTHSECS (DAYSECS*30)
187 #define YEARSECS (DAYSECS*365)
188 #ifdef USE_NSECS
189 #define DATESECS ((date_t)(1 << NSEC_SHIFT))
190 #else
191 #define DATESECS ((date_t)1)
192 #endif
193
194 char Nullstr[] = "";
195 char slash[] = PATH_DELIM_STR;
196 int slashlen = sizeof (PATH_DELIM_STR) -1; /* strlen(slash) */
197
198 LOCAL BOOL xpatrules; /* Have non local pattern rules in Makefile */
199 EXPORT int xssrules; /* Have non local simple suffix rules */
200
201 #ifdef _FASCII /* Mark Williams C */
202 char *_stksize = (char *) 8192;
203
204 /*
205 * Old and probably outdated setup that was needed in 1986 to make
206 * 'smake' run on a ATARI ST using the Marc Williams C development tools.
207 */
208 LOCAL void
setup_env()209 setup_env()
210 {
211 register char *ep;
212 extern char *getenv();
213
214 if ((ep = getenv("PATH")) == (char *) NULL || *ep == '\0')
215 putenv("PATH=.bin,,\\bin,\\lib");
216
217 if ((ep = getenv("SUFF")) == (char *) NULL || *ep == '\0')
218 putenv("SUFF=,.prg,.tos,.ttp");
219
220 if ((ep = getenv("LIBPATH")) == (char *) NULL || *ep == '\0')
221 putenv("LIBPATH=\\lib,\\bin");
222
223 if ((ep = getenv("TMPDIR")) == (char *) NULL || *ep == '\0')
224 putenv("TMPDIR=\\tmp");
225
226 if ((ep = getenv("INCDIR")) == (char *) NULL || *ep == '\0')
227 putenv("INCDIR=\\include");
228 }
229 #endif
230
231 EXPORT void
usage(exitcode)232 usage(exitcode)
233 int exitcode;
234 {
235 error("Usage: smake [options] [target...] [macro=value...]\n");
236 error("Options:\n");
237 error(" -a Do not set up architecture specific make macros.\n");
238 error(" -e Environment overrides variables in Makefile.\n");
239 error(" -i Ignore errors from commands.\n");
240 error(" -j maxj Specify the number of jobs to run simultaneously.\n");
241 error(" -k Ignore target errors, continue on unrelated targets.\n");
242 error(" -N Continue if no source for nonexistent dependencies is found.\n");
243 error(" -n Don't make - only say what to do.\n");
244 error(" -p Print all macro and target definitions.\n");
245 error(" -q Question mode. Exit code is 0 if target is up to date.\n");
246 error(" -r Turn off internal rules.\n");
247 error(" -s Be silent.\n");
248 error(" -S Undo the effect of the -k option, terminate on target errors.\n");
249 error(" -t Touch Objects instead of executing defined commands.\n");
250 error(" -w Don't print warning Messages.\n");
251 error(" -W Print extra (debug) warning Messages.\n");
252 error(" -WW Print even more (debug) warning Messages.\n");
253 error(" -D Display Makefiles as read in.\n");
254 error(" -DD Display Makefiles/Rules as read in.\n");
255 error(" -d Print reason why a target has to be rebuilt.\n");
256 error(" -dd Debug dependency check.\n");
257 error(" -xM Print include dependency.\n");
258 error(" -xd Print extended debug info.\n");
259 error(" -probj Print object tree.\n");
260 error(" -help Print this help.\n");
261 error(" -version Print version number.\n");
262 error(" -posix Force POSIX behaviour.\n");
263 error(" -C dir Change directory to 'dir' before starting work.\n");
264 error(" mf=makefilename | -f makefilename\n");
265 error("More than one -f makefile option may be specified.\n");
266 exit(exitcode);
267 }
268
269 LOCAL void
initmakefiles()270 initmakefiles()
271 {
272 /*
273 * Mfilecount als Index fuer MakeFileNames[] bei addmakefile()
274 * Mfileindex als globale Index Variable fuer den Parser
275 *
276 * This code needs to be kept in sync with the MF_IDX_* #defines
277 * in make.h
278 */
279 Mfilecount = 0;
280 addmakefile(Makedefs); /* Implicit rules */
281 addmakefile(Envdefs); /* Environment strings */
282 addmakefile(Makefile); /* Default make file */
283 Mfilecount--; /* -f name overwrites Makefile */
284 }
285
286 /*
287 * Called by getargs() if a -C option was found.
288 */
289 LOCAL int
dochdir(name)290 dochdir(name)
291 char *name;
292 {
293 if (chdir(name) < 0)
294 comerr("Cannot change directory to '%s'\n", name);
295
296 return (1);
297 }
298
299 /*
300 * Add a new makefile to the list of makefiles.
301 * Called by getargs() if a -f option was found.
302 */
303 LOCAL int
addmakefile(name)304 addmakefile(name)
305 char *name;
306 {
307 if (MakeFileNames == NULL) {
308 /*
309 * Use a default size of 4 as we usually have 4 Makefiles.
310 */
311 Mfilesize = 4;
312 MakeFileNames = malloc(Mfilesize * sizeof (char *));
313 } else if (Mfilesize <= (Mfilecount+1)) { /* One spare for CmdLMac */
314 Mfilesize += 4;
315 MakeFileNames = realloc(MakeFileNames, Mfilesize * sizeof (char *));
316 }
317 if (MakeFileNames == NULL)
318 comerr("No memory for Makefiles.\n");
319
320 MakeFileNames[Mfilecount++] = name;
321
322 return (1);
323 }
324
325 /*
326 * Read the default rules - either compiled in or from file.
327 */
328 LOCAL void
read_defs()329 read_defs()
330 {
331 int MFsave = Mfileindex;
332 char *deflts;
333 extern char implicit_rules[]; /* Default rules compiled into make */
334
335 Dmake--;
336 Mfileindex = MF_IDX_IMPLICIT; /* Index 0 Implicit Rules */
337
338 if (gftime(Ldefaults) != 0) {
339 MakeFileNames[0] = Ldefaults;
340 readfile(Ldefaults, TRUE);
341 #ifdef DEFAULTS_PATH_SEARCH_FIRST
342 } else if ((deflts = getdefaultsfile()) != NULL) {
343 MakeFileNames[0] = deflts;
344 readfile(deflts, TRUE);
345 #endif
346 #ifdef DEFAULTS_PATH /* This is the install path */
347 } else if (gftime(DEFAULTS_PATH) != 0) {
348 MakeFileNames[0] = DEFAULTS_PATH;
349 readfile(DEFAULTS_PATH, TRUE);
350 #endif
351 } else if (gftime(Defaults) != 0) {
352 MakeFileNames[0] = Defaults;
353 readfile(Defaults, TRUE);
354 #ifndef DEFAULTS_PATH_SEARCH_FIRST
355 } else if ((deflts = getdefaultsfile()) != NULL) {
356 MakeFileNames[0] = deflts;
357 readfile(deflts, TRUE);
358 #endif
359 } else {
360 readstring(implicit_rules, Makedefs);
361 }
362 Dmake++;
363 Mfileindex = MFsave;
364 }
365
366 /*
367 * Read in all external makefiles. Use either the names from command line
368 * or look for the default names "Makefile" and "makefile".
369 */
370 LOCAL void
read_makefiles()371 read_makefiles()
372 {
373 int MFsave = Mfileindex;
374 patr_t *oPatrules = Patrules;
375 patr_t **opattail = pattail;
376
377 Patrules = 0;
378 pattail = &Patrules;
379 xssrules = 0;
380
381 Mfileindex = MF_IDX_MAKEFILE; /* Index 2 Default Makefile */
382 if (Mfilecount == MF_IDX_MAKEFILE) {
383 if (posixmode) {
384 /*
385 * First look for "makefile"
386 * then for "Makefile", then for "SMakefile".
387 */
388 if (gftime(_makefile) != 0) { /* "makefile" */
389 Mfilecount++;
390 MakeFileNames[2] = _makefile;
391 } else if (gftime(Makefile) != 0) { /* "Makefile" */
392 Mfilecount++;
393 MakeFileNames[2] = Makefile;
394 } else if (gftime(SMakefile) != 0) { /* "SMakefile" */
395 Mfilecount++;
396 MakeFileNames[2] = SMakefile;
397 }
398 } else
399 /*
400 * First look for "SMakefile",
401 * then for "Makefile", then for "makefile"
402 */
403 if (gftime(SMakefile) != 0) { /* "SMakefile" */
404 Mfilecount++;
405 MakeFileNames[2] = SMakefile;
406 } else if (gftime(Makefile) != 0) { /* "Makefile" */
407 Mfilecount++;
408 MakeFileNames[2] = Makefile;
409 } else if (gftime(_makefile) != 0) { /* "makefile" */
410 Mfilecount++;
411 MakeFileNames[2] = _makefile;
412 }
413 }
414 while (Mfileindex < Mfilecount) {
415 readfile(MakeFileNames[Mfileindex], TRUE);
416 Mfileindex++;
417 }
418
419 /*
420 * Check for external pattern rule definitions.
421 */
422 xpatrules = Patrules != NULL;
423 /*
424 * The pattern rules which are defined in the external makefiles
425 * must supersede the pattern rules from the internal rules.
426 * Concat the pattern rules found in internal rules to the end of
427 * the patern rules list from external makefiles.
428 */
429 *pattail = oPatrules;
430 pattail = opattail;
431
432 Mfileindex = MFsave;
433 }
434
435 /*
436 * Setup special variables.
437 *
438 * NOTE: Must be reentrant because it may be called more than once
439 * if the "include" directive is used.
440 * As there is (currently) no way to delete an object
441 * it is OK not to do anything special if objlook() returns NULL.
442 */
443 EXPORT void
setup_dotvars()444 setup_dotvars()
445 {
446 obj_t *obj;
447 list_t *l;
448 char *name;
449
450 obj = objlook(".OBJDIR", FALSE);
451 if (obj != NULL && obj->o_type != ':') /* Must be a special target */
452 obj = NULL;
453
454 if (obj != NULL) {
455 if (obj->o_list && (ObjDir = obj->o_list->l_obj->o_name)) {
456 if (gfileid(ObjDir) == gfileid(".")) {
457 /*
458 * Do not allow moving targets to themselves.
459 */
460 ObjDir = NULL;
461 ObjDirlen = 0;
462 } else {
463 ObjDirlen = strlen(ObjDir);
464 }
465 }
466 }
467 #ifdef no_longer_needed /* Has been moved to dynmac expansion */
468 /*
469 * XXX We cannot do this here as we are called more than once and
470 * XXX we like to allow $O to be overwritten from Makefiles that
471 * XXX do not know about smake's special features.
472 */
473 /*
474 * Create special variable $O -> ObjDir
475 */
476 define_var("O", ObjDir ? ObjDir : ".");
477 #endif
478
479 obj = objlook(".OBJSEARCH", FALSE);
480 if (obj != NULL && obj->o_type != ':') /* Must be a special target */
481 obj = NULL;
482 if (obj != NULL) {
483 if ((l = obj->o_list) != NULL) {
484 name = l->l_obj->o_name;
485 if (streql("src", name)) {
486 ObjSearch = SSRC;
487 } else if (streql("obj", name)) {
488 ObjSearch = SOBJ;
489 } else if (streql("all", name)) {
490 ObjSearch = SALL;
491 } else {
492 /*
493 * This is the default.
494 */
495 ObjSearch = SALL;
496 }
497 }
498 }
499
500 obj = objlook(".SEARCHLIST", FALSE);
501 if (obj != NULL && obj->o_type != ':') /* Must be a special target */
502 obj = NULL;
503 if (obj != NULL) {
504 SearchList = obj->o_list;
505 } else if ((obj = objlook("VPATH", FALSE)) != NULL && obj->o_type == '=') {
506 SearchList = cvtvpath(obj->o_list);
507 }
508
509 obj = objlook(".IGNORE", FALSE);
510 if (obj != NULL && obj->o_type != ':') /* Must be a special target */
511 obj = NULL;
512 if (obj != NULL && obj->o_list == NULL)
513 Iflag = TRUE;
514
515 obj = objlook(".SILENT", FALSE);
516 if (obj != NULL && obj->o_type != ':') /* Must be a special target */
517 obj = NULL;
518 if (obj != NULL && obj->o_list == NULL)
519 Sflag = TRUE;
520
521 Init = objlook(".INIT", FALSE);
522 Done = objlook(".DONE", FALSE);
523 Failed = objlook(".FAILED", FALSE);
524 IncludeFailed = objlook(".INCLUDE_FAILED", FALSE);
525 if (IncludeFailed != NULL && IncludeFailed->o_cmd == NULL)
526 IncludeFailed = NULL;
527 Deflt = objlook(".DEFAULT", FALSE);
528 Precious = objlook(".PRECIOUS", FALSE);
529 Phony = objlook(".PHONY", FALSE);
530
531 if (objlook(".POSIX", FALSE))
532 posixmode = TRUE;
533 obj = objlook(".SUFFIXES", FALSE);
534 if (obj != NULL && obj->o_type != ':') /* Must be a special target */
535 obj = NULL;
536 if (obj != NULL)
537 Suffixes = obj->o_list;
538 if (Debug > 1 && Suffixes != (list_t *) NULL) {
539 register list_t *p;
540
541 error(".SUFFIXES :\t");
542 for (p = Suffixes; p; p = p->l_next)
543 error("%s ", p->l_obj->o_name);
544 error("\n");
545 }
546 SSuffrules = check_ssufftab();
547 }
548
549 /*
550 * Set up some known special macros.
551 */
552 LOCAL void
setup_vars()553 setup_vars()
554 {
555 int i;
556 char make_level[64];
557 char *p;
558
559 define_var("$", "$"); /* Really needed ? */
560 define_var("NUMBER_SIGN", "#"); /* Allow to use '#' */
561 define_var("MAKE_NAME", "smake"); /* Needed to identify syntax */
562 define_var("MAKE_VERSION", make_version); /* Version dependant files? */
563 if ((p = getenv(Make_Level)) != NULL) {
564 p = astoi(p, &i);
565 if (*p == '\0')
566 Mlevel = i;
567 }
568 snprintf(make_level, sizeof (make_level), "%d", Mlevel+1);
569 define_var(Make_Level, make_level);
570 doexport(Make_Level);
571 }
572
573 /*
574 * Set up the special macro $(MAKE).
575 * If we were called with an absolute PATH or without any '/', use argv[0],
576 * else compute the absolute PATH by prepending working dir to argv[0].
577 */
578 LOCAL void
setup_MAKE(name)579 setup_MAKE(name)
580 char *name;
581 {
582 char wd[MAXPATHNAME + 1];
583 int len;
584
585 /*
586 * If argv[0] starts with a slash or contains no slash,
587 * or on DOS like OS starts with MS-DOS drive letter,
588 * it is useful as $(MAKE).
589 */
590 #ifdef HAVE_DOS_DRIVELETTER
591 if (name[0] == SLASH || strchr(name, SLASH) == NULL || name[1] == ':') {
592 #else
593 if (name[0] == SLASH || strchr(name, SLASH) == NULL) {
594 #endif
595 define_var("MAKE", name);
596 } else {
597 /*
598 * Compute abs pathname for $(MAKE)
599 */
600 strncpy(wd, curwdir(), sizeof (wd));
601 wd[sizeof (wd)-1] = '\0';
602 len = strlen(wd);
603 if ((strlen(name) + len + 2) < sizeof (wd)) {
604 strcat(wd, PATH_DELIM_STR);
605 strcat(wd, name);
606 }
607 define_var("MAKE", wd);
608 }
609 }
610
611 /*
612 * Transfer object search types into human readable names.
613 */
614 EXPORT char *
searchtype(mode)615 searchtype(mode)
616 int mode;
617 {
618 if (mode == SSRC)
619 return ("src");
620 if (mode == SOBJ)
621 return ("obj");
622 if (mode == SALL)
623 return ("all");
624 return ("invalid Object search mode");
625 }
626
627 /*
628 * Print some 'smake' special macros:
629 * .OBJDIR, .SEARCHLIST and .OBJSEARCH
630 */
631 LOCAL void
printdirs()632 printdirs()
633 {
634 if (ObjDir != NULL)
635 error(".OBJDIR :\t%s\n", ObjDir);
636
637 error(".OBJSEARCH :\t%s\n", searchtype(ObjSearch));
638
639 if (SearchList != (list_t *) NULL) {
640 register list_t *p;
641 error(".SEARCHLIST :\t");
642 for (p = SearchList; p; p = p->l_next)
643 error("%s ", p->l_obj->o_name);
644 error("\n");
645 }
646 }
647
648 /*
649 * Check for a command line macro.
650 * This is called by getargs().
651 */
652 LOCAL int
addcommandline(name)653 addcommandline(name)
654 char *name;
655 {
656 if (Debug > 1)
657 error("got_it: %s\n", name);
658
659 /* UNIX make: ":;=$\n\t" */
660
661 if (!strchr(name, '='))
662 return (NOTAFILE); /* Tell getargs that this may be a flag */
663 return (1);
664 }
665
666 /*
667 * Add a command line macro to our list.
668 * This is called by scan_cmdline() past getargs() since getargs() would
669 * not permit spaces, '+' or ':' to the left of a '='.
670 */
671 LOCAL void
addcmdlinedef(name)672 addcmdlinedef(name)
673 char *name;
674 {
675 if (CmdLDefs == NULL) {
676 Cmdlinesize = 8;
677 CmdLDefs = malloc(Cmdlinesize * sizeof (char *));
678 } else if (Cmdlinesize <= Cmdlinecount) {
679 Cmdlinesize += 8;
680 CmdLDefs = realloc(CmdLDefs, Cmdlinesize * sizeof (char *));
681 }
682 if (CmdLDefs == NULL)
683 comerr("No memory for Commandline Macros.\n");
684
685 CmdLDefs[Cmdlinecount++] = name;
686 }
687
688 /*
689 * Read in and parse all command line macro definitions from list.
690 */
691 LOCAL void
scan_cmdline(ac,av)692 scan_cmdline(ac, av)
693 int ac;
694 char **av;
695 {
696 register int i;
697
698 for (i = 1; i < ac; i++) {
699 if (av[i][0] == '-')
700 continue;
701 if (strchr(av[i], '=') == NULL)
702 continue;
703 addcmdlinedef(av[i]);
704 }
705 }
706
707 /*
708 * Read in and parse all command line macro definitions from list.
709 */
710 LOCAL void
read_cmdline()711 read_cmdline()
712 {
713 int MFsave = Mfileindex;
714 register int i;
715
716 if (Cmdlinecount == 0)
717 return;
718
719 /*
720 * Register the command line macros past the last makefile
721 */
722 Mfileindex = Mfilecount;
723 if (Mfileindex == MF_IDX_MAKEFILE)
724 Mfileindex = MF_IDX_MAKEFILE + 1;
725 MakeFileNames[Mfileindex] = CmdLMac;
726
727 Mflags |= (F_READONLY|F_IDXOVERWRT);
728 for (i = 0; i < Cmdlinecount; i++) {
729 char *eq;
730 char *sp;
731
732 readstring(CmdLDefs[i], CmdLMac);
733
734 eq = strchr(CmdLDefs[i], '=');
735 sp = strchr(CmdLDefs[i], ' ');
736 if ((sp == NULL || sp > eq) && eq[-1] != ':')
737 put_env(CmdLDefs[i]);
738 }
739 Mflags &= ~(F_READONLY|F_IDXOVERWRT);
740 Mfileindex = MFsave;
741 }
742
743 /*
744 * Export a macro into the environment.
745 * This is mainly done by the "export" directive inside a makefile.
746 */
747 EXPORT void
doexport(oname)748 doexport(oname)
749 char *oname;
750 {
751 obj_t *obj;
752 list_t *l;
753 char *name;
754 int len;
755
756 obj = objlook(oname, FALSE);
757 if (obj != NULL && basetype(obj->o_type) != '=') /* Must be a macro type target */
758 obj = NULL;
759 if (obj != NULL) {
760 if ((l = obj->o_list) != NULL) {
761 char *xname;
762
763 len = strlen(oname)+1; /* Env name + '=' */
764 while (l && l->l_obj->o_name) {
765 xname = l->l_obj->o_name;
766 if (gbuf != NULL)
767 xname = substitute(xname,
768 NullObj, 0, 0);
769 len += strlen(xname)+1;
770 l = l->l_next;
771 }
772 name = malloc(len);
773 if (name == NULL)
774 comerr("Cannot alloc memory for env.\n");
775 name[0] = '\0';
776 l = obj->o_list;
777 strcat(name, oname);
778 strcat(name, "=");
779 while (l && l->l_obj->o_name) {
780 xname = l->l_obj->o_name;
781 if (gbuf != NULL)
782 xname = substitute(xname,
783 NullObj, 0, 0);
784 strcat(name, xname);
785 if (l->l_next == NULL)
786 break;
787 strcat(name, " ");
788 l = l->l_next;
789 }
790 put_env(name);
791 }
792 }
793 }
794
795 /*
796 * Unexport a macro from the environment.
797 * This is mainly done by the "unexport" directive inside a makefile.
798 */
799 EXPORT void
dounexport(oname)800 dounexport(oname)
801 char *oname;
802 {
803 unset_env(oname);
804 }
805
806
807 /*
808 * Read in and parse all environment vars to make them make macros.
809 */
810 LOCAL void
read_environ()811 read_environ()
812 {
813 int MFsave = Mfileindex;
814 register char **env;
815 extern char **environ;
816 char *ev;
817 char *p;
818
819 Dmake -= 2;
820 Mfileindex = MF_IDX_ENVIRON; /* Index 1 Environment vars */
821
822 if (Eflag)
823 Mflags |= F_READONLY;
824 mfname = Envdefs;
825 for (env = environ; *env; env++) {
826 ev = *env;
827 p = strchr(ev, EQUAL);
828 if (p == NULL)
829 continue;
830 if (strncmp(ev, "CURDIR=", 7) == 0)
831 continue; /* Never import CURDIR */
832 if (strncmp(ev, "SHELL=", 6) == 0)
833 continue; /* Never import SHELL */
834 if (strncmp(ev, "FORCE_SHELL=", 12) == 0) {
835 obj_t *obj = objlook(".FORCE_SHELL", TRUE);
836 if (obj->o_type == 0)
837 obj->o_type = COLON;
838 }
839 *p = '\0';
840 define_var(ev, &p[1]);
841 *p = EQUAL;
842 }
843 mfname = NULL;
844 Mflags &= ~F_READONLY;
845
846 Dmake += 2;
847 Mfileindex = MFsave;
848 }
849
850
851 EXPORT int
main(ac,av)852 main(ac, av)
853 int ac;
854 char *av[];
855 {
856 int failures = 0;
857 int i;
858 int maxj = 0;
859 int cac = ac;
860 char * const *cav = av;
861 static char options[] = "help,version,posix,a,e,i,j#,k,n,N,p,q,r,s,S,t,w,W+,d+,D+,xM,xd+,probj,C&,mf&,f&,&";
862
863 save_args(ac, av);
864
865 (void) setlocale(LC_ALL, "");
866
867 #ifdef USE_NLS
868 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
869 #define TEXT_DOMAIN "smake" /* Use this only if it weren't */
870 #endif
871 { char *dir;
872 dir = searchfileinpath("share/locale", F_OK,
873 SIP_ANY_FILE|SIP_NO_PATH, NULL);
874 if (dir)
875 (void) bindtextdomain(TEXT_DOMAIN, dir);
876 else
877 #if defined(PROTOTYPES) && defined(INS_BASE)
878 (void) bindtextdomain(TEXT_DOMAIN, INS_BASE "/share/locale");
879 #else
880 (void) bindtextdomain(TEXT_DOMAIN, "/usr/share/locale");
881 #endif
882 (void) textdomain(TEXT_DOMAIN);
883 }
884 #endif /* USE_NLS */
885
886 #ifdef __DJGPP__
887 set_progname("smake"); /* We may have strange av[0] on DJGPP */
888 #endif
889
890 #ifdef HAVE_GETPID
891 getpid(); /* Give some info for truss(1) users */
892 #endif
893 #ifdef HAVE_GETPGRP
894 getpgrp(); /* Give some info for truss(1) users */
895 #endif
896
897 #ifdef _FASCII /* Mark Williams C */
898 stderr->_ff &= ~_FSTBUF; /* setbuf was called ??? */
899
900 setup_env();
901 #endif
902 getmakeflags(); /* Default options from MAKEFLAGS= */
903 initmakefiles(); /* Set up MakeFileNames[] array */
904
905 cac--; cav++;
906 if (getallargs(&cac, &cav, options, &help, &pversion, &posixmode,
907 &Aflag,
908 &Eflag, &Iflag, &maxj,
909 &Kflag, &Nflag, &NSflag, &Print,
910 &Qflag, &Rflag, &Sflag, &Stopflag, &Tflag,
911 &No_Warn, &Do_Warn,
912 &Debug, &Dmake, &Prdep, &XDebug, &Pr_obj,
913 dochdir, NULL,
914 addmakefile, NULL,
915 addmakefile, NULL,
916 addcommandline, NULL) < 0) {
917 errmsgno(EX_BAD, "Bad flag: %s.\n", cav[0]);
918 usage(EX_BAD);
919 }
920 if (help)
921 usage(0);
922 if (pversion) {
923 gtprintf("Smake release %s %s (%s-%s-%s) Copyright (C) 1985, 87, 88, 91, 1995-2021 %s\n",
924 make_version, VERSION_DATE,
925 HOST_CPU, HOST_VENDOR, HOST_OS,
926 _("J�rg Schilling"));
927 exit(0);
928 }
929 if (maxj > 0 && maxj <= MAXJOBS_MAX)
930 maxjobs = maxj;
931 else if (maxj > 0)
932 maxjobs = MAXJOBS_MAX;
933
934 /*
935 * XXX Is this the right place to set the options and cmd line macros
936 * XXX to the exported environment?
937 * XXX Later in read_makemacs() we may find that MAKEFLAGS= may contain
938 * XXX garbage that has been propagated to MFCmdline.
939 * For this reason, we call read_makemacs() before, let it parse only
940 * and kill any unwanted content from MFCmdline.
941 */
942 if (NullObj == 0) /* First make sure we may expand vars */
943 NullObj = objlook(Nullstr, TRUE);
944
945 scan_cmdline(ac, av); /* Identify and save cmd line macro defs */
946 read_makemacs(); /* With gbuf == NULL, this is parse only */
947 setmakeflags();
948 if (Qflag) {
949 Sflag = TRUE;
950 Nflag = TRUE;
951 }
952 if (Tflag && !Nflag) {
953 Nflag = -1; /* Hack for touch_file() */
954 }
955 if (Stopflag) {
956 Kflag = FALSE;
957 }
958 if (Debug > 0)
959 error("MAKEFLAGS value: '%s'\n", getenv(Makeflags));
960
961 /*
962 * XXX Reihenfolge bei UNIX make beachten!!!
963 */
964 if (signal(SIGINT, SIG_IGN) != SIG_IGN)
965 signal(SIGINT, handler);
966 #ifdef SIGQUIT
967 if (signal(SIGQUIT, SIG_IGN) != SIG_IGN)
968 signal(SIGQUIT, handler);
969 #endif
970 #ifdef SIGHUP
971 if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
972 signal(SIGHUP, handler);
973 #endif
974 if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
975 signal(SIGTERM, handler);
976 curtime = gcurtime();
977 newtime = gnewtime();
978 NullObj->o_date = newtime; /* Make NullObj "up to date" */
979
980 initchars();
981 initgbuf(NAMEMAX); /* Now the Makefile parser becomes usable */
982
983 /*
984 * The functions read_cmdline() and read_makemacs() are setting
985 * the F_READONLY flag in all objects. The function read_environ()
986 * sets F_READONLY if the -e option was specified.
987 * This differs from the description in POSIX for 'make' but it
988 * is the only way to allow 'include' directives to work as expected.
989 * For the same reason, we are reading the macros in the opposite
990 * order as described in POSIX.
991 */
992 read_cmdline(); /* First read cmd line macros */
993 read_makemacs(); /* then the inherited cmd line macros */
994 if (!Rflag)
995 read_defs(); /* read "defaults.smk" */
996 setup_MAKE(av[0]); /* Set up $(MAKE) */
997 setup_SHELL(); /* Set up $(SHELL) */
998 setup_vars(); /* Set up some known special macros */
999 if (!Aflag)
1000 setup_arch(); /* Set up arch specific macros */
1001 read_environ(); /* Sets F_READONLY if -e flag is present*/
1002
1003 if (Debug > 0 && Mlevel > 0)
1004 error("Starting '%s'[%d] in directory '%s'\n",
1005 av[0], Mlevel, curwdir());
1006
1007 /*
1008 * Clear default target, then look again in makefiles
1009 */
1010 default_tgt = NULL;
1011 read_makefiles();
1012
1013 /*
1014 * Let all objects created later seem to bee in
1015 * last Makefile or in implicit rules if no
1016 * Makefile is present.
1017 */
1018 Mfileindex = Mfilecount - 1;
1019 if (Mfileindex < MF_IDX_MAKEFILE)
1020 Mfileindex = MF_IDX_IMPLICIT;
1021
1022 setup_dotvars();
1023 setup_xvars(); /* Set up compat vars like MAKE_SHELL_FLAG */
1024 if (!Rflag)
1025 check_old_makefiles();
1026
1027 if (Pr_obj) /* -probj Flag */
1028 printtree();
1029 if (Print) { /* -p Flag */
1030 prtree();
1031 exit(0); /* XXX Really exit() here for make -p -f /dev/null ??? */
1032 /* XXX Posix requires make -p -f /dev/null 2>/dev/null */
1033 /* XXX to print the internal macros */
1034 }
1035 on_comerr(exhandler, av[0]);
1036 if (Debug > 0)
1037 printdirs(); /* .OBJDIR .OBJSEARCH .SEARCHLIST */
1038
1039 makeincs(); /* Re-make included files */
1040 omake(Init, TRUE); /* Make .INIT target */
1041 cac = ac;
1042 cav = av;
1043 cac--; cav++;
1044 for (i = 0; getfiles(&cac, &cav, options); cac--, cav++, i++) {
1045 if (strchr(cav[0], '=')) { /* Skip command line macro defs */
1046 i--;
1047 continue;
1048 }
1049 if (!domake(cav[0])) /* Make targets from command line */
1050 failures++;
1051 }
1052
1053 if (i == 0 && !domake((char *) NULL)) /* Make default target */
1054 failures++;
1055 if (failures && Failed) {
1056 omake(Failed, TRUE); /* Make .FAILED target */
1057 } else {
1058 omake(Done, TRUE); /* Make .DONE target */
1059 }
1060 #ifdef DEBUG
1061 prmem();
1062 #endif
1063 if (failures > 0)
1064 comexit(1);
1065 comexit(0);
1066 return (0); /* keep lint happy :-) */
1067 }
1068
1069 /*
1070 * Check for old makefile systems without pattern matching rules.
1071 *
1072 * Old makefile systems only define simple suffix rules. Now that newer smake
1073 * releases support POSIX suffix rules, the makefile system will only work
1074 * if the makefile system uses pattern matching rules.
1075 * We may remove this function in 2005.
1076 */
1077 LOCAL void
check_old_makefiles()1078 check_old_makefiles()
1079 {
1080 obj_t *o;
1081
1082 if (Suffixes == NULL) /* No/Empty .SUFFIXES, no compat problems */
1083 return;
1084 if (xssrules == 0) /* Makefile did not define simple suff rule*/
1085 return;
1086 if (xpatrules) /* New makefiles define pattern rules */
1087 return;
1088
1089 /*
1090 * All makefiles from the Schily (SING) makefile system define
1091 * _UNIQ=.XxZzy-
1092 */
1093 if ((o = objlook("_UNIQ", FALSE)) == NULL)
1094 return;
1095 if (!streql(".XxZzy-", o->o_list->l_obj->o_name))
1096 return;
1097
1098 errmsgno(EX_BAD, "WARNING: this project uses an old version of the makefile system.\n");
1099 comerrno(EX_BAD, "Update the makefiles or call 'smake -r'.\n");
1100 }
1101
1102 /*
1103 * Read in and parse the makeflags we got from the MAKEFLAGS= environment var.
1104 * MAKEFLAGS= may be:
1105 *
1106 * - "et..." Only option letters.
1107 * No space and no macro definitions.
1108 * - "NAME=value..." Only a list of macro definitions (like a
1109 * make command line).
1110 * - "-et..." Options as they appear on the command line.
1111 * Space and multiple '-' are allowed.
1112 * "-et -- NAME=value..." A complete make command line (except
1113 * -f filename options and target arguments).
1114 * BSD make:
1115 *
1116 * - " NAME=value..." Only a list of macro definitions.
1117 *
1118 * - " -e -t" Only options.
1119 *
1120 * - " -e -t NAME=value..." A complete make command line.
1121 *
1122 * SunPro Make:
1123 *
1124 * "-et NAME=value..." A complete make command line.
1125 */
1126 LOCAL void
getmakeflags()1127 getmakeflags()
1128 {
1129 int MFsave = Mfileindex;
1130 char *mf = getenv(Makeflags);
1131 BOOL hasdash = FALSE;
1132
1133 if (!mf || *mf == '\0') /* No MAKEFLAGS= or empty MAKEFLAGS= */
1134 return;
1135 while (*mf == ' ')
1136 mf++;
1137
1138 Mfileindex = MF_IDX_ENVIRON; /* Index 1 Environment vars */
1139 if (*mf != '-') { /* Only macros if does not start with '-'*/
1140 char *p = nextmakemac(mf); /* Next unescaped ' ' */
1141 char *eql = strchr(mf, '=');
1142
1143 /*
1144 * Be gracious to non POSIX make programs like 'GNUmake' which
1145 * may have "e -- MAKE=smake" in the MAKEFLAGS environment.
1146 * The correct string would rather be "-e -- MAKE=smake".
1147 */
1148 if (eql != NULL && (p == NULL || eql < p)) {
1149 /*
1150 * No options at all, only cmdline macros.
1151 *
1152 * The content returned from getenv("MAKEFLAGS")
1153 * has been reported to change on DJGPP.
1154 * We need to use strdup() to keep it stable.
1155 */
1156 MFCmdline = strdup(mf);
1157 if (MFCmdline == NULL)
1158 MFCmdline = mf;
1159 goto out; /* Allow debug prints */
1160 }
1161 } else {
1162 hasdash = TRUE;
1163 }
1164
1165 while (*mf) {
1166 switch (*mf) {
1167
1168 case ' ': {
1169 char *p = mf;
1170
1171 while (*p == ' ')
1172 p++;
1173
1174 if (*p != '-') { /* May be a macro */
1175 if (hasdash) {
1176 mf = p;
1177 goto macs;
1178 }
1179 break; /* Ignore blanks */
1180 }
1181 mf = p; /* Starts with '-' */
1182 }
1183 /* FALLTHRU */
1184
1185 case '-': /* look for " -- " separator */
1186 if (mf[1] != '-')
1187 break; /* Ignore single '-' */
1188
1189 if (mf[2] != ' ') {
1190 char *p = nextmakemac(mf);
1191
1192 errmsgno(EX_BAD,
1193 "Found illegal option '%s' in MAKEFLAGS.\n",
1194 mf);
1195 if (p != NULL) {
1196 size_t d = p - mf;
1197 if (d > 50)
1198 d = 50;
1199 errmsgno(EX_BAD,
1200 "Skipping illegal option '%.*s'.\n",
1201 (int)d, mf);
1202 mf = p;
1203 break;
1204 } else {
1205 errmsgno(EX_BAD,
1206 "Ignoring illegal option '%s'.\n",
1207 mf);
1208 }
1209 goto out; /* Allow debug prints */
1210 }
1211 /*
1212 * The content returned from getenv("MAKEFLAGS")
1213 * has been reported to change on DJGPP.
1214 * We need to use strdup() to keep it stable.
1215 */
1216 mf += 3;
1217 macs:
1218 MFCmdline = strdup(mf);
1219 if (MFCmdline == NULL)
1220 MFCmdline = mf;
1221 goto out; /* Allow debug prints */
1222
1223 case 'D': /* Display makefile */
1224 Dmake++;
1225 break;
1226
1227 case 'd': /* Debug */
1228 Debug++;
1229 break;
1230
1231 case 'X': /* XDebug */
1232 XDebug++;
1233 break;
1234
1235 case 'a':
1236 Aflag = TRUE; /* Do not run setup_arch() */
1237 break;
1238
1239 case 'e': /* Environment overrides vars */
1240 Eflag = TRUE;
1241 break;
1242
1243 case 'i': /* Ignore errors from cmds */
1244 Iflag = TRUE;
1245 break;
1246
1247 case 'k': /* Ignore target errors */
1248 Kflag = TRUE;
1249 break;
1250
1251 case 'N': /* Ignore no Source on dep. */
1252 NSflag = TRUE;
1253 break;
1254
1255 case 'n': /* Do not exec any commands */
1256 Nflag = TRUE;
1257 break;
1258
1259 case 'P': /* POSIX mode */
1260 posixmode = TRUE;
1261 break;
1262
1263 case 'p': /* Print macros/targets */
1264 Print = TRUE;
1265 break;
1266
1267 case 'q': /* Question */
1268 Qflag = TRUE;
1269 break;
1270
1271 case 'r': /* Turn off internal Rules */
1272 Rflag = TRUE;
1273 break;
1274
1275 case 's': /* Silent */
1276 Sflag = TRUE;
1277 break;
1278
1279 case 'S': /* Stop on error (opposite of -k) */
1280 Stopflag = TRUE;
1281 break;
1282
1283 case 't': /* Touch */
1284 Tflag = TRUE;
1285 break;
1286
1287 case 'W': /* Extra Warnings */
1288 Do_Warn++;
1289 break;
1290
1291 case 'w': /* No Warnings */
1292 No_Warn = TRUE;
1293 break;
1294
1295 case 'Z': /* Print includes */
1296 Prdep = TRUE;
1297 break;
1298 }
1299 mf++;
1300 }
1301 out:
1302 /*
1303 * As this is called before we call getargs(), Debug may only be true
1304 * if the 'd' option is present in the MAKEFLAGS environment.
1305 */
1306 if (Debug > 0)
1307 error("Read MAKEFLAGS: '%s'\n", getenv(Makeflags));
1308
1309 Mfileindex = MFsave;
1310 }
1311
1312 /*
1313 * Parse a list of macro=value command line macros from the
1314 * MAKEFLAGS= environment and set up the macro in the make tree.
1315 * If gbuf is NULL, read_mac() is parse only.
1316 */
1317 LOCAL void
read_makemacs()1318 read_makemacs()
1319 {
1320 register char *mf = MFCmdline;
1321 register char *p;
1322 int MFsave = Mfileindex;
1323
1324 if (mf == NULL)
1325 return;
1326
1327 Mfileindex = MF_IDX_ENVIRON; /* Index 1 Environment vars */
1328 while (*mf) {
1329 p = nextmakemac(mf);
1330 if (p == NULL) { /* No other macro def follows */
1331 if (!read_mac(mf)) {
1332 errmsgno(EX_BAD,
1333 "Bad MAKEFLAGS= environment '%s'.\n",
1334 getenv(Makeflags));
1335 *mf = '\0';
1336 }
1337 break;
1338 } else { /* Need to temporarily null terminate */
1339 *p = '\0';
1340 if (!read_mac(mf)) {
1341 errmsgno(EX_BAD,
1342 "Bad MAKEFLAGS= environment '%s'.\n",
1343 getenv(Makeflags));
1344 ovstrcpy(mf, &p[1]);
1345 } else {
1346 *p = ' ';
1347 mf = &p[1];
1348 }
1349 }
1350 }
1351 Mfileindex = MFsave;
1352 }
1353
1354 /*
1355 * Find next un-escaped blank (' ') which is a separator
1356 * for a list of macro=value items.
1357 */
1358 LOCAL char *
nextmakemac(s)1359 nextmakemac(s)
1360 char *s;
1361 {
1362 while (*s) {
1363 if (*s == '\\') { /* escaped character */
1364 if (*++s == '\0')
1365 return (NULL);
1366 } else if (*s == ' ') { /* un-escaped space */
1367 return (s);
1368 }
1369 s++;
1370 }
1371 return (NULL);
1372 }
1373
1374 /*
1375 * Remove the escapes that have been introduced before the name=value
1376 * lists are put together into the MAKEFLAGS= environment.
1377 * Then parse the result as a string.
1378 * If gbuf is NULL, read_mac() is parse only.
1379 */
1380 LOCAL BOOL
read_mac(mf)1381 read_mac(mf)
1382 char *mf;
1383 {
1384 char *omf = mf;
1385 char macdef[NAMEMAX*2+1];
1386 char *p;
1387
1388 p = macdef;
1389 while (*mf) {
1390 if (p >= &macdef[NAMEMAX*2])
1391 break;
1392 /*
1393 * Only remove those escape sequences, that we created.
1394 * This is "\\" and "\ ".
1395 */
1396 if (mf[0] == '\\' && (mf[1] == '\\' || mf[1] == ' '))
1397 mf++;
1398 *p++ = *mf++;
1399 }
1400 *p = '\0';
1401
1402 if (macdef[0] == '\0') /* Ignore empty definition */
1403 return (TRUE);
1404 if (strchr(macdef, '=') == NULL) { /* Check if it is a macro def*/
1405 errmsgno(EX_BAD,
1406 "Found illegal macro definition '%s' in MAKEFLAGS.\n",
1407 macdef);
1408 errmsgno(EX_BAD, "The raw macro definition was '%s'.\n", omf);
1409 return (FALSE);
1410 }
1411
1412 if (gbuf == NULL) /* Parse only and kill */
1413 return (TRUE); /* unwanted content */
1414
1415 Mflags |= F_READONLY;
1416 readstring(macdef, Makeflags);
1417 Mflags &= ~F_READONLY;
1418 return (TRUE);
1419 }
1420
1421 /*
1422 * Prepare the MAKEFLAGS= environment for export.
1423 */
1424 LOCAL void
setmakeflags()1425 setmakeflags()
1426 {
1427 /*
1428 * MAKEFLAGS=- 12 bytes incl '\0'
1429 * 4 x 8 bytes= 32 bytes
1430 * 16 flags 16 bytes
1431 * '-- ' 3 bytes
1432 * =====================
1433 * 62 bytes
1434 */
1435 #define MAKEENV_SIZE_STATIC 64
1436 static char makeenv[MAKEENV_SIZE_STATIC];
1437 char *p;
1438 int i;
1439
1440 p = strcatl(makeenv, Makeflags, (char *)NULL);
1441 *p++ = '=';
1442 *p++ = '-'; /* Posix make includes '-' */
1443 /* "MAKEFLAGS=-" 12 incl. '\0' */
1444
1445 i = Dmake; /* Display makefile */
1446 if (i > 8)
1447 i = 8;
1448 while (--i >= 0)
1449 *p++ = 'D';
1450
1451 i = Debug; /* Debug */
1452 if (i > 8)
1453 i = 8;
1454 while (--i >= 0)
1455 *p++ = 'd';
1456
1457 i = Do_Warn; /* Do_Wan - Extra Warnings */
1458 if (i > 8)
1459 i = 8;
1460 while (--i >= 0)
1461 *p++ = 'W';
1462
1463 i = XDebug; /* XDebug */
1464 if (i > 8)
1465 i = 8;
1466 while (--i >= 0)
1467 *p++ = 'X';
1468
1469 if (Aflag) /* Do not run setup_arch() */
1470 *p++ = 'a';
1471 if (Eflag) /* Environment overrides vars */
1472 *p++ = 'e';
1473 if (Iflag) /* Ignore errors from cmds */
1474 *p++ = 'i';
1475 if (Kflag) /* Ignore target errors */
1476 *p++ = 'k';
1477 if (NSflag) /* Ignore no Source on dep. */
1478 *p++ = 'N';
1479 if (Nflag) /* Do not exec any commands */
1480 *p++ = 'n';
1481 if (posixmode) /* POSIX mode */
1482 *p++ = 'P';
1483 if (Print) /* Print macros/targets */
1484 *p++ = 'p';
1485 if (Qflag) /* Question */
1486 *p++ = 'q';
1487 if (Rflag) /* Turn off internal Rules */
1488 *p++ = 'r';
1489 if (Sflag) /* Silent */
1490 *p++ = 's';
1491 if (Stopflag) /* Stop on error (opposite of -k) */
1492 *p++ = 'S';
1493 if (Tflag) /* Touch */
1494 *p++ = 't';
1495 if (No_Warn) /* No Warnings */
1496 *p++ = 'w';
1497 if (Prdep) /* Print includes */
1498 *p++ = 'Z';
1499
1500 if (p - makeenv == 11) /* Empty flags, remove '-' */
1501 --p;
1502 *p = '\0';
1503 define_var(Make_Flags, &makeenv[10]); /* MAKE_FLAGS= ... */
1504 doexport(Make_Flags);
1505 setmakeenv(makeenv, p); /* Add cmdline macs */
1506 }
1507
1508 /*
1509 * Strip out macro defs inherited from MAKELAGS, that will be overwritten
1510 * by command line macro defs.
1511 * Return new write pointer at end of string.
1512 */
1513 LOCAL char *
stripmacros(macbase,new)1514 stripmacros(macbase, new)
1515 char *macbase;
1516 char *new;
1517 {
1518 char *p = strchr(new, '=');
1519 char *p2;
1520
1521 if (p == NULL) /* Paranoia */
1522 return (macbase + strlen(macbase));
1523
1524 do {
1525 p2 = nextmakemac(macbase); /* Find next macro delim */
1526
1527 if (strncmp(macbase, new, p - new) == 0) {
1528 /*
1529 * Got a match, need to remove this entry.
1530 */
1531 if (p2 == NULL) { /* This is the only, zap out */
1532 *macbase = '\0';
1533 } else { /* Copy rest over current */
1534 ovstrcpy(macbase, &p2[1]);
1535 }
1536 } else if (p2) { /* Continue with next extry */
1537 macbase = &p2[1];
1538 }
1539 } while (p2);
1540 return (macbase + strlen(macbase));
1541 }
1542
1543 /*
1544 * Add the actual command line macro definitions to the MAKEFLAGS= string
1545 * and then putenv() the result.
1546 */
1547 LOCAL void
setmakeenv(envbase,envp)1548 setmakeenv(envbase, envp)
1549 char *envbase;
1550 char *envp;
1551 {
1552 register int i;
1553 register int l;
1554 register int len = 0;
1555 register char *p;
1556 register char *macbase;
1557
1558 if (Cmdlinecount == 0 && (MFCmdline == 0 || *MFCmdline == '\0')) {
1559 /*
1560 * No command line macros and no inherited command line
1561 * macros from MAKEFLAGS, so just call putenv() and return.
1562 */
1563 put_env(envbase);
1564 return;
1565 }
1566
1567 if ((envp - envbase) > 10) { /* envbase[] is currently not empty */
1568 strcpy(envp, " -- "); /* we need a separator to the flags */
1569
1570 envp += 4;
1571 *envp = '\0';
1572 }
1573 if (MFCmdline) /* Add one for '\0' or ' ' at end */
1574 len = strlen(MFCmdline) + 1;
1575
1576 for (i = 0; i < Cmdlinecount; i++) {
1577 p = CmdLDefs[i];
1578 while (*p) {
1579 if (*p == '\\' || *p == ' ')
1580 len++;
1581 len++;
1582 p++;
1583 }
1584 len += 1; /* Add one for '\0' or ' ' at end */
1585 }
1586
1587 l = strlen(envbase) + len + 1; /* Add one (see stripmacro comment) */
1588 if (l > MAKEENV_SIZE_STATIC) {
1589 p = malloc(l);
1590 strcpy(p, envbase);
1591 envp = p + (envp - envbase);
1592 envbase = p;
1593 }
1594
1595 macbase = envp;
1596 if (MFCmdline) {
1597 for (p = MFCmdline; *p; )
1598 *envp++ = *p++;
1599 *envp++ = ' ';
1600 }
1601 *envp = '\0';
1602
1603 for (i = 0; i < Cmdlinecount; i++) {
1604 p = CmdLDefs[i];
1605 envp = stripmacros(macbase, p);
1606 while (*p) {
1607 if (*p == '\\' || *p == ' ')
1608 *envp++ = '\\';
1609 *envp++ = *p++;
1610 }
1611 *envp++ = ' ';
1612 *envp = '\0'; /* Needed for stripmacros */
1613 } /* But overshoots by one */
1614 *--envp = '\0';
1615 put_env(envbase);
1616 define_var(Make_Macs, macbase); /* MAKE_MACS= ... */
1617 doexport(Make_Macs);
1618 }
1619
1620 #ifdef tos
1621 # include "osbind.h"
1622 #endif
1623
1624 /*
1625 * Move a target file to ObjDir.
1626 *
1627 * Returns:
1628 * FALSE Failure
1629 * TRUE OK, but no file was moved
1630 * TRUE + 1 OK, but file was not found
1631 * TRUE + 2 OK and file actually moved
1632 */
1633 EXPORT int
move_tgt(from)1634 move_tgt(from)
1635 register obj_t *from;
1636 {
1637 date_t fromtime;
1638 int code;
1639 char _objname[TYPICAL_NAMEMAX];
1640 char *objname = NULL;
1641 BOOL ret = TRUE;
1642
1643 /*
1644 * Move only if:
1645 * objdir to corresponding srcdir exists
1646 * target is known in Makefile
1647 */
1648 if ((ObjDir == NULL && from->o_level == OBJLEVEL) ||
1649 from->o_level < OBJLEVEL)
1650 return (TRUE);
1651
1652 if (strchr(from->o_name, SLASH)) /* Only move from current directory */
1653 return (TRUE);
1654
1655 fromtime = gftime(from->o_name);
1656 if (fromtime == 0) /* Nothing to move found */
1657 return (TRUE+1);
1658
1659 if (Debug > 3) error("move: from->o_level: %d\n", from->o_level);
1660 if ((objname = build_path(from->o_level, from->o_name, from->o_namelen,
1661 _objname, sizeof (_objname))) == NULL)
1662 return (FALSE);
1663 if (!Sflag || Nflag)
1664 gtprintf("%smove %s %s\n", posixmode?"\t":"...", from->o_name, objname);
1665 ret = TRUE + 2;
1666 if (Nflag) {
1667 goto out;
1668 }
1669
1670 if ((from->o_name == objname) ||
1671 (gfileid(from->o_name) == gfileid(objname))) {
1672 errmsgno(EX_BAD, "Will not move '%s' to itself.\n",
1673 from->o_name);
1674 ret = TRUE;
1675 goto out;
1676 }
1677 # ifdef tos
1678 unlink(objname);
1679 if ((code = Frename(0, from->o_name, objname)) < 0) {
1680 if (code == EXDEV) {
1681 code = copy_file(from->o_name, objname);
1682 if (unlink(from->o_name) < 0)
1683 errmsg("Can't remove old name '%s'.\n",
1684 from->o_name);
1685 } else {
1686 errmsgno(-code, "Can't rename '%s' to '%s'.\n",
1687 from->o_name, objname);
1688 }
1689 }
1690 if (code < 0) {
1691 ret = FALSE;
1692 goto out;
1693 }
1694 # else
1695 if ((code = rename(from->o_name, objname)) < 0) {
1696 if (geterrno() == EXDEV) {
1697 if (rmdir(objname) < 0 && geterrno() == ENOTDIR)
1698 unlink(objname);
1699 code = copy_file(from->o_name, objname);
1700 if (unlink(from->o_name) < 0)
1701 errmsg("Can't remove old name '%s'.\n",
1702 from->o_name);
1703 } else {
1704 errmsg("Can't rename '%s' to '%s'.\n",
1705 from->o_name, objname);
1706 }
1707 }
1708 if (code < 0) {
1709 ret = FALSE;
1710 goto out;
1711 }
1712 #endif /* tos */
1713 out:
1714 if (objname != NULL && objname != from->o_name && objname != _objname)
1715 free(objname);
1716 return (ret);
1717 }
1718
1719 /*
1720 * Copy File if we cannot rename the file.
1721 */
1722 #ifdef tos
1723 LOCAL int
copy_file(from,objname)1724 copy_file(from, objname)
1725 char *from;
1726 char *objname;
1727 {
1728 int fin;
1729 int fout;
1730 int cnt = -1;
1731
1732 if ((fin = open(from, O_RDONLY)) < 0)
1733 errmsg("Can't open '%s'.\n", from);
1734 else {
1735 if ((fout = creat(objname, 0666)) < 0)
1736 errmsg("Can't create '%s'.\n", objname);
1737 else {
1738 while ((cnt = read(fin, gbuf, gbufsize)) > 0) {
1739 if (write(fout, gbuf, cnt) != cnt) {
1740 errmsg("Write error on '%s'.\n",
1741 objname);
1742 close(fout);
1743 close(fin);
1744 return (-1);
1745 }
1746 }
1747 if (cnt < 0)
1748 errmsg("Read error on '%s'.\n", from);
1749 close(fout);
1750 }
1751 close(fin);
1752 }
1753 return (cnt);
1754 }
1755 #else
1756 LOCAL int
copy_file(from,objname)1757 copy_file(from, objname)
1758 char *from;
1759 char *objname;
1760 {
1761 FILE *fin;
1762 FILE *fout;
1763 int cnt = -1;
1764
1765 if ((fin = fileopen(from, "rub")) == 0)
1766 errmsg("Can't open '%s'.\n", from);
1767 else {
1768 if ((fout = fileopen(objname, "wtcub")) == 0)
1769 errmsg("Can't create '%s'.\n", objname);
1770 else {
1771 file_raise(fin, FALSE);
1772 file_raise(fout, FALSE);
1773 while ((cnt = fileread(fin, gbuf, gbufsize)) > 0) {
1774 if (filewrite(fout, gbuf, cnt) < 0) {
1775 errmsg("Write error on '%s'.\n",
1776 objname);
1777 fclose(fout);
1778 fclose(fin);
1779 return (-1);
1780 }
1781 }
1782 if (cnt < 0)
1783 errmsg("Read error on '%s'.\n", from);
1784 fclose(fout);
1785 }
1786 fclose(fin);
1787 }
1788 return (cnt);
1789 }
1790 #endif
1791
1792 /*
1793 * This function behaves similar to the UNIX 'touch' command.
1794 */
1795 EXPORT BOOL
touch_file(name)1796 touch_file(name)
1797 char *name;
1798 {
1799 FILE *f;
1800 char _objname[TYPICAL_NAMEMAX];
1801 char *objname = _objname;
1802 size_t objlen = sizeof (_objname);
1803 char *np = NULL;
1804 #ifndef HAVE_UTIME
1805 char c;
1806 #endif
1807
1808 again:
1809 if (ObjDir == NULL)
1810 objname = name;
1811 else if (snprintf(objname, objlen, "%s%s%s", ObjDir,
1812 slash, filename(name)) >= objlen) {
1813 objlen = strlen(filename(name)) + ObjDirlen + slashlen + 1;
1814 objname = np = ___realloc(np, objlen, "touch path");
1815 goto again;
1816 }
1817 #ifdef __is_this_ok__
1818 if (!gftime(objname))
1819 snprintf(_objname, sizeof (_objname), name);
1820 #endif
1821 if (!Sflag)
1822 gtprintf("%stouch %s\n", posixmode?"\t":"...", objname);
1823 if (Nflag > 0)
1824 return (TRUE);
1825 /*
1826 * No touch if make was called with -n.
1827 */
1828 if ((f = fileopen(objname, "rwcub")) != (FILE *)NULL) {
1829 file_raise(f, FALSE);
1830 #ifdef HAVE_UTIME
1831 utime(objname, NULL);
1832 #else
1833 c = getc(f);
1834 fileseek(f, (off_t)0);
1835 putc(c, f);
1836 #endif
1837 fclose(f);
1838 if (np)
1839 free(np);
1840 return (TRUE);
1841 }
1842 if (np)
1843 free(np);
1844 return (FALSE);
1845 }
1846
1847 # include <schily/stat.h>
1848 # define STATBUF struct stat
1849
1850 /*
1851 * Get current time.
1852 */
1853 LOCAL date_t
gcurtime()1854 gcurtime()
1855 {
1856 struct timespec ts;
1857 date_t d;
1858
1859 getnstimeofday(&ts);
1860 d = ts.tv_sec;
1861 #ifdef USE_NSECS
1862 d <<= NSEC_SHIFT; /* Make space for nanoseconds */
1863 d |= ts.tv_nsec;
1864 #endif
1865 if (Debug > 1)
1866 error("gcurtime() = %s (%llx)\n", prtime(d), (Llong)d);
1867 return (d);
1868 }
1869
1870 /*
1871 * Get a time that is in the future (as far as possible).
1872 */
1873 LOCAL date_t
gnewtime()1874 gnewtime()
1875 {
1876 time_t t;
1877 date_t d;
1878
1879 t = TYPE_MAXVAL(time_t);
1880
1881 /*
1882 * "t" is now the maximum positive number for type time_t.
1883 * In case of a 64 bit time_t, this is more than we can have in date_t
1884 * so we need to make the number small enough to have space for nsecs.
1885 */
1886 d = t;
1887 #ifdef USE_NSECS
1888 #if SIZEOF_DATE_T > SIZEOF_TIME_T
1889 d <<= NSEC_SHIFT; /* Make space for nanoseconds */
1890 #else
1891 d >>= NSEC_SHIFT; /* Shrink d to maximum time_t */
1892 d <<= NSEC_SHIFT; /* Make space for nanoseconds */
1893 #endif
1894 d += 999999999; /* Add maximum nanosecond value */
1895 #endif /* USE_NSECS */
1896
1897 while (d == NOTIME || d == BADTIME ||
1898 d == RECURSETIME || d == PHONYTIME) {
1899 d--;
1900 }
1901
1902 /*printf("i: %d, %llu, %llx, %s\n", i, d, d, prtime(-3));*/
1903
1904 if (Debug > 1)
1905 error("gnewtime() = %s (%llx)\n", prtime(d), (Llong)d);
1906 return (d);
1907 }
1908
1909 /*
1910 * Get the time of last modification for a file.
1911 * Cannot call it gmtime()
1912 */
1913 EXPORT date_t
gftime(file)1914 gftime(file)
1915 char *file;
1916 {
1917 STATBUF stbuf;
1918 char this_time[42];
1919 char cur_time[42];
1920 date_t d;
1921
1922 /*
1923 * XXX should we cache the file times?
1924 */
1925 /*#define nonono__*/
1926 #ifdef nonono__
1927 obj_t *o = objlook(file, FALSE);
1928
1929 if (o != NULL && VALIDTIME(o->o_date)) {
1930 if (o->o_date != newtime) /* Only if real time */
1931 return (o->o_date); /* Cached file time */
1932 }
1933 #endif
1934
1935 stbuf.st_mtime = NOTIME;
1936 if (stat(file, &stbuf) < 0) {
1937 /*
1938 * GNU libc.6 destroys st_mtime
1939 */
1940 d = NOTIME;
1941 } else {
1942 #ifdef USE_NSECS
1943 long nsecs;
1944 #endif
1945 d = stbuf.st_mtime;
1946 #ifdef USE_NSECS
1947 d <<= NSEC_SHIFT;
1948 nsecs = stat_mnsecs(&stbuf);
1949 #if !defined(HAVE_UTIMENS) && !defined(HAVE_UTIMENSAT)
1950 /*
1951 * If the current platform does not support to willfully
1952 * set full nanosecond values, but only microseconds, we
1953 * compare time stamps only with microsecond resolution.
1954 */
1955 nsecs -= nsecs % 1000;
1956 #endif
1957 d |= nsecs;
1958 #endif
1959 /*
1960 * Make sure that the time for an existing file is not
1961 * in the list of special time stamps.
1962 */
1963 while (d == NOTIME || d == BADTIME ||
1964 d == RECURSETIME || d == MAKETIME || d == PHONYTIME) {
1965 d++;
1966 }
1967 #ifdef nonono__
1968 if (o == NULL) {
1969 o = objlook(file, TRUE);
1970 o->o_date = d;
1971 }
1972 #endif
1973 }
1974
1975 if (Debug > 3)
1976 error("gftime(%s) = %s\n", file, prtime(d));
1977
1978 /*
1979 * If the time stamp retrieved by stat() is more than 5 seconds
1980 * ahead of our start time, we check for a possible time skew between
1981 * this machine and it's fileserver.
1982 */
1983 if (d > (curtime + (5*DATESECS))) {
1984 date_t xcurtime;
1985
1986 xcurtime = gcurtime();
1987 if (d <= (xcurtime + (5*DATESECS))) {
1988 /*
1989 * We run for more than 5 seconds already and the
1990 * file's time stamp is not more than 5 seconds ahead
1991 * of the current time. Return silently.
1992 */
1993 curtime = xcurtime;
1994 return (d);
1995 }
1996 strncpy(this_time, prtime(d), sizeof (this_time));
1997 this_time[sizeof (this_time)-1] = '\0';
1998 strncpy(cur_time, prtime(curtime), sizeof (cur_time));
1999 cur_time[sizeof (cur_time)-1] = '\0';
2000 errmsgno(EX_BAD,
2001 "WARNING: '%s' has modification time in the future (%s > %s).\n",
2002 file, this_time, cur_time);
2003 }
2004 return (d);
2005 }
2006
2007 /*
2008 * Check if file is a directory.
2009 */
2010 LOCAL BOOL
isdir(file)2011 isdir(file)
2012 char *file;
2013 {
2014 STATBUF stbuf;
2015
2016 /*
2017 * It is safe to assume that "." is a directory.
2018 */
2019 if (file[0] == '.' && file[1] == '\0')
2020 return (TRUE);
2021
2022 if (stat(file, &stbuf) < 0)
2023 return (TRUE);
2024 if ((stbuf.st_mode&S_IFMT) == S_IFDIR)
2025 return (TRUE);
2026 return (FALSE);
2027 }
2028
2029 /*
2030 * Get a unique number for a file to prevent moving targets to themselves.
2031 * XXX inode number is now long !!!
2032 */
2033 EXPORT Llong
gfileid(file)2034 gfileid(file)
2035 char *file;
2036 {
2037 STATBUF stbuf;
2038 Llong result;
2039
2040 /*
2041 * Cache .OBJDIR and ".".
2042 */
2043 if (file == ObjDir) {
2044 if (ObjDirfid != 0)
2045 return (ObjDirfid);
2046 } else if (file[0] == '.' && file[1] == '\0') {
2047 if (dotfid != 0)
2048 return (dotfid);
2049 }
2050
2051 /*
2052 * Setup a unique default. In case stat() will fail.
2053 */
2054 stbuf.st_ino = (ino_t) (long) file;
2055 stbuf.st_dev = 0;
2056 if (stat(file, &stbuf) < 0) {
2057 /*
2058 * GNU libc.6 destroys st_mtime
2059 * Paranoia .... we fall back here too.
2060 */
2061 stbuf.st_ino = (ino_t) (long) file;
2062 stbuf.st_dev = 0;
2063 }
2064 #if SIZEOF_LLONG > 4
2065 result = stbuf.st_dev;
2066 result <<= 32;
2067 result |= stbuf.st_ino;
2068 #else
2069 result = stbuf.st_dev;
2070 result <<= 16;
2071 result |= stbuf.st_ino;
2072 #endif
2073
2074 if (file == ObjDir)
2075 ObjDirfid = result;
2076 else if (file[0] == '.' && file[1] == '\0')
2077 dotfid = result;
2078
2079 if (Debug > 3)
2080 error("gfileid: %s %lld\n", file, result);
2081 return (result);
2082 }
2083
2084 /*
2085 * Transfer UNIX time stamps into human readable names.
2086 * Take care of our "special timestamps".
2087 */
2088 EXPORT char *
prtime(date)2089 prtime(date)
2090 date_t date;
2091 {
2092 char *s;
2093 time_t t;
2094 char nsbuf[20];
2095 long nsecs;
2096
2097 if (date == (date_t)0)
2098 return ("File does not exist");
2099 if (date == BADTIME)
2100 return ("File could not be made");
2101 if (date == RECURSETIME)
2102 return ("Recursive dependencies");
2103 if (date == MAKETIME)
2104 return ("File is currently being made");
2105 if (date == PHONYTIME)
2106 return ("File is phony");
2107 if (date == newtime)
2108 return ("Younger than any file");
2109
2110 #ifdef USE_NSECS
2111 t = date >> NSEC_SHIFT;
2112 #else
2113 t = date;
2114 #endif
2115 s = ctime(&t);
2116 if (s == NULL)
2117 strcpy(s, "<time range error>");
2118 else
2119 s[strlen(s)-1] = '\0';
2120 #ifdef USE_NSECS
2121 nsecs = date & 0x3fffffff;
2122 snprintf(nsbuf, sizeof (nsbuf), ".%9.9ld", nsecs);
2123 strcat(s, nsbuf);
2124 #endif
2125 return (s);
2126 }
2127
2128 /*
2129 * Our general signal handler. Does some needed clean up and includes
2130 * workarounds for buggy OS like Linux.
2131 */
2132 LOCAL void
handler(signo)2133 handler(signo)
2134 int signo;
2135 {
2136 char *name;
2137 #if defined(__linux__) || defined(__linux) || \
2138 defined(SHELL_IS_BASH) || defined(BIN_SHELL_IS_BASH)
2139 #if defined(HAVE_SIGNAL) && defined(HAVE_KILL) && \
2140 defined(SIG_IGN) && defined(SIGKILL)
2141 job *jobp;
2142 int i;
2143 #endif
2144 #endif
2145
2146 signal(signo, handler);
2147 errmsgno(EX_BAD, "Got signal %d\n", signo);
2148 if (!curtarget)
2149 goto out;
2150
2151 errmsgno(EX_BAD, "Current target is: %s precious: %d phony: %d\n",
2152 curtarget->o_name,
2153 isprecious(curtarget),
2154 isprecious(curtarget));
2155
2156 /* while(wait(0) >= 0) */
2157 /* ;*/
2158 /*
2159 * Keine Bibliotheken
2160 * Kein -t, -q etc.
2161 */
2162 if (Tflag || Print || Qflag || Nflag)
2163 goto out;
2164 if (isprecious(curtarget))
2165 goto out;
2166 if (isphony(curtarget))
2167 goto out;
2168
2169 name = curtarget->o_name;
2170
2171 if (isdir(name)) {
2172 error("*** %s not removed.\n", name);
2173 goto out;
2174 }
2175 if (unlink(name) >= 0) {
2176 error("*** %s removed.\n", name);
2177 } else {
2178 errmsg("*** %s could not be removed.\n", name);
2179 }
2180 /*
2181 * Test ob ObjDir/name existiert und neuer als vorher ist.
2182 */
2183
2184 out:
2185
2186 #if defined(__linux__) || defined(__linux) || \
2187 defined(SHELL_IS_BASH) || defined(BIN_SHELL_IS_BASH)
2188 #if defined(HAVE_SIGNAL) && defined(HAVE_KILL) && \
2189 defined(SIG_IGN) && defined(SIGKILL)
2190 /*
2191 * Linux signal handling is broken. This is caused by a bug in 'bash'.
2192 * Bash does jobcontrol even if called as "sh -ce 'command'".
2193 * This is illegal. Only the foreground (make) process and with some
2194 * bash versions the descendant 'make' processes are killed.
2195 * The following code tries to kill the others too.
2196 */
2197 signal(signo, SIG_IGN); /* Make us immune to death ;-) */
2198
2199 /*
2200 * First shoot everyone into the foot.
2201 */
2202 for (jobp = jobs, i = maxjobs; --i >= 0; jobp++) {
2203 pid_t pid = jobp->j_pid;
2204
2205 if (pid == 0)
2206 continue;
2207 kill(pid, signo); /* Kill bash that is our child */
2208 kill(-pid, signo); /* Kill possible bash children */
2209 }
2210 kill(-getpgrp(), signo); /* Kill our process group */
2211
2212 /*
2213 * Now shoot everyone into the head.
2214 */
2215 for (jobp = jobs, i = maxjobs; --i >= 0; jobp++) {
2216 pid_t pid = jobp->j_pid;
2217
2218 if (pid == 0)
2219 continue;
2220 kill(pid, SIGKILL); /* Kill bash that is our child */
2221 kill(-pid, SIGKILL); /* Kill possible bash children */
2222 }
2223 kill(-getpgrp(), SIGKILL); /* Kill our process group */
2224 #endif
2225 #endif
2226 comexit(signo);
2227 }
2228
2229 LOCAL void
exhandler(excode,arg)2230 exhandler(excode, arg)
2231 int excode;
2232 void *arg;
2233 {
2234 /*
2235 * Ausgabe wenn:
2236 *
2237 * - excode != 0 && Mlevel > 0
2238 * - Debug > 0 && Mlevel > 0
2239 */
2240 if ((Debug <= 1 && excode == 0) || Mlevel <= 0)
2241 return;
2242
2243 errmsgno(EX_BAD, "Leaving '%s'[%d] from directory '%s'\n",
2244 (char *)arg, Mlevel, curwdir());
2245 if (default_tgt != NULL)
2246 errmsgno(EX_BAD,
2247 "Default commandline target: '%s'\n", default_tgt->o_name);
2248 errmsgno(EX_BAD, "Doing exit(%d)\n", excode);
2249 }
2250
2251 /*
2252 * Return current working directory in an allocated string.
2253 */
2254 EXPORT char *
curwdir()2255 curwdir()
2256 {
2257 static char *wdir;
2258 char wd[MAXPATHNAME + 1];
2259
2260 if (wdir != NULL)
2261 return (wdir);
2262
2263 if (getcwd(wd, MAXPATHNAME) == NULL) {
2264 wd[0] = '/';
2265 wd[1] = '\0';
2266 }
2267 wdir = malloc(strlen(wd)+1);
2268 if (wdir == NULL)
2269 comerr("Cannot malloc working dir.\n");
2270 strcpy(wdir, wd);
2271 define_var("CURDIR", wdir);
2272 return (wdir);
2273 }
2274
2275 /*
2276 * Search for the defaults.smk file in the PATH of the user.
2277 * Assume that the file is ... bin/../share/lib/smake/defaults.smk
2278 */
2279 LOCAL char *
getdefaultsfile()2280 getdefaultsfile()
2281 {
2282 return (searchfileinpath("share/lib/smake/defaults.smk",
2283 R_OK, TRUE, NULL));
2284 }
2285
2286 LOCAL int
put_env(new)2287 put_env(new)
2288 char *new;
2289 {
2290 if (strncmp(new, "SHELL=", 6) == 0)
2291 return (0); /* Never export SHELL */
2292
2293 return (putenv(new));
2294 }
2295
2296 LOCAL int
unset_env(name)2297 unset_env(name)
2298 char *name;
2299 {
2300 if (strcmp(name, "SHELL") == 0)
2301 return (0); /* Never unexport SHELL */
2302
2303 unsetenv(name); /* OpenBSD deviates and returns void */
2304 return (0);
2305 }
2306