| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: job.c,v 1.347 2020/12/08 19:58:20 rillig Exp $ */ | | 1 | /* $NetBSD: job.c,v 1.348 2020/12/08 20:04:17 rillig Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 1988, 1989, 1990 The Regents of the University of California. | | 4 | * Copyright (c) 1988, 1989, 1990 The Regents of the University of California. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * This code is derived from software contributed to Berkeley by | | 7 | * This code is derived from software contributed to Berkeley by |
8 | * Adam de Boor. | | 8 | * Adam de Boor. |
9 | * | | 9 | * |
10 | * Redistribution and use in source and binary forms, with or without | | 10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions | | 11 | * modification, are permitted provided that the following conditions |
12 | * are met: | | 12 | * are met: |
13 | * 1. Redistributions of source code must retain the above copyright | | 13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. | | 14 | * notice, this list of conditions and the following disclaimer. |
| @@ -133,27 +133,27 @@ | | | @@ -133,27 +133,27 @@ |
133 | #ifndef USE_SELECT | | 133 | #ifndef USE_SELECT |
134 | #include <poll.h> | | 134 | #include <poll.h> |
135 | #endif | | 135 | #endif |
136 | #include <signal.h> | | 136 | #include <signal.h> |
137 | #include <utime.h> | | 137 | #include <utime.h> |
138 | | | 138 | |
139 | #include "make.h" | | 139 | #include "make.h" |
140 | #include "dir.h" | | 140 | #include "dir.h" |
141 | #include "job.h" | | 141 | #include "job.h" |
142 | #include "pathnames.h" | | 142 | #include "pathnames.h" |
143 | #include "trace.h" | | 143 | #include "trace.h" |
144 | | | 144 | |
145 | /* "@(#)job.c 8.2 (Berkeley) 3/19/94" */ | | 145 | /* "@(#)job.c 8.2 (Berkeley) 3/19/94" */ |
146 | MAKE_RCSID("$NetBSD: job.c,v 1.347 2020/12/08 19:58:20 rillig Exp $"); | | 146 | MAKE_RCSID("$NetBSD: job.c,v 1.348 2020/12/08 20:04:17 rillig Exp $"); |
147 | | | 147 | |
148 | /* | | 148 | /* |
149 | * A shell defines how the commands are run. All commands for a target are | | 149 | * A shell defines how the commands are run. All commands for a target are |
150 | * written into a single file, which is then given to the shell to execute | | 150 | * written into a single file, which is then given to the shell to execute |
151 | * the commands from it. The commands are written to the file using a few | | 151 | * the commands from it. The commands are written to the file using a few |
152 | * templates for echo control and error control. | | 152 | * templates for echo control and error control. |
153 | * | | 153 | * |
154 | * The name of the shell is the basename for the predefined shells, such as | | 154 | * The name of the shell is the basename for the predefined shells, such as |
155 | * "sh", "csh", "bash". For custom shells, it is the full pathname, and its | | 155 | * "sh", "csh", "bash". For custom shells, it is the full pathname, and its |
156 | * basename is used to select the type of shell; the longest match wins. | | 156 | * basename is used to select the type of shell; the longest match wins. |
157 | * So /usr/pkg/bin/bash has type sh, /usr/local/bin/tcsh has type csh. | | 157 | * So /usr/pkg/bin/bash has type sh, /usr/local/bin/tcsh has type csh. |
158 | * | | 158 | * |
159 | * The echoing of command lines is controlled using hasEchoCtl, echoOff, | | 159 | * The echoing of command lines is controlled using hasEchoCtl, echoOff, |
| @@ -212,26 +212,28 @@ typedef struct Shell { | | | @@ -212,26 +212,28 @@ typedef struct Shell { |
212 | const char *newline; | | 212 | const char *newline; |
213 | char commentChar; /* character used by shell for comment lines */ | | 213 | char commentChar; /* character used by shell for comment lines */ |
214 | | | 214 | |
215 | /* | | 215 | /* |
216 | * command-line flags | | 216 | * command-line flags |
217 | */ | | 217 | */ |
218 | const char *echo; /* echo commands */ | | 218 | const char *echo; /* echo commands */ |
219 | const char *exit; /* exit on error */ | | 219 | const char *exit; /* exit on error */ |
220 | } Shell; | | 220 | } Shell; |
221 | | | 221 | |
222 | typedef struct RunFlags { | | 222 | typedef struct RunFlags { |
223 | /* true if we put a no echo command into the command file */ | | 223 | /* true if we put a no echo command into the command file */ |
224 | Boolean silent; | | 224 | Boolean silent; |
| | | 225 | |
| | | 226 | Boolean always; |
225 | } RunFlags; | | 227 | } RunFlags; |
226 | | | 228 | |
227 | /* | | 229 | /* |
228 | * error handling variables | | 230 | * error handling variables |
229 | */ | | 231 | */ |
230 | static int job_errors = 0; /* number of errors reported */ | | 232 | static int job_errors = 0; /* number of errors reported */ |
231 | typedef enum AbortReason { /* why is the make aborting? */ | | 233 | typedef enum AbortReason { /* why is the make aborting? */ |
232 | ABORT_NONE, | | 234 | ABORT_NONE, |
233 | ABORT_ERROR, /* Because of an error */ | | 235 | ABORT_ERROR, /* Because of an error */ |
234 | ABORT_INTERRUPT, /* Because it was interrupted */ | | 236 | ABORT_INTERRUPT, /* Because it was interrupted */ |
235 | ABORT_WAIT /* Waiting for jobs to finish */ | | 237 | ABORT_WAIT /* Waiting for jobs to finish */ |
236 | } AbortReason; | | 238 | } AbortReason; |
237 | static AbortReason aborting = ABORT_NONE; | | 239 | static AbortReason aborting = ABORT_NONE; |
| @@ -665,42 +667,40 @@ JobFindPid(int pid, JobStatus status, Bo | | | @@ -665,42 +667,40 @@ JobFindPid(int pid, JobStatus status, Bo |
665 | Job *job; | | 667 | Job *job; |
666 | | | 668 | |
667 | for (job = job_table; job < job_table_end; job++) { | | 669 | for (job = job_table; job < job_table_end; job++) { |
668 | if (job->status == status && job->pid == pid) | | 670 | if (job->status == status && job->pid == pid) |
669 | return job; | | 671 | return job; |
670 | } | | 672 | } |
671 | if (DEBUG(JOB) && isJobs) | | 673 | if (DEBUG(JOB) && isJobs) |
672 | job_table_dump("no pid"); | | 674 | job_table_dump("no pid"); |
673 | return NULL; | | 675 | return NULL; |
674 | } | | 676 | } |
675 | | | 677 | |
676 | /* Parse leading '@', '-' and '+', which control the exact execution mode. */ | | 678 | /* Parse leading '@', '-' and '+', which control the exact execution mode. */ |
677 | static void | | 679 | static void |
678 | ParseRunOptions(char **pp, | | 680 | ParseRunOptions(char **pp, RunFlags *out_runFlags, Boolean *out_errOff) |
679 | RunFlags *out_runFlags, Boolean *out_errOff, | | | |
680 | Boolean *out_runAlways) | | | |
681 | { | | 681 | { |
682 | char *p = *pp; | | 682 | char *p = *pp; |
683 | out_runFlags->silent = FALSE; | | 683 | out_runFlags->silent = FALSE; |
684 | *out_errOff = FALSE; | | 684 | *out_errOff = FALSE; |
685 | *out_runAlways = FALSE; | | 685 | out_runFlags->always = FALSE; |
686 | | | 686 | |
687 | for (;;) { | | 687 | for (;;) { |
688 | if (*p == '@') | | 688 | if (*p == '@') |
689 | out_runFlags->silent = !DEBUG(LOUD); | | 689 | out_runFlags->silent = !DEBUG(LOUD); |
690 | else if (*p == '-') | | 690 | else if (*p == '-') |
691 | *out_errOff = TRUE; | | 691 | *out_errOff = TRUE; |
692 | else if (*p == '+') | | 692 | else if (*p == '+') |
693 | *out_runAlways = TRUE; | | 693 | out_runFlags->always = TRUE; |
694 | else | | 694 | else |
695 | break; | | 695 | break; |
696 | p++; | | 696 | p++; |
697 | } | | 697 | } |
698 | | | 698 | |
699 | pp_skip_whitespace(&p); | | 699 | pp_skip_whitespace(&p); |
700 | | | 700 | |
701 | *pp = p; | | 701 | *pp = p; |
702 | } | | 702 | } |
703 | | | 703 | |
704 | /* Escape a string for a double-quoted string literal in sh, csh and ksh. */ | | 704 | /* Escape a string for a double-quoted string literal in sh, csh and ksh. */ |
705 | static char * | | 705 | static char * |
706 | EscapeShellDblQuot(const char *cmd) | | 706 | EscapeShellDblQuot(const char *cmd) |
| @@ -732,29 +732,29 @@ JobPrintf(Job *job, const char *fmt, con | | | @@ -732,29 +732,29 @@ JobPrintf(Job *job, const char *fmt, con |
732 | static void | | 732 | static void |
733 | JobPrintln(Job *job, const char *line) | | 733 | JobPrintln(Job *job, const char *line) |
734 | { | | 734 | { |
735 | JobPrintf(job, "%s\n", line); | | 735 | JobPrintf(job, "%s\n", line); |
736 | } | | 736 | } |
737 | | | 737 | |
738 | /* | | 738 | /* |
739 | * We don't want the error-control commands showing up either, so we turn | | 739 | * We don't want the error-control commands showing up either, so we turn |
740 | * off echoing while executing them. We could put another field in the shell | | 740 | * off echoing while executing them. We could put another field in the shell |
741 | * structure to tell JobDoOutput to look for this string too, but why make | | 741 | * structure to tell JobDoOutput to look for this string too, but why make |
742 | * it any more complex than it already is? | | 742 | * it any more complex than it already is? |
743 | */ | | 743 | */ |
744 | static void | | 744 | static void |
745 | JobPrintSpecialsErrCtl(Job *job, Boolean shutUp) | | 745 | JobPrintSpecialsErrCtl(Job *job, Boolean silent) |
746 | { | | 746 | { |
747 | if (!(job->flags & JOB_SILENT) && !shutUp && commandShell->hasEchoCtl) { | | 747 | if (!(job->flags & JOB_SILENT) && !silent && commandShell->hasEchoCtl) { |
748 | JobPrintln(job, commandShell->echoOff); | | 748 | JobPrintln(job, commandShell->echoOff); |
749 | JobPrintln(job, commandShell->errOffOrExecIgnore); | | 749 | JobPrintln(job, commandShell->errOffOrExecIgnore); |
750 | JobPrintln(job, commandShell->echoOn); | | 750 | JobPrintln(job, commandShell->echoOn); |
751 | } else { | | 751 | } else { |
752 | JobPrintln(job, commandShell->errOffOrExecIgnore); | | 752 | JobPrintln(job, commandShell->errOffOrExecIgnore); |
753 | } | | 753 | } |
754 | } | | 754 | } |
755 | | | 755 | |
756 | /* | | 756 | /* |
757 | * The shell has no error control, so we need to be weird to get it to | | 757 | * The shell has no error control, so we need to be weird to get it to |
758 | * ignore any errors from the command. If echoing is turned on, we turn it | | 758 | * ignore any errors from the command. If echoing is turned on, we turn it |
759 | * off and use the errOnOrEcho template to echo the command. Leave echoing | | 759 | * off and use the errOnOrEcho template to echo the command. Leave echoing |
760 | * off so the user doesn't see the weirdness we go through to ignore errors. | | 760 | * off so the user doesn't see the weirdness we go through to ignore errors. |
| @@ -826,45 +826,44 @@ JobPrintCommand(Job *job, char *cmd) | | | @@ -826,45 +826,44 @@ JobPrintCommand(Job *job, char *cmd) |
826 | const char *const cmdp = cmd; | | 826 | const char *const cmdp = cmd; |
827 | /* | | 827 | /* |
828 | * true if we shouldn't worry about inserting special commands into | | 828 | * true if we shouldn't worry about inserting special commands into |
829 | * the input stream. | | 829 | * the input stream. |
830 | */ | | 830 | */ |
831 | Boolean noSpecials; | | 831 | Boolean noSpecials; |
832 | | | 832 | |
833 | RunFlags runFlags; | | 833 | RunFlags runFlags; |
834 | /* | | 834 | /* |
835 | * true if we turned error checking off before printing the command | | 835 | * true if we turned error checking off before printing the command |
836 | * and need to turn it back on | | 836 | * and need to turn it back on |
837 | */ | | 837 | */ |
838 | Boolean errOff; | | 838 | Boolean errOff; |
839 | Boolean runAlways; | | | |
840 | /* Template to use when printing the command */ | | 839 | /* Template to use when printing the command */ |
841 | const char *cmdTemplate; | | 840 | const char *cmdTemplate; |
842 | char *cmdStart; /* Start of expanded command */ | | 841 | char *cmdStart; /* Start of expanded command */ |
843 | char *escCmd = NULL; /* Command with quotes/backticks escaped */ | | 842 | char *escCmd = NULL; /* Command with quotes/backticks escaped */ |
844 | | | 843 | |
845 | noSpecials = !GNode_ShouldExecute(job->node); | | 844 | noSpecials = !GNode_ShouldExecute(job->node); |
846 | | | 845 | |
847 | numCommands++; | | 846 | numCommands++; |
848 | | | 847 | |
849 | Var_Subst(cmd, job->node, VARE_WANTRES, &cmd); | | 848 | Var_Subst(cmd, job->node, VARE_WANTRES, &cmd); |
850 | /* TODO: handle errors */ | | 849 | /* TODO: handle errors */ |
851 | cmdStart = cmd; | | 850 | cmdStart = cmd; |
852 | | | 851 | |
853 | cmdTemplate = "%s\n"; | | 852 | cmdTemplate = "%s\n"; |
854 | | | 853 | |
855 | ParseRunOptions(&cmd, &runFlags, &errOff, &runAlways); | | 854 | ParseRunOptions(&cmd, &runFlags, &errOff); |
856 | | | 855 | |
857 | if (runAlways && noSpecials) { | | 856 | if (runFlags.always && noSpecials) { |
858 | /* | | 857 | /* |
859 | * We're not actually executing anything... | | 858 | * We're not actually executing anything... |
860 | * but this one needs to be - use compat mode just for it. | | 859 | * but this one needs to be - use compat mode just for it. |
861 | */ | | 860 | */ |
862 | Compat_RunCommand(cmdp, job->node); | | 861 | Compat_RunCommand(cmdp, job->node); |
863 | free(cmdStart); | | 862 | free(cmdStart); |
864 | return; | | 863 | return; |
865 | } | | 864 | } |
866 | | | 865 | |
867 | /* | | 866 | /* |
868 | * If the shell doesn't have error control the alternate echo'ing will | | 867 | * If the shell doesn't have error control the alternate echo'ing will |
869 | * be done (to avoid showing additional error checking code) | | 868 | * be done (to avoid showing additional error checking code) |
870 | * and this will need the characters '$ ` \ "' escaped | | 869 | * and this will need the characters '$ ` \ "' escaped |