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