]>
Commit | Line | Data |
---|---|---|
2ead455b JB |
1 | diff --git a/builtins.h b/builtins.h |
2 | --- a/builtins.h | |
3 | +++ b/builtins.h | |
4 | @@ -46,6 +46,7 @@ | |
5 | #define POSIX_BUILTIN 0x20 /* This builtins is special in the Posix command search order. */ | |
6 | #define LOCALVAR_BUILTIN 0x40 /* This builtin creates local variables */ | |
7 | #define ARRAYREF_BUILTIN 0x80 /* This builtin takes array references as arguments */ | |
8 | +#define REQUIRES_BUILTIN 0x100 /* This builtin requires other files. */ | |
9 | ||
10 | #define BASE_INDENT 4 | |
11 | ||
12 | diff --git a/builtins/mkbuiltins.c b/builtins/mkbuiltins.c | |
13 | --- a/builtins/mkbuiltins.c | |
14 | +++ b/builtins/mkbuiltins.c | |
15 | @@ -69,11 +69,16 @@ extern char *strcpy (); | |
155af773 AM |
16 | #define whitespace(c) (((c) == ' ') || ((c) == '\t')) |
17 | ||
18 | /* Flag values that builtins can have. */ | |
9ecd8d09 | 19 | +/* These flags are for the C code generator, |
155af773 | 20 | + the C which is produced (./builtin.c) |
9ecd8d09 | 21 | + includes the flags definitions found |
155af773 | 22 | + in ../builtins.h */ |
35373510 | 23 | #define BUILTIN_FLAG_SPECIAL 0x01 |
24 | #define BUILTIN_FLAG_ASSIGNMENT 0x02 | |
155af773 | 25 | #define BUILTIN_FLAG_LOCALVAR 0x04 |
2ead455b JB |
26 | #define BUILTIN_FLAG_POSIX_BUILTIN 0x08 |
27 | #define BUILTIN_FLAG_ARRAYREF_ARG 0x10 | |
28 | +#define BUILTIN_FLAG_REQUIRES 0x20 | |
0b94540b AM |
29 | |
30 | #define BASE_INDENT 4 | |
35373510 | 31 | |
2ead455b JB |
32 | @@ -189,13 +194,21 @@ char *arrayvar_builtins[] = |
33 | "typeset", "unset", "wait", /*]*/ | |
35373510 | 34 | (char *)NULL |
35 | }; | |
2ead455b JB |
36 | - |
37 | + | |
35373510 | 38 | +/* The builtin commands that cause requirements on other files. */ |
155af773 | 39 | +static char *requires_builtins[] = |
35373510 | 40 | +{ |
41 | + ".", "command", "exec", "source", "inlib", | |
42 | + (char *)NULL | |
43 | +}; | |
44 | + | |
45 | /* Forward declarations. */ | |
46 | static int is_special_builtin (); | |
47 | static int is_assignment_builtin (); | |
155af773 | 48 | static int is_localvar_builtin (); |
0b94540b | 49 | static int is_posix_builtin (); |
2ead455b | 50 | static int is_arrayvar_builtin (); |
35373510 | 51 | +static int is_requires_builtin (); |
52 | ||
53 | #if !defined (HAVE_RENAME) | |
9ecd8d09 | 54 | static int rename (); |
2ead455b | 55 | @@ -856,6 +869,8 @@ builtin_handler (self, defs, arg) |
0b94540b | 56 | new->flags |= BUILTIN_FLAG_POSIX_BUILTIN; |
2ead455b JB |
57 | if (is_arrayvar_builtin (name)) |
58 | new->flags |= BUILTIN_FLAG_ARRAYREF_ARG; | |
35373510 | 59 | + if (is_requires_builtin (name)) |
60 | + new->flags |= BUILTIN_FLAG_REQUIRES; | |
61 | ||
62 | array_add ((char *)new, defs->builtins); | |
63 | building_builtin = 1; | |
2ead455b | 64 | @@ -1275,13 +1290,14 @@ write_builtins (defs, structfile, externfile) |
35373510 | 65 | else |
69ed6004 | 66 | fprintf (structfile, "(sh_builtin_func_t *)0x0, "); |
35373510 | 67 | |
2ead455b JB |
68 | - fprintf (structfile, "%s%s%s%s%s%s, %s_doc,\n", |
69 | + fprintf (structfile, "%s%s%s%s%s%s%s, %s_doc,\n", | |
35373510 | 70 | "BUILTIN_ENABLED | STATIC_BUILTIN", |
71 | (builtin->flags & BUILTIN_FLAG_SPECIAL) ? " | SPECIAL_BUILTIN" : "", | |
72 | (builtin->flags & BUILTIN_FLAG_ASSIGNMENT) ? " | ASSIGNMENT_BUILTIN" : "", | |
155af773 | 73 | (builtin->flags & BUILTIN_FLAG_LOCALVAR) ? " | LOCALVAR_BUILTIN" : "", |
0b94540b | 74 | (builtin->flags & BUILTIN_FLAG_POSIX_BUILTIN) ? " | POSIX_BUILTIN" : "", |
2ead455b | 75 | (builtin->flags & BUILTIN_FLAG_ARRAYREF_ARG) ? " | ARRAYREF_BUILTIN" : "", |
35373510 | 76 | + (builtin->flags & BUILTIN_FLAG_REQUIRES) ? " | REQUIRES_BUILTIN" : "", |
69ed6004 | 77 | document_name (builtin)); |
35373510 | 78 | |
155af773 | 79 | /* Don't translate short document summaries that are identical |
2ead455b JB |
80 | @@ -1678,6 +1694,13 @@ is_arrayvar_builtin (name) |
81 | return (_find_in_table (name, arrayvar_builtins)); | |
155af773 AM |
82 | } |
83 | ||
35373510 | 84 | +static int |
85 | +is_requires_builtin (name) | |
86 | + char *name; | |
87 | +{ | |
88 | + return (_find_in_table (name, requires_builtins)); | |
155af773 AM |
89 | +} |
90 | + | |
35373510 | 91 | #if !defined (HAVE_RENAME) |
155af773 AM |
92 | static int |
93 | rename (from, to) | |
2ead455b JB |
94 | diff --git a/doc/bash.1 b/doc/bash.1 |
95 | --- a/doc/bash.1 | |
96 | +++ b/doc/bash.1 | |
9ecd8d09 | 97 | @@ -239,6 +239,14 @@ The shell becomes restricted (see |
35373510 | 98 | .B "RESTRICTED SHELL" |
99 | below). | |
100 | .TP | |
101 | +.B \-\-rpm-requires | |
9ecd8d09 | 102 | +Produce the list of files that are required for the |
35373510 | 103 | +shell script to run. This implies '-n' and is subject |
104 | +to the same limitations as compile time error checking checking; | |
155af773 AM |
105 | +Command substitutions, Conditional expressions and |
106 | +.BR eval | |
107 | +builtin are not parsed so some dependencies may be missed. | |
108 | +.TP | |
35373510 | 109 | .B \-\-verbose |
9ecd8d09 | 110 | Equivalent to \fB\-v\fP. |
35373510 | 111 | .TP |
2ead455b JB |
112 | diff --git a/doc/bashref.texi b/doc/bashref.texi |
113 | --- a/doc/bashref.texi | |
114 | +++ b/doc/bashref.texi | |
115 | @@ -6927,6 +6927,13 @@ standard. @xref{Bash POSIX Mode}, for a description of the Bash | |
35373510 | 116 | @item --restricted |
117 | Make the shell a restricted shell (@pxref{The Restricted Shell}). | |
118 | ||
119 | +@item --rpm-requires | |
9ecd8d09 | 120 | +Produce the list of files that are required for the |
35373510 | 121 | +shell script to run. This implies '-n' and is subject |
122 | +to the same limitations as compile time error checking checking; | |
155af773 AM |
123 | +Command substitutions, Conditional expressions and @command{eval} |
124 | +are not parsed so some dependencies may be missed. | |
35373510 | 125 | + |
126 | @item --verbose | |
155af773 | 127 | Equivalent to @option{-v}. Print shell input lines as they're read. |
35373510 | 128 | |
2ead455b JB |
129 | diff --git a/eval.c b/eval.c |
130 | --- a/eval.c | |
131 | +++ b/eval.c | |
132 | @@ -138,7 +138,8 @@ reader_loop () | |
155af773 AM |
133 | |
134 | if (read_command () == 0) | |
135 | { | |
136 | - if (interactive_shell == 0 && read_but_dont_execute) | |
9ecd8d09 | 137 | + |
155af773 AM |
138 | + if (interactive_shell == 0 && (read_but_dont_execute && !rpm_requires)) |
139 | { | |
2ead455b | 140 | set_exit_status (last_command_exit_value); |
155af773 | 141 | dispose_command (global_command); |
2ead455b JB |
142 | diff --git a/execute_cmd.c b/execute_cmd.c |
143 | --- a/execute_cmd.c | |
144 | +++ b/execute_cmd.c | |
145 | @@ -561,6 +561,8 @@ async_redirect_stdin () | |
155af773 AM |
146 | |
147 | #define DESCRIBE_PID(pid) do { if (interactive) describe_pid (pid); } while (0) | |
148 | ||
149 | +extern int rpm_requires; | |
150 | + | |
151 | /* Execute the command passed in COMMAND, perhaps doing it asynchronously. | |
152 | COMMAND is exactly what read_command () places into GLOBAL_COMMAND. | |
0507c857 | 153 | ASYNCHRONOUS, if non-zero, says to do this command in the background. |
2ead455b | 154 | @@ -592,7 +594,13 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out, |
155af773 AM |
155 | |
156 | if (breaking || continuing) | |
157 | return (last_command_exit_value); | |
2ead455b | 158 | - if (read_but_dont_execute) |
155af773 AM |
159 | + if (command == 0 || (read_but_dont_execute && !rpm_requires)) |
160 | + return (EXECUTION_SUCCESS); | |
161 | + if (rpm_requires && command->type == cm_function_def) | |
162 | + return last_command_exit_value = | |
163 | + execute_intern_function (command->value.Function_def->name, | |
164 | + command->value.Function_def); | |
2ead455b JB |
165 | + if (read_but_dont_execute) |
166 | return (last_command_exit_value); | |
167 | if (command == 0) | |
155af773 | 168 | return (EXECUTION_SUCCESS); |
2ead455b | 169 | @@ -2883,7 +2891,7 @@ execute_for_command (for_command) |
9ecd8d09 AM |
170 | save_line_number = line_number; |
171 | if (check_identifier (for_command->name, 1) == 0) | |
155af773 AM |
172 | { |
173 | - if (posixly_correct && interactive_shell == 0) | |
174 | + if (posixly_correct && interactive_shell == 0 && rpm_requires == 0) | |
175 | { | |
176 | last_command_exit_value = EX_BADUSAGE; | |
177 | jump_to_top_level (ERREXIT); | |
2ead455b JB |
178 | diff --git a/execute_cmd.h b/execute_cmd.h |
179 | --- a/execute_cmd.h | |
180 | +++ b/execute_cmd.h | |
9ecd8d09 | 181 | @@ -22,6 +22,9 @@ |
155af773 AM |
182 | #define _EXECUTE_CMD_H_ |
183 | ||
184 | #include "stdc.h" | |
185 | +#include "variables.h" | |
186 | +#include "command.h" | |
35373510 | 187 | + |
35373510 | 188 | |
9ecd8d09 AM |
189 | #if defined (ARRAY_VARS) |
190 | struct func_array_state | |
2ead455b JB |
191 | diff --git a/make_cmd.c b/make_cmd.c |
192 | --- a/make_cmd.c | |
193 | +++ b/make_cmd.c | |
194 | @@ -35,6 +35,8 @@ | |
195 | #include "bashintl.h" | |
196 | ||
197 | #include "shell.h" | |
198 | +#include "builtins.h" | |
199 | +#include "builtins/common.h" | |
200 | #include "execute_cmd.h" | |
201 | #include "parser.h" | |
202 | #include "flags.h" | |
203 | @@ -839,6 +841,30 @@ make_coproc_command (name, command) | |
155af773 | 204 | return (make_command (cm_coproc, (SIMPLE_COM *)temp)); |
35373510 | 205 | } |
206 | ||
155af773 AM |
207 | +static void |
208 | +output_requirement (deptype, filename) | |
209 | +const char *deptype; | |
210 | +char *filename; | |
35373510 | 211 | +{ |
2ead455b JB |
212 | + static char *alphabet_set = "abcdefghijklmnopqrstuvwxyz" |
213 | + "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; | |
214 | + | |
155af773 AM |
215 | + if (strchr(filename, '$') || (filename[0] != '/' && strchr(filename, '/'))) |
216 | + return; | |
35373510 | 217 | + |
9ecd8d09 | 218 | + /* |
155af773 | 219 | + if the executable is called via variable substitution we can |
9ecd8d09 | 220 | + not dermine what it is at compile time. |
35373510 | 221 | + |
155af773 AM |
222 | + if the executable consists only of characters not in the |
223 | + alphabet we do not consider it a dependency just an artifact | |
224 | + of shell parsing (ex "exec < ${infile}"). | |
225 | + */ | |
35373510 | 226 | + |
155af773 AM |
227 | + if (strpbrk(filename, alphabet_set)) |
228 | + printf ("%s(%s)\n", deptype, filename); | |
35373510 | 229 | +} |
230 | + | |
231 | /* Reverse the word list and redirection list in the simple command | |
232 | has just been parsed. It seems simpler to do this here the one | |
233 | time then by any other method that I can think of. */ | |
2ead455b | 234 | @@ -856,6 +882,28 @@ clean_simple_command (command) |
35373510 | 235 | REVERSE_LIST (command->value.Simple->redirects, REDIRECT *); |
236 | } | |
155af773 | 237 | |
35373510 | 238 | + if (rpm_requires && command->value.Simple->words) |
239 | + { | |
240 | + char *cmd0; | |
241 | + char *cmd1; | |
242 | + struct builtin *b; | |
243 | + | |
244 | + cmd0 = command->value.Simple->words->word->word; | |
245 | + b = builtin_address_internal (cmd0, 0); | |
246 | + cmd1 = 0; | |
155af773 AM |
247 | + if (command->value.Simple->words->next) |
248 | + cmd1 = command->value.Simple->words->next->word->word; | |
249 | + | |
35373510 | 250 | + if (b) { |
155af773 AM |
251 | + if ( (b->flags & REQUIRES_BUILTIN) && cmd1) |
252 | + output_requirement ("executable", cmd1); | |
35373510 | 253 | + } else { |
155af773 AM |
254 | + if (!assignment(cmd0, 0)) |
255 | + output_requirement (find_function(cmd0) ? "function" : "executable", cmd0); | |
35373510 | 256 | + } |
257 | + } /*rpm_requires*/ | |
9ecd8d09 | 258 | + |
155af773 AM |
259 | + |
260 | parser_state &= ~PST_REDIRLIST; | |
35373510 | 261 | return (command); |
262 | } | |
2ead455b JB |
263 | diff --git a/shell.c b/shell.c |
264 | --- a/shell.c | |
265 | +++ b/shell.c | |
266 | @@ -196,6 +196,9 @@ int have_devfd = 0; | |
35373510 | 267 | /* The name of the .(shell)rc file. */ |
9ecd8d09 | 268 | static char *bashrc_file = DEFAULT_BASHRC; |
35373510 | 269 | |
270 | +/* Non-zero if we are finding the scripts requirements. */ | |
271 | +int rpm_requires; | |
272 | + | |
273 | /* Non-zero means to act more like the Bourne shell on startup. */ | |
274 | static int act_like_sh; | |
275 | ||
2ead455b | 276 | @@ -266,6 +269,7 @@ static const struct { |
155af773 AM |
277 | { "protected", Int, &protected_mode, (char **)0x0 }, |
278 | #endif | |
35373510 | 279 | { "rcfile", Charp, (int *)0x0, &bashrc_file }, |
280 | + { "rpm-requires", Int, &rpm_requires, (char **)0x0 }, | |
281 | #if defined (RESTRICTED_SHELL) | |
282 | { "restricted", Int, &restricted, (char **)0x0 }, | |
283 | #endif | |
2ead455b | 284 | @@ -510,6 +514,12 @@ main (argc, argv, env) |
35373510 | 285 | read_but_dont_execute = 1; |
2ead455b | 286 | #endif |
155af773 | 287 | |
35373510 | 288 | + if (rpm_requires) |
289 | + { | |
290 | + read_but_dont_execute = 1; | |
291 | + initialize_shell_builtins (); | |
292 | + } | |
155af773 | 293 | + |
35373510 | 294 | if (running_setuid && privileged_mode == 0) |
295 | disable_priv_mode (); | |
155af773 | 296 | |
2ead455b JB |
297 | diff --git a/shell.h b/shell.h |
298 | --- a/shell.h | |
299 | +++ b/shell.h | |
300 | @@ -100,6 +100,7 @@ extern int interactive, interactive_shell; | |
9ecd8d09 AM |
301 | extern int startup_state; |
302 | extern int reading_shell_script; | |
303 | extern int shell_initialized; | |
304 | +extern int rpm_requires; | |
9ecd8d09 AM |
305 | extern int bash_argv_initialized; |
306 | extern int subshell_environment; | |
307 | extern int current_command_number; |