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