]>
Commit | Line | Data |
---|---|---|
ccc6cda3 JA |
1 | /* make_cmd.c -- Functions for making instances of the various |
2 | parser constructs. */ | |
726f6388 JA |
3 | |
4 | /* Copyright (C) 1989 Free Software Foundation, Inc. | |
5 | ||
6 | This file is part of GNU Bash, the Bourne Again SHell. | |
7 | ||
8 | Bash is free software; you can redistribute it and/or modify it under | |
9 | the terms of the GNU General Public License as published by the Free | |
10 | Software Foundation; either version 1, or (at your option) any later | |
11 | version. | |
12 | ||
13 | Bash is distributed in the hope that it will be useful, but WITHOUT ANY | |
14 | WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
15 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
16 | for more details. | |
17 | ||
18 | You should have received a copy of the GNU General Public License along | |
19 | with Bash; see the file COPYING. If not, write to the Free Software | |
20 | Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ | |
21 | ||
ccc6cda3 JA |
22 | #include "config.h" |
23 | ||
726f6388 JA |
24 | #include <stdio.h> |
25 | #include "bashtypes.h" | |
26 | #include <sys/file.h> | |
27 | #include "filecntl.h" | |
28 | #include "bashansi.h" | |
ccc6cda3 JA |
29 | #if defined (HAVE_UNISTD_H) |
30 | # include <unistd.h> | |
31 | #endif | |
32 | ||
726f6388 JA |
33 | #include "command.h" |
34 | #include "general.h" | |
35 | #include "error.h" | |
36 | #include "flags.h" | |
37 | #include "make_cmd.h" | |
ccc6cda3 | 38 | #include "variables.h" |
726f6388 JA |
39 | #include "subst.h" |
40 | #include "input.h" | |
41 | #include "externs.h" | |
42 | ||
43 | #if defined (JOB_CONTROL) | |
44 | #include "jobs.h" | |
45 | #endif | |
46 | ||
47 | extern int line_number, current_command_line_count; | |
48 | extern int disallow_filename_globbing; | |
49 | ||
50 | WORD_DESC * | |
ccc6cda3 | 51 | make_bare_word (string) |
726f6388 JA |
52 | char *string; |
53 | { | |
54 | WORD_DESC *temp; | |
55 | ||
56 | temp = (WORD_DESC *)xmalloc (sizeof (WORD_DESC)); | |
ccc6cda3 JA |
57 | if (*string) |
58 | temp->word = savestring (string); | |
59 | else | |
726f6388 | 60 | { |
ccc6cda3 JA |
61 | temp->word = xmalloc (1); |
62 | temp->word[0] = '\0'; | |
726f6388 | 63 | } |
ccc6cda3 JA |
64 | |
65 | temp->flags = 0; | |
726f6388 JA |
66 | return (temp); |
67 | } | |
68 | ||
ccc6cda3 JA |
69 | WORD_DESC * |
70 | make_word_flags (w, string) | |
71 | WORD_DESC *w; | |
72 | char *string; | |
73 | { | |
74 | register char *s; | |
75 | ||
76 | for (s = string; *s; s++) | |
77 | switch (*s) | |
78 | { | |
79 | case '$': | |
80 | w->flags |= W_HASDOLLAR; | |
81 | break; | |
82 | case '\\': | |
83 | break; /* continue the loop */ | |
84 | case '\'': | |
85 | case '`': | |
86 | case '"': | |
87 | w->flags |= W_QUOTED; | |
88 | break; | |
89 | } | |
90 | return (w); | |
91 | } | |
92 | ||
93 | WORD_DESC * | |
94 | make_word (string) | |
95 | char *string; | |
96 | { | |
97 | WORD_DESC *temp; | |
98 | ||
99 | temp = make_bare_word (string); | |
100 | return (make_word_flags (temp, string)); | |
101 | } | |
102 | ||
726f6388 JA |
103 | WORD_DESC * |
104 | make_word_from_token (token) | |
105 | int token; | |
106 | { | |
107 | char tokenizer[2]; | |
108 | ||
109 | tokenizer[0] = token; | |
110 | tokenizer[1] = '\0'; | |
111 | ||
112 | return (make_word (tokenizer)); | |
113 | } | |
114 | ||
115 | WORD_LIST * | |
116 | make_word_list (word, link) | |
117 | WORD_DESC *word; | |
118 | WORD_LIST *link; | |
119 | { | |
120 | WORD_LIST *temp; | |
121 | ||
122 | temp = (WORD_LIST *)xmalloc (sizeof (WORD_LIST)); | |
123 | temp->word = word; | |
124 | temp->next = link; | |
125 | return (temp); | |
126 | } | |
127 | ||
128 | WORD_LIST * | |
129 | add_string_to_list (string, list) | |
130 | char *string; | |
131 | WORD_LIST *list; | |
132 | { | |
ccc6cda3 JA |
133 | WORD_LIST *temp; |
134 | ||
135 | temp = (WORD_LIST *)xmalloc (sizeof (WORD_LIST)); | |
726f6388 JA |
136 | temp->word = make_word (string); |
137 | temp->next = list; | |
138 | return (temp); | |
139 | } | |
140 | ||
726f6388 JA |
141 | COMMAND * |
142 | make_command (type, pointer) | |
143 | enum command_type type; | |
144 | SIMPLE_COM *pointer; | |
145 | { | |
146 | COMMAND *temp; | |
147 | ||
148 | temp = (COMMAND *)xmalloc (sizeof (COMMAND)); | |
149 | temp->type = type; | |
150 | temp->value.Simple = pointer; | |
ccc6cda3 | 151 | temp->value.Simple->flags = temp->flags = 0; |
726f6388 JA |
152 | temp->redirects = (REDIRECT *)NULL; |
153 | return (temp); | |
154 | } | |
155 | ||
156 | COMMAND * | |
157 | command_connect (com1, com2, connector) | |
158 | COMMAND *com1, *com2; | |
159 | int connector; | |
160 | { | |
161 | CONNECTION *temp; | |
162 | ||
163 | temp = (CONNECTION *)xmalloc (sizeof (CONNECTION)); | |
164 | temp->connector = connector; | |
165 | temp->first = com1; | |
166 | temp->second = com2; | |
167 | return (make_command (cm_connection, (SIMPLE_COM *)temp)); | |
168 | } | |
169 | ||
ccc6cda3 JA |
170 | static COMMAND * |
171 | make_for_or_select (type, name, map_list, action) | |
172 | enum command_type type; | |
726f6388 JA |
173 | WORD_DESC *name; |
174 | WORD_LIST *map_list; | |
175 | COMMAND *action; | |
176 | { | |
ccc6cda3 | 177 | FOR_COM *temp; |
726f6388 | 178 | |
ccc6cda3 | 179 | temp = (FOR_COM *)xmalloc (sizeof (FOR_COM)); |
726f6388 JA |
180 | temp->flags = 0; |
181 | temp->name = name; | |
182 | temp->map_list = map_list; | |
183 | temp->action = action; | |
ccc6cda3 | 184 | return (make_command (type, (SIMPLE_COM *)temp)); |
726f6388 JA |
185 | } |
186 | ||
726f6388 | 187 | COMMAND * |
ccc6cda3 | 188 | make_for_command (name, map_list, action) |
726f6388 JA |
189 | WORD_DESC *name; |
190 | WORD_LIST *map_list; | |
191 | COMMAND *action; | |
192 | { | |
ccc6cda3 | 193 | return (make_for_or_select (cm_for, name, map_list, action)); |
726f6388 | 194 | } |
ccc6cda3 JA |
195 | |
196 | COMMAND * | |
197 | make_select_command (name, map_list, action) | |
198 | WORD_DESC *name; | |
199 | WORD_LIST *map_list; | |
200 | COMMAND *action; | |
201 | { | |
202 | #if defined (SELECT_COMMAND) | |
203 | return (make_for_or_select (cm_select, name, map_list, action)); | |
726f6388 | 204 | #endif |
ccc6cda3 | 205 | } |
726f6388 JA |
206 | |
207 | COMMAND * | |
208 | make_group_command (command) | |
209 | COMMAND *command; | |
210 | { | |
ccc6cda3 | 211 | GROUP_COM *temp; |
726f6388 | 212 | |
ccc6cda3 | 213 | temp = (GROUP_COM *)xmalloc (sizeof (GROUP_COM)); |
726f6388 JA |
214 | temp->command = command; |
215 | return (make_command (cm_group, (SIMPLE_COM *)temp)); | |
216 | } | |
217 | ||
218 | COMMAND * | |
219 | make_case_command (word, clauses) | |
220 | WORD_DESC *word; | |
221 | PATTERN_LIST *clauses; | |
222 | { | |
223 | CASE_COM *temp; | |
224 | ||
225 | temp = (CASE_COM *)xmalloc (sizeof (CASE_COM)); | |
226 | temp->flags = 0; | |
227 | temp->word = word; | |
228 | temp->clauses = REVERSE_LIST (clauses, PATTERN_LIST *); | |
229 | return (make_command (cm_case, (SIMPLE_COM *)temp)); | |
230 | } | |
231 | ||
232 | PATTERN_LIST * | |
233 | make_pattern_list (patterns, action) | |
234 | WORD_LIST *patterns; | |
235 | COMMAND *action; | |
236 | { | |
237 | PATTERN_LIST *temp; | |
238 | ||
239 | temp = (PATTERN_LIST *)xmalloc (sizeof (PATTERN_LIST)); | |
240 | temp->patterns = REVERSE_LIST (patterns, WORD_LIST *); | |
241 | temp->action = action; | |
242 | temp->next = NULL; | |
243 | return (temp); | |
244 | } | |
245 | ||
246 | COMMAND * | |
247 | make_if_command (test, true_case, false_case) | |
248 | COMMAND *test, *true_case, *false_case; | |
249 | { | |
250 | IF_COM *temp; | |
251 | ||
252 | temp = (IF_COM *)xmalloc (sizeof (IF_COM)); | |
253 | temp->flags = 0; | |
254 | temp->test = test; | |
255 | temp->true_case = true_case; | |
256 | temp->false_case = false_case; | |
257 | return (make_command (cm_if, (SIMPLE_COM *)temp)); | |
258 | } | |
259 | ||
260 | static COMMAND * | |
ccc6cda3 | 261 | make_until_or_while (which, test, action) |
726f6388 | 262 | enum command_type which; |
ccc6cda3 | 263 | COMMAND *test, *action; |
726f6388 JA |
264 | { |
265 | WHILE_COM *temp; | |
266 | ||
267 | temp = (WHILE_COM *)xmalloc (sizeof (WHILE_COM)); | |
268 | temp->flags = 0; | |
269 | temp->test = test; | |
270 | temp->action = action; | |
271 | return (make_command (which, (SIMPLE_COM *)temp)); | |
272 | } | |
273 | ||
274 | COMMAND * | |
275 | make_while_command (test, action) | |
276 | COMMAND *test, *action; | |
277 | { | |
ccc6cda3 | 278 | return (make_until_or_while (cm_while, test, action)); |
726f6388 JA |
279 | } |
280 | ||
281 | COMMAND * | |
282 | make_until_command (test, action) | |
283 | COMMAND *test, *action; | |
284 | { | |
ccc6cda3 | 285 | return (make_until_or_while (cm_until, test, action)); |
726f6388 JA |
286 | } |
287 | ||
288 | COMMAND * | |
289 | make_bare_simple_command () | |
290 | { | |
291 | COMMAND *command; | |
ccc6cda3 JA |
292 | SIMPLE_COM *temp; |
293 | ||
294 | command = (COMMAND *)xmalloc (sizeof (COMMAND)); | |
295 | command->value.Simple = temp = (SIMPLE_COM *)xmalloc (sizeof (SIMPLE_COM)); | |
726f6388 JA |
296 | |
297 | temp->flags = 0; | |
298 | temp->line = line_number; | |
299 | temp->words = (WORD_LIST *)NULL; | |
300 | temp->redirects = (REDIRECT *)NULL; | |
ccc6cda3 | 301 | |
726f6388 JA |
302 | command->type = cm_simple; |
303 | command->redirects = (REDIRECT *)NULL; | |
304 | command->flags = 0; | |
ccc6cda3 | 305 | |
726f6388 JA |
306 | return (command); |
307 | } | |
308 | ||
309 | /* Return a command which is the connection of the word or redirection | |
310 | in ELEMENT, and the command * or NULL in COMMAND. */ | |
311 | COMMAND * | |
312 | make_simple_command (element, command) | |
313 | ELEMENT element; | |
314 | COMMAND *command; | |
315 | { | |
316 | /* If we are starting from scratch, then make the initial command | |
317 | structure. Also note that we have to fill in all the slots, since | |
318 | malloc doesn't return zeroed space. */ | |
319 | if (!command) | |
320 | command = make_bare_simple_command (); | |
ccc6cda3 | 321 | |
726f6388 JA |
322 | if (element.word) |
323 | { | |
324 | WORD_LIST *tw = (WORD_LIST *)xmalloc (sizeof (WORD_LIST)); | |
325 | tw->word = element.word; | |
326 | tw->next = command->value.Simple->words; | |
327 | command->value.Simple->words = tw; | |
328 | } | |
329 | else | |
330 | { | |
331 | REDIRECT *r = element.redirect; | |
332 | /* Due to the way <> is implemented, there may be more than a single | |
333 | redirection in element.redirect. We just follow the chain as far | |
334 | as it goes, and hook onto the end. */ | |
335 | while (r->next) | |
336 | r = r->next; | |
337 | r->next = command->value.Simple->redirects; | |
338 | command->value.Simple->redirects = element.redirect; | |
339 | } | |
340 | return (command); | |
341 | } | |
342 | ||
ccc6cda3 JA |
343 | /* Because we are Bourne compatible, we read the input for this |
344 | << or <<- redirection now, from wherever input is coming from. | |
345 | We store the input read into a WORD_DESC. Replace the text of | |
346 | the redirectee.word with the new input text. If <<- is on, | |
347 | then remove leading TABS from each line. */ | |
726f6388 JA |
348 | void |
349 | make_here_document (temp) | |
350 | REDIRECT *temp; | |
351 | { | |
ccc6cda3 JA |
352 | int kill_leading, redir_len; |
353 | char *redir_word, *document, *full_line; | |
354 | int document_index, document_size, delim_unquoted; | |
355 | ||
356 | if (temp->instruction != r_deblank_reading_until && | |
357 | temp->instruction != r_reading_until) | |
358 | { | |
359 | internal_error ("make_here_document: bad instruction type %d", temp->instruction); | |
360 | return; | |
361 | } | |
362 | ||
363 | kill_leading = temp->instruction == r_deblank_reading_until; | |
364 | ||
365 | document = (char *)NULL; | |
366 | document_index = document_size = 0; | |
367 | ||
368 | /* Quote removal is the only expansion performed on the delimiter | |
369 | for here documents, making it an extremely special case. */ | |
370 | redir_word = string_quote_removal (temp->redirectee.filename->word, 0); | |
371 | ||
372 | /* redirection_expand will return NULL if the expansion results in | |
373 | multiple words or no words. Check for that here, and just abort | |
374 | this here document if it does. */ | |
375 | if (redir_word) | |
376 | redir_len = strlen (redir_word); | |
377 | else | |
378 | { | |
379 | temp->here_doc_eof = xmalloc (1); | |
380 | temp->here_doc_eof[0] = '\0'; | |
381 | goto document_done; | |
382 | } | |
726f6388 | 383 | |
ccc6cda3 JA |
384 | free (temp->redirectee.filename->word); |
385 | temp->here_doc_eof = redir_word; | |
386 | ||
387 | /* Read lines from wherever lines are coming from. | |
388 | For each line read, if kill_leading, then kill the | |
389 | leading tab characters. | |
390 | If the line matches redir_word exactly, then we have | |
391 | manufactured the document. Otherwise, add the line to the | |
392 | list of lines in the document. */ | |
393 | ||
394 | /* If the here-document delimiter was quoted, the lines should | |
395 | be read verbatim from the input. If it was not quoted, we | |
396 | need to perform backslash-quoted newline removal. */ | |
397 | delim_unquoted = (temp->redirectee.filename->flags & W_QUOTED) == 0; | |
398 | while (full_line = read_secondary_line (delim_unquoted)) | |
726f6388 | 399 | { |
ccc6cda3 JA |
400 | register char *line; |
401 | int len; | |
402 | ||
403 | line = full_line; | |
404 | line_number++; | |
405 | ||
406 | if (kill_leading && *line) | |
407 | { | |
408 | /* Hack: To be compatible with some Bourne shells, we | |
409 | check the word before stripping the whitespace. This | |
410 | is a hack, though. */ | |
411 | if (STREQN (line, redir_word, redir_len) && line[redir_len] == '\n') | |
412 | goto document_done; | |
413 | ||
414 | while (*line == '\t') | |
415 | line++; | |
416 | } | |
417 | ||
418 | if (*line == 0) | |
419 | continue; | |
420 | ||
421 | if (STREQN (line, redir_word, redir_len) && line[redir_len] == '\n') | |
422 | goto document_done; | |
423 | ||
424 | len = strlen (line); | |
425 | if (len + document_index >= document_size) | |
726f6388 | 426 | { |
ccc6cda3 JA |
427 | document_size = document_size ? 2 * (document_size + len) : 1000; |
428 | document = xrealloc (document, document_size); | |
726f6388 | 429 | } |
ccc6cda3 JA |
430 | |
431 | /* len is guaranteed to be > 0 because of the check for line | |
432 | being an empty string before the call to strlen. */ | |
433 | FASTCOPY (line, document + document_index, len); | |
434 | document_index += len; | |
435 | } | |
436 | ||
437 | document_done: | |
438 | if (document) | |
439 | document[document_index] = '\0'; | |
440 | else | |
441 | { | |
442 | document = xmalloc (1); | |
443 | document[0] = '\0'; | |
726f6388 | 444 | } |
ccc6cda3 | 445 | temp->redirectee.filename->word = document; |
726f6388 | 446 | } |
ccc6cda3 JA |
447 | |
448 | /* Generate a REDIRECT from SOURCE, DEST, and INSTRUCTION. | |
726f6388 JA |
449 | INSTRUCTION is the instruction type, SOURCE is a file descriptor, |
450 | and DEST is a file descriptor or a WORD_DESC *. */ | |
451 | REDIRECT * | |
452 | make_redirection (source, instruction, dest_and_filename) | |
453 | int source; | |
454 | enum r_instruction instruction; | |
455 | REDIRECTEE dest_and_filename; | |
456 | { | |
457 | REDIRECT *temp = (REDIRECT *)xmalloc (sizeof (REDIRECT)); | |
458 | ||
459 | /* First do the common cases. */ | |
460 | temp->redirector = source; | |
461 | temp->redirectee = dest_and_filename; | |
462 | temp->instruction = instruction; | |
463 | temp->flags = 0; | |
464 | temp->next = (REDIRECT *)NULL; | |
465 | ||
466 | switch (instruction) | |
467 | { | |
468 | ||
469 | case r_output_direction: /* >foo */ | |
470 | case r_output_force: /* >| foo */ | |
471 | temp->flags = O_TRUNC | O_WRONLY | O_CREAT; | |
472 | break; | |
473 | ||
474 | case r_input_direction: /* <foo */ | |
475 | case r_inputa_direction: /* foo & makes this. */ | |
476 | temp->flags = O_RDONLY; | |
477 | break; | |
478 | ||
479 | case r_appending_to: /* >>foo */ | |
480 | temp->flags = O_APPEND | O_WRONLY | O_CREAT; | |
481 | break; | |
482 | ||
483 | case r_deblank_reading_until: /* <<-foo */ | |
484 | case r_reading_until: /* << foo */ | |
485 | break; | |
486 | ||
ccc6cda3 | 487 | case r_close_this: /* <&- */ |
726f6388 JA |
488 | case r_duplicating_input: /* 1<&2 */ |
489 | case r_duplicating_output: /* 1>&2 */ | |
726f6388 JA |
490 | case r_duplicating_input_word: /* 1<&$foo */ |
491 | case r_duplicating_output_word: /* 1>&$foo */ | |
492 | break; | |
ccc6cda3 | 493 | |
726f6388 JA |
494 | case r_err_and_out: /* command &>filename */ |
495 | temp->flags = O_TRUNC | O_WRONLY | O_CREAT; | |
496 | break; | |
497 | ||
498 | case r_input_output: | |
499 | temp->flags = O_RDWR | O_CREAT; | |
500 | break; | |
501 | ||
502 | default: | |
ccc6cda3 | 503 | programming_error ("make_redirection: redirection instruction `%d' out of range", instruction); |
726f6388 JA |
504 | abort (); |
505 | break; | |
506 | } | |
507 | return (temp); | |
508 | } | |
509 | ||
510 | COMMAND * | |
ccc6cda3 | 511 | make_function_def (name, command, lineno, lstart) |
726f6388 JA |
512 | WORD_DESC *name; |
513 | COMMAND *command; | |
ccc6cda3 | 514 | int lineno, lstart; |
726f6388 JA |
515 | { |
516 | FUNCTION_DEF *temp; | |
517 | ||
518 | temp = (FUNCTION_DEF *)xmalloc (sizeof (FUNCTION_DEF)); | |
519 | temp->command = command; | |
520 | temp->name = name; | |
ccc6cda3 JA |
521 | temp->line = lineno; |
522 | temp->ignore = 0; | |
523 | command->line = lstart; | |
726f6388 JA |
524 | return (make_command (cm_function_def, (SIMPLE_COM *)temp)); |
525 | } | |
526 | ||
527 | /* Reverse the word list and redirection list in the simple command | |
528 | has just been parsed. It seems simpler to do this here the one | |
529 | time then by any other method that I can think of. */ | |
530 | COMMAND * | |
531 | clean_simple_command (command) | |
532 | COMMAND *command; | |
533 | { | |
534 | if (command->type != cm_simple) | |
ccc6cda3 | 535 | programming_error ("clean_simple_command: bad command type `%d'", command->type); |
726f6388 JA |
536 | else |
537 | { | |
538 | command->value.Simple->words = | |
539 | REVERSE_LIST (command->value.Simple->words, WORD_LIST *); | |
ccc6cda3 | 540 | command->value.Simple->redirects = |
726f6388 JA |
541 | REVERSE_LIST (command->value.Simple->redirects, REDIRECT *); |
542 | } | |
543 | ||
544 | return (command); | |
545 | } | |
546 | ||
726f6388 JA |
547 | /* The Yacc grammar productions have a problem, in that they take a |
548 | list followed by an ampersand (`&') and do a simple command connection, | |
549 | making the entire list effectively asynchronous, instead of just | |
550 | the last command. This means that when the list is executed, all | |
551 | the commands have stdin set to /dev/null when job control is not | |
552 | active, instead of just the last. This is wrong, and needs fixing | |
553 | up. This function takes the `&' and applies it to the last command | |
554 | in the list. This is done only for lists connected by `;'; it makes | |
555 | `;' bind `tighter' than `&'. */ | |
556 | COMMAND * | |
557 | connect_async_list (command, command2, connector) | |
558 | COMMAND *command, *command2; | |
559 | int connector; | |
560 | { | |
561 | COMMAND *t, *t1, *t2; | |
562 | ||
563 | t1 = command; | |
564 | t = command->value.Connection->second; | |
565 | ||
566 | if (!t || (command->flags & CMD_WANT_SUBSHELL) || | |
567 | command->value.Connection->connector != ';') | |
568 | { | |
569 | t = command_connect (command, command2, connector); | |
570 | return t; | |
571 | } | |
572 | ||
573 | /* This is just defensive programming. The Yacc precedence rules | |
574 | will generally hand this function a command where t points directly | |
575 | to the command we want (e.g. given a ; b ; c ; d &, t1 will point | |
576 | to the `a ; b ; c' list and t will be the `d'). We only want to do | |
577 | this if the list is not being executed as a unit in the background | |
578 | with `( ... )', so we have to check for CMD_WANT_SUBSHELL. That's | |
579 | the only way to tell. */ | |
580 | while (((t->flags & CMD_WANT_SUBSHELL) == 0) && t->type == cm_connection && | |
581 | t->value.Connection->connector == ';') | |
582 | { | |
583 | t1 = t; | |
584 | t = t->value.Connection->second; | |
585 | } | |
586 | /* Now we have t pointing to the last command in the list, and | |
587 | t1->value.Connection->second == t. */ | |
588 | t2 = command_connect (t, command2, connector); | |
589 | t1->value.Connection->second = t2; | |
590 | return command; | |
591 | } |