xref: /openbsd-src/usr.bin/make/compat.c (revision db3296cf5c1dd9058ceecc3a29fe4aaa0bd26000)
1 /*	$OpenPackages$ */
2 /*	$OpenBSD: compat.c,v 1.49 2003/06/03 02:56:11 millert Exp $	*/
3 /*	$NetBSD: compat.c,v 1.14 1996/11/06 17:59:01 christos Exp $	*/
4 
5 /*
6  * Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
7  * Copyright (c) 1988, 1989 by Adam de Boor
8  * Copyright (c) 1989 by Berkeley Softworks
9  * All rights reserved.
10  *
11  * This code is derived from software contributed to Berkeley by
12  * Adam de Boor.
13  *
14  * Redistribution and use in source and binary forms, with or without
15  * modification, are permitted provided that the following conditions
16  * are met:
17  * 1. Redistributions of source code must retain the above copyright
18  *    notice, this list of conditions and the following disclaimer.
19  * 2. Redistributions in binary form must reproduce the above copyright
20  *    notice, this list of conditions and the following disclaimer in the
21  *    documentation and/or other materials provided with the distribution.
22  * 3. 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 
39 #include <sys/types.h>
40 #include <sys/stat.h>
41 #include <sys/wait.h>
42 #include <ctype.h>
43 #include <errno.h>
44 #include <limits.h>
45 #include <signal.h>
46 #include <stddef.h>
47 #include <stdio.h>
48 #include <stdlib.h>
49 #include <string.h>
50 #include <unistd.h>
51 #include "config.h"
52 #include "defines.h"
53 #include "dir.h"
54 #include "job.h"
55 #include "compat.h"
56 #include "suff.h"
57 #include "var.h"
58 #include "targ.h"
59 #include "error.h"
60 #include "str.h"
61 #include "extern.h"
62 #include "memory.h"
63 #include "gnode.h"
64 #include "make.h"
65 #include "timestamp.h"
66 #include "lst.h"
67 #include "pathnames.h"
68 
69 /* The following array is used to make a fast determination of which
70  * characters are interpreted specially by the shell.  If a command
71  * contains any of these characters, it is executed by the shell, not
72  * directly by us.  */
73 
74 static char	    meta[256];
75 
76 static GNode	    *ENDNode;
77 static void CompatInterrupt(int);
78 static int CompatRunCommand(void *, void *);
79 static void CompatMake(void *, void *);
80 static int shellneed(char **);
81 
82 static volatile sig_atomic_t interrupted;
83 
84 static void
85 CompatInterrupt(signo)
86     int signo;
87 {
88     if (interrupted != SIGINT)
89 	interrupted = signo;
90 }
91 
92 /*-
93  *-----------------------------------------------------------------------
94  * shellneed --
95  *
96  * Results:
97  *	Returns 1 if a specified set of arguments
98  *	must be executed by the shell,
99  *	0 if it can be run via execve, and -1 if the command can be
100  *	handled internally
101  *
102  * Side Effects:
103  *	May modify the process umask
104  *-----------------------------------------------------------------------
105  */
106 static int
107 shellneed(av)
108 	char **av;
109 {
110 	char *runsh[] = {
111 		"alias", "cd", "eval", "exec", "exit", "read", "set", "ulimit",
112 		"unalias", "unset", "wait",
113 		NULL
114 	};
115 
116 	char **p;
117 
118 	/* FIXME most of these ARE actual no-ops */
119 	for (p = runsh; *p; p++)
120 		if (strcmp(av[0], *p) == 0)
121 			return 1;
122 
123 	if (strcmp(av[0], "umask") == 0) {
124 		long umi;
125 		char *ep = NULL;
126 		mode_t um;
127 
128 		if (av[1] != NULL) {
129 			umi = strtol(av[1], &ep, 8);
130 			if (ep == NULL)
131 				return 1;
132 			um = umi;
133 		}
134 		else {
135 			um = umask(0);
136 			printf("%o\n", um);
137 		}
138 		(void)umask(um);
139 		return -1;
140 	}
141 
142 	return 0;
143 }
144 
145 /*-
146  *-----------------------------------------------------------------------
147  * CompatRunCommand --
148  *	Execute the next command for a target. If the command returns an
149  *	error, the node's made field is set to ERROR and creation stops.
150  *
151  * Results:
152  *	0 in case of error, 1 if ok.
153  *
154  * Side Effects:
155  *	The node's 'made' field may be set to ERROR.
156  *-----------------------------------------------------------------------
157  */
158 static int
159 CompatRunCommand(cmdp, gnp)
160     void *	  cmdp; 	/* Command to execute */
161     void *	  gnp;		/* Node from which the command came */
162 {
163     char	  *cmdStart;	/* Start of expanded command */
164     char *cp, *bp = NULL;
165     bool	  silent,	/* Don't print command */
166 		  doExecute;	/* Execute the command */
167     volatile bool errCheck;	/* Check errors */
168     int 	  reason;	/* Reason for child's death */
169     int 	  status;	/* Description of child's death */
170     pid_t 	  cpid; 	/* Child actually found */
171     pid_t	  stat; 	/* Status of fork */
172     LstNode	  cmdNode;	/* Node where current command is located */
173     char	  ** volatile av; /* Argument vector for thing to exec */
174     int 	  argc; 	/* Number of arguments in av or 0 if not
175 				 * dynamically allocated */
176     bool	  local;	/* true if command should be executed
177 				 * locally */
178     char	  *cmd = (char *)cmdp;
179     GNode	  *gn = (GNode *)gnp;
180     static char *shargv[4] = { _PATH_BSHELL };
181 
182     silent = gn->type & OP_SILENT;
183     errCheck = !(gn->type & OP_IGNORE);
184     doExecute = !noExecute;
185 
186     cmdNode = Lst_Member(&gn->commands, cmd);
187     cmdStart = Var_Subst(cmd, &gn->context, false);
188 
189     /* brk_string will return an argv with a NULL in av[0], thus causing
190      * execvp to choke and die horribly. Besides, how can we execute a null
191      * command? In any case, we warn the user that the command expanded to
192      * nothing (is this the right thing to do?).  */
193 
194     if (*cmdStart == '\0') {
195 	free(cmdStart);
196 	Error("%s expands to empty string", cmd);
197 	return 1;
198     } else
199 	cmd = cmdStart;
200     Lst_Replace(cmdNode, cmdStart);
201 
202     if ((gn->type & OP_SAVE_CMDS) && (gn != ENDNode)) {
203 	Lst_AtEnd(&ENDNode->commands, cmdStart);
204 	return 1;
205     } else if (strcmp(cmdStart, "...") == 0) {
206 	gn->type |= OP_SAVE_CMDS;
207 	return 1;
208     }
209 
210     for (;; cmd++) {
211 	if (*cmd == '@')
212 	    silent = DEBUG(LOUD) ? false : true;
213 	else if (*cmd == '-')
214 	    errCheck = false;
215 	else if (*cmd == '+')
216 	    doExecute = true;
217 	else
218 	    break;
219     }
220 
221     while (isspace(*cmd))
222 	cmd++;
223 
224     /* Search for meta characters in the command. If there are no meta
225      * characters, there's no need to execute a shell to execute the
226      * command.  */
227     for (cp = cmd; !meta[(unsigned char)*cp]; cp++) {
228 	continue;
229     }
230 
231     /* Print the command before echoing if we're not supposed to be quiet for
232      * this one. We also print the command if -n given.  */
233     if (!silent || noExecute) {
234 	printf("%s\n", cmd);
235 	fflush(stdout);
236     }
237 
238     /* If we're not supposed to execute any commands, this is as far as
239      * we go...  */
240     if (!doExecute)
241 	return 1;
242 
243     if (*cp != '\0') {
244 	/* If *cp isn't the null character, we hit a "meta" character and
245 	 * need to pass the command off to the shell. We give the shell the
246 	 * -e flag as well as -c if it's supposed to exit when it hits an
247 	 * error.  */
248 
249 	shargv[1] = errCheck ? "-ec" : "-c";
250 	shargv[2] = cmd;
251 	shargv[3] = NULL;
252 	av = shargv;
253 	argc = 0;
254     } else {
255 	/* No meta-characters, so probably no need to exec a shell.
256 	 * Break the command into words to form an argument vector
257 	 * we can execute.  */
258 	av = brk_string(cmd, &argc, &bp);
259 	switch (shellneed(av)) {
260 	case -1: /* handled internally */
261 		free(bp);
262 		free(av);
263 		return 1;
264 	case 1:
265 		shargv[1] = errCheck ? "-ec" : "-c";
266 		shargv[2] = cmd;
267 		shargv[3] = NULL;
268 		free(av);
269 		free(bp);
270 		bp = NULL;
271 		av = shargv;
272 		argc = 0;
273 		break;
274 	default: /* nothing needed */
275 		break;
276 	}
277     }
278 
279     local = true;
280 
281     /* Fork and execute the single command. If the fork fails, we abort.  */
282     cpid = fork();
283     if (cpid == -1)
284 	Fatal("Could not fork");
285     if (cpid == 0) {
286 	if (local) {
287 	    execvp(av[0], av);
288 	    if (errno == ENOENT)
289 		fprintf(stderr, "%s: not found\n", av[0]);
290 	    else
291 		perror(av[0]);
292 	} else
293 	    (void)execv(av[0], av);
294 	_exit(1);
295     }
296     if (bp) {
297 	free(av);
298 	free(bp);
299     }
300     free(cmdStart);
301     Lst_Replace(cmdNode, NULL);
302 
303     /* The child is off and running. Now all we can do is wait...  */
304     while (1) {
305 
306 	while ((stat = wait(&reason)) != cpid) {
307 	    if (stat == -1 && errno != EINTR)
308 		break;
309 	}
310 
311 	if (interrupted)
312 	    break;
313 
314 	if (stat != -1) {
315 	    if (WIFSTOPPED(reason))
316 		status = WSTOPSIG(reason);		/* stopped */
317 	    else if (WIFEXITED(reason)) {
318 		status = WEXITSTATUS(reason);		/* exited */
319 		if (status != 0)
320 		    printf("*** Error code %d", status);
321 	    } else {
322 		status = WTERMSIG(reason);		/* signaled */
323 		printf("*** Signal %d", status);
324 	    }
325 
326 
327 	    if (!WIFEXITED(reason) || status != 0) {
328 		if (errCheck) {
329 		    gn->made = ERROR;
330 		    if (keepgoing)
331 			/* Abort the current target, but let others
332 			 * continue.  */
333 			printf(" (continuing)\n");
334 		} else {
335 		    /* Continue executing commands for this target.
336 		     * If we return 0, this will happen...  */
337 		    printf(" (ignored)\n");
338 		    status = 0;
339 		}
340 	    }
341 	    return !status;
342 	} else
343 	    Fatal("error in wait: %d", stat);
344 	    /*NOTREACHED*/
345     }
346 
347     /* This is reached only if interrupted */
348     if (!Targ_Precious(gn)) {
349 	char	  *file = Varq_Value(TARGET_INDEX, gn);
350 
351 	if (!noExecute && eunlink(file) != -1)
352 	    Error("*** %s removed\n", file);
353     }
354     if (interrupted == SIGINT) {
355     	GNode *i = Targ_FindNode(".INTERRUPT", TARG_NOCREATE);
356 	signal(SIGINT, SIG_IGN);
357 	signal(SIGTERM, SIG_IGN);
358 	signal(SIGHUP, SIG_IGN);
359 	signal(SIGQUIT, SIG_IGN);
360 	interrupted = 0;
361 	if (i != NULL)
362 	    Lst_Find(&i->commands, CompatRunCommand, i);
363 	exit(SIGINT);
364     }
365     exit(interrupted);
366 }
367 
368 /*-
369  *-----------------------------------------------------------------------
370  * CompatMake --
371  *	Make a target.
372  *
373  * Side Effects:
374  *	If an error is detected and not being ignored, the process exits.
375  *-----------------------------------------------------------------------
376  */
377 static void
378 CompatMake(gnp, pgnp)
379     void *	gnp;	    /* The node to make */
380     void *	pgnp;	    /* Parent to abort if necessary */
381 {
382     GNode *gn = (GNode *)gnp;
383     GNode *pgn = (GNode *)pgnp;
384 
385     if (pgn->type & OP_MADE) {
386 	(void)Dir_MTime(gn);
387 	gn->made = UPTODATE;
388     }
389 
390     if (gn->type & OP_USE) {
391 	Make_HandleUse(gn, pgn);
392     } else if (gn->made == UNMADE) {
393 	/* First mark ourselves to be made, then apply whatever transformations
394 	 * the suffix module thinks are necessary. Once that's done, we can
395 	 * descend and make all our children. If any of them has an error
396 	 * but the -k flag was given, our 'make' field will be set false again.
397 	 * This is our signal to not attempt to do anything but abort our
398 	 * parent as well.  */
399 	gn->make = true;
400 	gn->made = BEINGMADE;
401 	Suff_FindDeps(gn);
402 	Lst_ForEach(&gn->children, CompatMake, gn);
403 	if (!gn->make) {
404 	    gn->made = ABORTED;
405 	    pgn->make = false;
406 	    return;
407 	}
408 
409 	if (Lst_Member(&gn->iParents, pgn) != NULL) {
410 	    Varq_Set(IMPSRC_INDEX, Varq_Value(TARGET_INDEX, gn), pgn);
411 	}
412 
413 	/* All the children were made ok. Now cmtime contains the modification
414 	 * time of the newest child, we need to find out if we exist and when
415 	 * we were modified last. The criteria for datedness are defined by the
416 	 * Make_OODate function.  */
417 	if (DEBUG(MAKE))
418 	    printf("Examining %s...", gn->name);
419 	if (! Make_OODate(gn)) {
420 	    gn->made = UPTODATE;
421 	    if (DEBUG(MAKE))
422 		printf("up-to-date.\n");
423 	    return;
424 	} else if (DEBUG(MAKE))
425 	    printf("out-of-date.\n");
426 
427 	/* If the user is just seeing if something is out-of-date, exit now
428 	 * to tell him/her "yes".  */
429 	if (queryFlag)
430 	    exit(-1);
431 
432 	/* We need to be re-made. We also have to make sure we've got a $?
433 	 * variable. To be nice, we also define the $> variable using
434 	 * Make_DoAllVar().  */
435 	Make_DoAllVar(gn);
436 
437 	/* Alter our type to tell if errors should be ignored or things
438 	 * should not be printed so CompatRunCommand knows what to do.	*/
439 	if (Targ_Ignore(gn))
440 	    gn->type |= OP_IGNORE;
441 	if (Targ_Silent(gn))
442 	    gn->type |= OP_SILENT;
443 
444 	if (Job_CheckCommands(gn, Fatal)) {
445 	    /* Our commands are ok, but we still have to worry about the -t
446 	     * flag...	*/
447 	    if (!touchFlag)
448 		Lst_Find(&gn->commands, CompatRunCommand, gn);
449 	    else
450 		Job_Touch(gn, gn->type & OP_SILENT);
451 	} else
452 	    gn->made = ERROR;
453 
454 	if (gn->made != ERROR) {
455 	    /* If the node was made successfully, mark it so, update
456 	     * its modification time and timestamp all its parents. Note
457 	     * that for .ZEROTIME targets, the timestamping isn't done.
458 	     * This is to keep its state from affecting that of its parent.  */
459 	    gn->made = MADE;
460 #ifndef RECHECK
461 	    /* We can't re-stat the thing, but we can at least take care of
462 	     * rules where a target depends on a source that actually creates
463 	     * the target, but only if it has changed, e.g.
464 	     *
465 	     * parse.h : parse.o
466 	     *
467 	     * parse.o : parse.y
468 	     *		yacc -d parse.y
469 	     *		cc -c y.tab.c
470 	     *		mv y.tab.o parse.o
471 	     *		cmp -s y.tab.h parse.h || mv y.tab.h parse.h
472 	     *
473 	     * In this case, if the definitions produced by yacc haven't
474 	     * changed from before, parse.h won't have been updated and
475 	     * gn->mtime will reflect the current modification time for
476 	     * parse.h. This is something of a kludge, I admit, but it's a
477 	     * useful one..
478 	     *
479 	     * XXX: People like to use a rule like
480 	     *
481 	     * FRC:
482 	     *
483 	     * To force things that depend on FRC to be made, so we have to
484 	     * check for gn->children being empty as well...  */
485 	    if (!Lst_IsEmpty(&gn->commands) || Lst_IsEmpty(&gn->children))
486 		gn->mtime = now;
487 #else
488 	    /* This is what Make does and it's actually a good thing, as it
489 	     * allows rules like
490 	     *
491 	     *	cmp -s y.tab.h parse.h || cp y.tab.h parse.h
492 	     *
493 	     * to function as intended. Unfortunately, thanks to the stateless
494 	     * nature of NFS (and the speed of this program), there are times
495 	     * when the modification time of a file created on a remote
496 	     * machine will not be modified before the stat() implied by
497 	     * the Dir_MTime occurs, thus leading us to believe that the file
498 	     * is unchanged, wreaking havoc with files that depend on this one.
499 	     *
500 	     * I have decided it is better to make too much than to make too
501 	     * little, so this stuff is commented out unless you're sure it's
502 	     * ok.
503 	     * -- ardeb 1/12/88
504 	     */
505 	    if (noExecute || is_out_of_date(Dir_MTime(gn)))
506 		gn->mtime = now;
507 	    if (is_strictly_before(gn->mtime, gn->cmtime))
508 		gn->mtime = gn->cmtime;
509 	    if (DEBUG(MAKE))
510 		printf("update time: %s\n", Targ_FmtTime(gn->mtime));
511 #endif
512 	    if (!(gn->type & OP_EXEC)) {
513 		pgn->childMade = true;
514 		Make_TimeStamp(pgn, gn);
515 	    }
516 	} else if (keepgoing)
517 	    pgn->make = false;
518 	else {
519 
520 	    if (gn->lineno)
521 		printf("\n\nStop in %s (line %lu of %s).\n",
522 			Var_Value(".CURDIR"),
523 			(unsigned long)gn->lineno,
524 			gn->fname);
525 	    else
526 		printf("\n\nStop in %s.\n", Var_Value(".CURDIR"));
527 	    exit(1);
528 	}
529     } else if (gn->made == ERROR)
530 	/* Already had an error when making this beastie. Tell the parent
531 	 * to abort.  */
532 	pgn->make = false;
533     else {
534 	if (Lst_Member(&gn->iParents, pgn) != NULL) {
535 	    Varq_Set(IMPSRC_INDEX, Varq_Value(TARGET_INDEX, gn), pgn);
536 	}
537 	switch (gn->made) {
538 	    case BEINGMADE:
539 		Error("Graph cycles through %s\n", gn->name);
540 		gn->made = ERROR;
541 		pgn->make = false;
542 		break;
543 	    case MADE:
544 		if ((gn->type & OP_EXEC) == 0) {
545 		    pgn->childMade = true;
546 		    Make_TimeStamp(pgn, gn);
547 		}
548 		break;
549 	    case UPTODATE:
550 		if ((gn->type & OP_EXEC) == 0)
551 		    Make_TimeStamp(pgn, gn);
552 		break;
553 	    default:
554 		break;
555 	}
556     }
557 }
558 
559 void
560 Compat_Run(targs)
561     Lst 	  targs;    /* List of target nodes to re-create */
562 {
563     char	  *cp;	    /* Pointer to string of shell meta-characters */
564     GNode	  *gn = NULL;/* Current root target */
565     int 	  errors;   /* Number of targets not remade due to errors */
566 
567     signal(SIGINT, CompatInterrupt);
568     signal(SIGTERM, CompatInterrupt);
569     signal(SIGHUP, CompatInterrupt);
570     signal(SIGQUIT, CompatInterrupt);
571 
572     for (cp = "#=|^(){};&<>*?[]:$`\\\n"; *cp != '\0'; cp++)
573 	meta[(unsigned char) *cp] = 1;
574     /* The null character serves as a sentinel in the string.  */
575     meta[0] = 1;
576 
577     ENDNode = Targ_FindNode(".END", TARG_CREATE);
578     /* If the user has defined a .BEGIN target, execute the commands attached
579      * to it.  */
580     if (!queryFlag) {
581 	gn = Targ_FindNode(".BEGIN", TARG_NOCREATE);
582 	if (gn != NULL) {
583 	    Lst_Find(&gn->commands, CompatRunCommand, gn);
584 	    if (gn->made == ERROR) {
585 		printf("\n\nStop.\n");
586 		exit(1);
587 	    }
588 	}
589     }
590 
591     /* For each entry in the list of targets to create, call CompatMake on
592      * it to create the thing. CompatMake will leave the 'made' field of gn
593      * in one of several states:
594      *	    UPTODATE	    gn was already up-to-date
595      *	    MADE	    gn was recreated successfully
596      *	    ERROR	    An error occurred while gn was being created
597      *	    ABORTED	    gn was not remade because one of its inferiors
598      *			    could not be made due to errors.  */
599     errors = 0;
600     while ((gn = (GNode *)Lst_DeQueue(targs)) != NULL) {
601 	CompatMake(gn, gn);
602 
603 	if (gn->made == UPTODATE)
604 	    printf("`%s' is up to date.\n", gn->name);
605 	else if (gn->made == ABORTED) {
606 	    printf("`%s' not remade because of errors.\n", gn->name);
607 	    errors += 1;
608 	}
609     }
610 
611     /* If the user has defined a .END target, run its commands.  */
612     if (errors == 0)
613 	Lst_Find(&ENDNode->commands, CompatRunCommand, ENDNode);
614 }
615