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