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