]> git.ipfire.org Git - thirdparty/bash.git/blame - subst.c
Imported from ../bash-1.14.7.tar.gz.
[thirdparty/bash.git] / subst.c
CommitLineData
726f6388
JA
1/* subst.c -- The part of the shell that does parameter, command, and
2 globbing substitutions. */
3
4/* Copyright (C) 1987,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 2, 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 "bashtypes.h"
23#include <stdio.h>
24#include <pwd.h>
25#include <signal.h>
26#include <errno.h>
27/* Not all systems declare ERRNO in errno.h... and some systems #define it! */
28#if !defined (errno)
29extern int errno;
30#endif /* !errno */
31
32#include "bashansi.h"
33#include "posixstat.h"
34
35#include "shell.h"
36#include "flags.h"
37#include "jobs.h"
38#include "execute_cmd.h"
39#include "filecntl.h"
40
41#if defined (READLINE)
42# include <readline/readline.h>
43#else
44# include <tilde/tilde.h>
45#endif
46
47#if defined (HISTORY)
48# include "bashhist.h"
49# include <readline/history.h>
50#endif
51
52#include <glob/fnmatch.h>
53#include "builtins/getopt.h"
54
55/* The size that strings change by. */
56#define DEFAULT_ARRAY_SIZE 512
57
58/* How to quote and determine the quoted state of the character C. */
59static char *make_quoted_char ();
60#define QUOTED_CHAR(c) ((c) == CTLESC)
61
62/* Process ID of the last command executed within command substitution. */
63pid_t last_command_subst_pid = NO_PID;
64
65/* Extern functions and variables from different files. */
66extern int last_command_exit_value, interactive, interactive_shell;
67extern int subshell_environment;
68extern int dollar_dollar_pid, no_brace_expansion;
69extern int posixly_correct;
70extern int eof_encountered, eof_encountered_limit, ignoreeof;
71extern char *this_command_name;
72extern jmp_buf top_level;
73#if defined (READLINE)
74extern int no_line_editing;
75extern int hostname_list_initialized;
76#endif
77
78#if !defined (USE_POSIX_GLOB_LIBRARY)
79extern int glob_dot_filenames, noglob_dot_filenames;
80extern char *glob_error_return;
81#endif
82
83static WORD_LIST expand_word_error, expand_word_fatal;
84static char expand_param_error, expand_param_fatal;
85
86static WORD_LIST *expand_string_internal ();
87static WORD_LIST *expand_word_internal (), *expand_words_internal ();
88static WORD_LIST *expand_string_leave_quoted ();
89static WORD_LIST *word_list_split ();
90static char *quote_string ();
91static int unquoted_substring (), unquoted_member ();
92static int unquoted_glob_pattern_p ();
93static void quote_list (), dequote_list ();
94static int do_assignment_internal ();
95static char *string_extract_verbatim (), *string_extract ();
96static char *string_extract_double_quoted (), *string_extract_single_quoted ();
97static char *extract_delimited_string ();
98static char *extract_dollar_brace_string ();
99
100/* **************************************************************** */
101/* */
102/* Utility Functions */
103/* */
104/* **************************************************************** */
105
106/* Cons a new string from STRING starting at START and ending at END,
107 not including END. */
108char *
109substring (string, start, end)
110 char *string;
111 int start, end;
112{
113 register int len = end - start;
114 register char *result = xmalloc (len + 1);
115
116 strncpy (result, string + start, len);
117 result[len] = '\0';
118 return (result);
119}
120
121/* Conventions:
122
123 A string with s[0] == CTLNUL && s[1] == 0 is a quoted null string.
124 The parser passes CTLNUL as CTLESC CTLNUL. */
125
126/* The parser passes us CTLESC as CTLESC CTLESC and CTLNUL as CTLESC CTLNUL.
127 This is necessary to make unquoted CTLESC and CTLNUL characters in the
128 data stream pass through properly.
129 Here we remove doubled CTLESC characters inside quoted strings before
130 quoting the entire string, so we do not double the number of CTLESC
131 characters. */
132static char *
133remove_quoted_escapes (string)
134 char *string;
135{
136 register char *s;
137
138 for (s = string; s && *s; s++)
139 {
140 if (*s == CTLESC && (s[1] == CTLESC || s[1] == CTLNUL))
141 strcpy (s, s + 1); /* XXX - should be memmove */
142 }
143 return (string);
144}
145
146/* Quote escape characters in string s, but no other characters. This is
147 used to protect CTLESC and CTLNUL in variable values from the rest of
148 the word expansion process after the variable is expanded. */
149static char *
150quote_escapes (string)
151 char *string;
152{
153 register char *s, *t;
154 char *result;
155
156 result = xmalloc ((strlen (string) * 2) + 1);
157 for (s = string, t = result; s && *s; )
158 {
159 if (*s == CTLESC || *s == CTLNUL)
160 *t++ = CTLESC;
161 *t++ = *s++;
162 }
163 *t = '\0';
164 return (result);
165}
166
167/* Just like string_extract, but doesn't hack backslashes or any of
168 that other stuff. Obeys quoting. Used to do splitting on $IFS. */
169static char *
170string_extract_verbatim (string, sindex, charlist)
171 char *string, *charlist;
172 int *sindex;
173{
174 register int i = *sindex;
175 int c;
176 char *temp;
177
178 if (charlist[0] == '\'' && !charlist[1])
179 {
180 temp = string_extract_single_quoted (string, sindex);
181 i = *sindex - 1;
182 *sindex = i;
183 return (temp);
184 }
185
186 for (i = *sindex; (c = string[i]); i++)
187 {
188 if (c == CTLESC)
189 {
190 i++;
191 continue;
192 }
193
194 if (MEMBER (c, charlist))
195 break;
196 }
197
198 temp = xmalloc (1 + (i - *sindex));
199 strncpy (temp, string + (*sindex), i - (*sindex));
200 temp[i - (*sindex)] = '\0';
201 *sindex = i;
202
203 return (temp);
204}
205
206/* Extract a substring from STRING, starting at SINDEX and ending with
207 one of the characters in CHARLIST. Don't make the ending character
208 part of the string. Leave SINDEX pointing at the ending character.
209 Understand about backslashes in the string. */
210static char *
211string_extract (string, sindex, charlist)
212 char *string, *charlist;
213 int *sindex;
214{
215 register int c, i = *sindex;
216 char *temp;
217
218 while (c = string[i])
219 {
220 if (c == '\\')
221 if (string[i + 1])
222 i++;
223 else
224 break;
225 else
226 if (MEMBER (c, charlist))
227 break;
228 i++;
229 }
230 temp = xmalloc (1 + (i - *sindex));
231 strncpy (temp, string + (*sindex), i - (*sindex));
232 temp[i - (*sindex)] = '\0';
233 *sindex = i;
234 return (temp);
235}
236
237/* Remove backslashes which are quoting backquotes from STRING. Modifies
238 STRING, and returns a pointer to it. */
239char *
240de_backslash (string)
241 char *string;
242{
243 register int i, l = strlen (string);
244
245 for (i = 0; i < l; i++)
246 if (string[i] == '\\' && (string[i + 1] == '`' || string[i + 1] == '\\' ||
247 string[i + 1] == '$'))
248 strcpy (string + i, string + i + 1); /* XXX - should be memmove */
249 return (string);
250}
251
252#if 0
253/* Replace instances of \! in a string with !. */
254void
255unquote_bang (string)
256 char *string;
257{
258 register int i, j;
259 register char *temp;
260
261 temp = xmalloc (1 + strlen (string));
262
263 for (i = 0, j = 0; (temp[j] = string[i]); i++, j++)
264 {
265 if (string[i] == '\\' && string[i + 1] == '!')
266 {
267 temp[j] = '!';
268 i++;
269 }
270 }
271 strcpy (string, temp);
272 free (temp);
273}
274#endif
275
276/* Extract the $( construct in STRING, and return a new string.
277 Start extracting at (SINDEX) as if we had just seen "$(".
278 Make (SINDEX) get the position just after the matching ")". */
279char *
280extract_command_subst (string, sindex)
281 char *string;
282 int *sindex;
283{
284 return (extract_delimited_string (string, sindex, "$(", "(", ")"));
285}
286
287/* Extract the $[ construct in STRING, and return a new string.
288 Start extracting at (SINDEX) as if we had just seen "$[".
289 Make (SINDEX) get the position just after the matching "]". */
290char *
291extract_arithmetic_subst (string, sindex)
292 char *string;
293 int *sindex;
294{
295 return (extract_delimited_string (string, sindex, "$[", "[", "]"));
296}
297
298#if defined (PROCESS_SUBSTITUTION)
299/* Extract the <( or >( construct in STRING, and return a new string.
300 Start extracting at (SINDEX) as if we had just seen "<(".
301 Make (SINDEX) get the position just after the matching ")". */
302char *
303extract_process_subst (string, starter, sindex)
304 char *string;
305 char *starter;
306 int *sindex;
307{
308 return (extract_delimited_string (string, sindex, starter, "(", ")"));
309}
310#endif /* PROCESS_SUBSTITUTION */
311
312/* Extract and create a new string from the contents of STRING, a
313 character string delimited with OPENER and CLOSER. SINDEX is
314 the address of an int describing the current offset in STRING;
315 it should point to just after the first OPENER found. On exit,
316 SINDEX gets the position just after the matching CLOSER. If
317 OPENER is more than a single character, ALT_OPENER, if non-null,
318 contains a character string that can also match CLOSER and thus
319 needs to be skipped. */
320static char *
321extract_delimited_string (string, sindex, opener, alt_opener, closer)
322 char *string;
323 int *sindex;
324 char *opener, *alt_opener, *closer;
325{
326 register int i, c, l;
327 int pass_character, nesting_level;
328 int delimiter, delimited_nesting_level;
329 int len_closer, len_opener, len_alt_opener;
330 char *result;
331
332 len_opener = STRLEN (opener);
333 len_alt_opener = STRLEN (alt_opener);
334 len_closer = STRLEN (closer);
335
336 pass_character = delimiter = delimited_nesting_level = 0;
337
338 nesting_level = 1;
339
340 for (i = *sindex; c = string[i]; i++)
341 {
342 if (pass_character)
343 {
344 pass_character = 0;
345 continue;
346 }
347
348 if (c == CTLESC)
349 {
350 pass_character++;
351 continue;
352 }
353
354 if (c == '\\')
355 {
356 if ((delimiter == '"') &&
357 (member (string[i + 1], slashify_in_quotes)))
358 {
359 pass_character++;
360 continue;
361 }
362 }
363
364 if (!delimiter || delimiter == '"')
365 {
366 if (STREQN (string + i, opener, len_opener))
367 {
368 if (!delimiter)
369 nesting_level++;
370 else
371 delimited_nesting_level++;
372
373 i += len_opener - 1;
374 continue;
375 }
376
377 if (len_alt_opener && STREQN (string + i, alt_opener, len_alt_opener))
378 {
379 if (!delimiter)
380 nesting_level++;
381 else
382 delimited_nesting_level++;
383
384 i += len_alt_opener - 1;
385 continue;
386 }
387
388 if (STREQN (string + i, closer, len_closer))
389 {
390 i += len_closer - 1;
391
392 if (delimiter && delimited_nesting_level)
393 delimited_nesting_level--;
394
395 if (!delimiter)
396 {
397 nesting_level--;
398 if (nesting_level == 0)
399 break;
400 }
401 }
402 }
403
404 if (delimiter)
405 {
406 if (c == delimiter || delimiter == '\\')
407 delimiter = 0;
408 continue;
409 }
410 else
411 {
412 if (c == '"' || c == '\'' || c == '\\')
413 delimiter = c;
414 }
415 }
416
417 l = i - *sindex;
418 result = xmalloc (1 + l);
419 strncpy (result, string + *sindex, l);
420 result[l] = '\0';
421 *sindex = i;
422
423 if (!c && (delimiter || nesting_level))
424 {
425 report_error ("bad substitution: no `%s' in %s", closer, string);
426 free (result);
427 longjmp (top_level, DISCARD);
428 }
429 return (result);
430}
431
432/* Extract a parameter expansion expression within ${ and } from STRING.
433 Obey the Posix.2 rules for finding the ending `}': count braces while
434 skipping over enclosed quoted strings and command substitutions.
435 SINDEX is the address of an int describing the current offset in STRING;
436 it should point to just after the first `{' found. On exit, SINDEX
437 gets the position just after the matching `}'. */
438/* XXX -- this is very similar to extract_delimited_string -- XXX */
439static char *
440extract_dollar_brace_string (string, sindex)
441 char *string;
442 int *sindex;
443{
444 register int i, c, l;
445 int pass_character, nesting_level;
446 int delimiter, delimited_nesting_level;
447 char *result;
448
449 pass_character = delimiter = delimited_nesting_level = 0;
450
451 nesting_level = 1;
452
453 for (i = *sindex; c = string[i]; i++)
454 {
455 if (pass_character)
456 {
457 pass_character = 0;
458 continue;
459 }
460
461 if (c == CTLESC)
462 {
463 pass_character++;
464 continue;
465 }
466
467 /* Backslashes quote the next character. */
468 if (c == '\\')
469 {
470 if ((delimiter == '"') &&
471 (member (string[i + 1], slashify_in_quotes)))
472 {
473 pass_character++;
474 continue;
475 }
476 }
477
478 if (!delimiter || delimiter == '"')
479 {
480 if (string[i] == '$' && string[i+1] == '{')
481 {
482 if (!delimiter)
483 nesting_level++;
484 else
485 delimited_nesting_level++;
486
487 i++;
488 continue;
489 }
490
491 /* Pass the contents of old-style command substitutions through
492 verbatim. */
493 if (string[i] == '`')
494 {
495 int si;
496 char *t;
497
498 si = i + 1;
499 t = string_extract (string, &si, "`");
500 i = si;
501 free (t);
502 continue;
503 }
504
505 /* Pass the contents of new-style command substitutions through
506 verbatim. */
507 if (string[i] == '$' && string[i+1] == '(')
508 {
509 int si;
510 char *t;
511
512 si = i + 2;
513 t = extract_delimited_string (string, &si, "$(", "(", ")");
514 i = si;
515 free (t);
516 continue;
517 }
518
519 if (string[i] == '{')
520 {
521 if (!delimiter)
522 nesting_level++;
523 else
524 delimited_nesting_level++;
525
526 continue;
527 }
528
529 if (string[i] == '}')
530 {
531 if (delimiter && delimited_nesting_level)
532 delimited_nesting_level--;
533
534 if (!delimiter)
535 {
536 nesting_level--;
537 if (nesting_level == 0)
538 break;
539 }
540 }
541 }
542
543 if (delimiter)
544 {
545 if (c == delimiter || delimiter == '\\')
546 delimiter = 0;
547 continue;
548 }
549 else
550 {
551 if (c == '"' || c == '\'' || c == '\\')
552 delimiter = c;
553 }
554 }
555
556 l = i - *sindex;
557 result = xmalloc (1 + l);
558 strncpy (result, string + *sindex, l);
559 result[l] = '\0';
560 *sindex = i;
561
562 if (!c && (delimiter || nesting_level))
563 {
564 report_error ("bad substitution: no ending `}' in %s", string);
565 free (result);
566 longjmp (top_level, DISCARD);
567 }
568 return (result);
569}
570
571/* Extract the contents of STRING as if it is enclosed in double quotes.
572 SINDEX, when passed in, is the offset of the character immediately
573 following the opening double quote; on exit, SINDEX is left pointing after
574 the closing double quote. */
575static char *
576string_extract_double_quoted (string, sindex)
577 char *string;
578 int *sindex;
579{
580 register int c, j, i;
581 char *temp; /* The new string we return. */
582 int pass_next, backquote; /* State variables for the machine. */
583
584 pass_next = backquote = 0;
585 temp = xmalloc (1 + strlen (string) - *sindex);
586
587 for (j = 0, i = *sindex; c = string[i]; i++)
588 {
589 /* Process a character that was quoted by a backslash. */
590 if (pass_next)
591 {
592 /* Posix.2 sez:
593
594 ``The backslash shall retain its special meaning as an escape
595 character only when followed by one of the characters:
596 $ ` " \ <newline>''.
597
598 We handle the double quotes here. expand_word_internal handles
599 the rest. */
600 if (c != '"')
601 temp[j++] = '\\';
602 temp[j++] = c;
603 pass_next = 0;
604 continue;
605 }
606
607 /* A backslash protects the next character. The code just above
608 handles preserving the backslash in front of any character but
609 a double quote. */
610 if (c == '\\')
611 {
612 pass_next++;
613 continue;
614 }
615
616 /* Inside backquotes, ``the portion of the quoted string from the
617 initial backquote and the characters up to the next backquote
618 that is not preceded by a backslash, having escape characters
619 removed, defines that command''. */
620 if (backquote)
621 {
622 if (c == '`')
623 backquote = 0;
624 temp[j++] = c;
625 continue;
626 }
627
628 if (c == '`')
629 {
630 temp[j++] = c;
631 backquote++;
632 continue;
633 }
634
635 /* Pass everything between `$(' and the matching `)' or a quoted
636 ${ ... } pair through according to the Posix.2 specification. */
637 if (c == '$' && ((string[i + 1] == '(') || (string[i + 1] == '{')))
638 {
639 register int t;
640 int si;
641 char *ret;
642
643 si = i + 2;
644 if (string[i + 1] == '(')
645 ret = extract_delimited_string (string, &si, "$(", "(", ")");
646 else
647 ret = extract_dollar_brace_string (string, &si);
648
649 temp[j++] = '$';
650 temp[j++] = string[i + 1];
651
652 for (t = 0; ret[t]; t++)
653 temp[j++] = ret[t];
654
655 i = si;
656 temp[j++] = string[i];
657 free (ret);
658 continue;
659 }
660
661 /* An unescaped double quote serves to terminate the string. */
662 if (c == '"')
663 break;
664
665 /* Add the character to the quoted string we're accumulating. */
666 temp[j++] = c;
667 }
668 temp[j] = '\0';
669
670 /* Point to after the closing quote. */
671 if (c)
672 i++;
673 *sindex = i;
674
675 return (temp);
676}
677
678/* Extract the contents of STRING as if it is enclosed in single quotes.
679 SINDEX, when passed in, is the offset of the character immediately
680 following the opening single quote; on exit, SINDEX is left pointing after
681 the closing single quote. */
682static char *
683string_extract_single_quoted (string, sindex)
684 char *string;
685 int *sindex;
686{
687 register int i = *sindex;
688 char *temp;
689
690 while (string[i] && string[i] != '\'')
691 i++;
692
693 temp = xmalloc (1 + i - *sindex);
694 strncpy (temp, string + *sindex, i - *sindex);
695 temp[i - *sindex] = '\0';
696
697 if (string[i])
698 i++;
699 *sindex = i;
700
701 return (temp);
702}
703
704/* Return 1 if the portion of STRING ending at EINDEX is quoted (there is
705 an unclosed quoted string), or if the character at EINDEX is quoted
706 by a backslash. */
707int
708char_is_quoted (string, eindex)
709 char *string;
710 int eindex;
711{
712 int i, pass_next, quoted;
713 char *temp;
714
715 for (i = pass_next = quoted = 0; i <= eindex; i++)
716 {
717 if (pass_next)
718 {
719 pass_next = 0;
720 if (i >= eindex) /* XXX was if (i >= eindex - 1) */
721 return 1;
722 continue;
723 }
724 else if (string[i] == '\'')
725 {
726 i++;
727 temp = string_extract_single_quoted (string, &i);
728 free (temp);
729 if (i > eindex)
730 return 1;
731 i--;
732 }
733 else if (string[i] == '"')
734 {
735 i++;
736 temp = string_extract_double_quoted (string, &i);
737 free (temp);
738 if (i > eindex)
739 return 1;
740 i--;
741 }
742 else if (string[i] == '\\')
743 {
744 pass_next = 1;
745 continue;
746 }
747 }
748 return (0);
749}
750
751#if defined (READLINE)
752int
753unclosed_pair (string, eindex, openstr)
754 char *string;
755 int eindex;
756 char *openstr;
757{
758 int i, pass_next, openc, c, olen;
759 char *temp, *s;
760
761 olen = strlen (openstr);
762 for (i = pass_next = openc = 0; i <= eindex; i++)
763 {
764 if (pass_next)
765 {
766 pass_next = 0;
767 if (i >= eindex) /* XXX was if (i >= eindex - 1) */
768 return 0;
769 continue;
770 }
771 else if (STREQN (string + i, openstr, olen))
772 {
773 openc = 1 - openc;
774 i += olen - 1;
775 }
776 else if (string[i] == '\'')
777 {
778 i++;
779 temp = string_extract_single_quoted (string, &i);
780 free (temp);
781 if (i > eindex)
782 return 0;
783 }
784 else if (string[i] == '"')
785 {
786 i++;
787 temp = string_extract_double_quoted (string, &i);
788 free (temp);
789 if (i > eindex)
790 return 0;
791 }
792 else if (string[i] == '\\')
793 {
794 pass_next = 1;
795 continue;
796 }
797 }
798 return (openc);
799}
800#endif /* READLINE */
801
802/* Extract the name of the variable to bind to from the assignment string. */
803char *
804assignment_name (string)
805 char *string;
806{
807 int offset = assignment (string);
808 char *temp;
809
810 if (!offset)
811 return (char *)NULL;
812 temp = xmalloc (offset + 1);
813 strncpy (temp, string, offset);
814 temp[offset] = '\0';
815 return (temp);
816}
817
818/* Return a single string of all the words in LIST. SEP is the separator
819 to put between individual elements of LIST in the output string. */
820static char *
821string_list_internal (list, sep)
822 WORD_LIST *list;
823 char *sep;
824{
825 register WORD_LIST *t;
826 char *result, *r;
827 int word_len, sep_len, result_size;
828
829 if (!list)
830 return ((char *)NULL);
831
832 /* This is nearly always called with either sep[0] == 0 or sep[1] == 0. */
833 sep_len = STRLEN (sep);
834 result_size = 0;
835
836 for (t = list; t; t = t->next)
837 {
838 if (t != list)
839 result_size += sep_len;
840 result_size += strlen (t->word->word);
841 }
842
843 r = result = xmalloc (result_size + 1);
844
845 for (t = list; t; t = t->next)
846 {
847 if (t != list && sep_len)
848 {
849 FASTCOPY (sep, r, sep_len);
850 r += sep_len;
851 }
852
853 word_len = strlen (t->word->word);
854 FASTCOPY (t->word->word, r, word_len);
855 r += word_len;
856 }
857
858 *r = '\0';
859 return (result);
860}
861
862/* Return a single string of all the words present in LIST, separating
863 each word with a space. */
864char *
865string_list (list)
866 WORD_LIST *list;
867{
868 return (string_list_internal (list, " "));
869}
870
871/* Return a single string of all the words present in LIST, obeying the
872 quoting rules for "$*", to wit: (P1003.2, draft 11, 3.5.2) "If the
873 expansion [of $*] appears within a double quoted string, it expands
874 to a single field with the value of each parameter separated by the
875 first character of the IFS variable, or by a <space> if IFS is unset." */
876char *
877string_list_dollar_star (list)
878 WORD_LIST *list;
879{
880 char *ifs = get_string_value ("IFS");
881 char sep[2];
882
883 if (!ifs)
884 sep[0] = ' ';
885 else if (!*ifs)
886 sep[0] = '\0';
887 else
888 sep[0] = *ifs;
889
890 sep[1] = '\0';
891
892 return (string_list_internal (list, sep));
893}
894
895/* Return the list of words present in STRING. Separate the string into
896 words at any of the characters found in SEPARATORS. If QUOTED is
897 non-zero then word in the list will have its quoted flag set, otherwise
898 the quoted flag is left as make_word () deemed fit.
899
900 This obeys the P1003.2 word splitting semantics. If `separators' is
901 exactly <space><tab><newline>, then the splitting algorithm is that of
902 the Bourne shell, which treats any sequence of characters from `separators'
903 as a delimiter. If IFS is unset, which results in `separators' being set
904 to "", no splitting occurs. If separators has some other value, the
905 following rules are applied (`IFS white space' means zero or more
906 occurrences of <space>, <tab>, or <newline>, as long as those characters
907 are in `separators'):
908
909 1) IFS white space is ignored at the start and the end of the
910 string.
911 2) Each occurrence of a character in `separators' that is not
912 IFS white space, along with any adjacent occurrences of
913 IFS white space delimits a field.
914 3) Any nonzero-length sequence of IFS white space delimits a field.
915 */
916
917/* BEWARE! list_string strips null arguments. Don't call it twice and
918 expect to have "" preserved! */
919
920/* Is the first character of STRING a quoted NULL character? */
921#define QUOTED_NULL(string) ((string)[0] == CTLNUL && (string)[1] == '\0')
922
923/* Perform quoted null character removal on STRING. We don't allow any
924 quoted null characters in the middle or at the ends of strings because
925 of how expand_word_internal works. remove_quoted_nulls () simply
926 turns STRING into an empty string iff it only consists of a quoted null. */
927/*
928#define remove_quoted_nulls(string) \
929 do { if (QUOTED_NULL (string)) string[0] ='\0'; } while (0)
930*/
931static void
932remove_quoted_nulls (string)
933 char *string;
934{
935 char *nstr, *s, *p;
936
937 nstr = savestring (string);
938 nstr[0] = '\0';
939 for (p = nstr, s = string; *s; s++)
940 {
941 if (*s == CTLESC)
942 {
943 *p++ = *s++; /* CTLESC */
944 if (*s == 0)
945 break;
946 *p++ = *s; /* quoted char */
947 continue;
948 }
949 if (*s == CTLNUL)
950 continue;
951 *p++ = *s;
952 }
953 *p = '\0';
954 strcpy (string, nstr);
955 free (nstr);
956}
957
958/* Perform quoted null character removal on each element of LIST.
959 This modifies LIST. */
960void
961word_list_remove_quoted_nulls (list)
962 WORD_LIST *list;
963{
964 register WORD_LIST *t;
965
966 t = list;
967
968 while (t)
969 {
970 remove_quoted_nulls (t->word->word);
971 t = t->next;
972 }
973}
974
975/* This performs word splitting and quoted null character removal on
976 STRING. */
977
978#define issep(c) (member ((c), separators))
979
980WORD_LIST *
981list_string (string, separators, quoted)
982 register char *string, *separators;
983 int quoted;
984{
985 WORD_LIST *result = (WORD_LIST *)NULL;
986 char *current_word = (char *)NULL, *s;
987 int sindex = 0;
988 int sh_style_split;
989
990 if (!string || !*string)
991 return ((WORD_LIST *)NULL);
992
993 sh_style_split =
994 separators && *separators && (STREQ (separators, " \t\n"));
995
996 /* Remove sequences of whitespace at the beginning of STRING, as
997 long as those characters appear in IFS. Do not do this if
998 STRING is quoted or if there are no separator characters. */
999 if (!quoted || !separators || !*separators)
1000 {
1001 for (s = string; *s && spctabnl (*s) && issep (*s); s++);
1002
1003 if (!*s)
1004 return ((WORD_LIST *)NULL);
1005
1006 string = s;
1007 }
1008
1009 /* OK, now STRING points to a word that does not begin with white space.
1010 The splitting algorithm is:
1011 extract a word, stopping at a separator
1012 skip sequences of spc, tab, or nl as long as they are separators
1013 This obeys the field splitting rules in Posix.2. */
1014
1015 while (string[sindex])
1016 {
1017 current_word = string_extract_verbatim (string, &sindex, separators);
1018 if (!current_word)
1019 break;
1020
1021 /* If we have a quoted empty string, add a quoted null argument. We
1022 want to preserve the quoted null character iff this is a quoted
1023 empty string; otherwise the quoted null characters are removed
1024 below. */
1025 if (QUOTED_NULL (current_word))
1026 {
1027 WORD_DESC *t = make_word (" ");
1028 t->quoted++;
1029 free (t->word);
1030 t->word = make_quoted_char ('\0');
1031 result = make_word_list (t, result);
1032 }
1033 else if (strlen (current_word))
1034 {
1035 /* If we have something, then add it regardless. However,
1036 perform quoted null character removal on the current word. */
1037 remove_quoted_nulls (current_word);
1038 result = make_word_list (make_word (current_word), result);
1039 if (quoted)
1040 result->word->quoted = 1;
1041 }
1042
1043 /* If we're not doing sequences of separators in the traditional
1044 Bourne shell style, then add a quoted null argument. */
1045
1046 else if (!sh_style_split && !spctabnl (string[sindex]))
1047 {
1048 result = make_word_list (make_word (""), result);
1049 result->word->quoted = 1;
1050 }
1051
1052 free (current_word);
1053
1054 /* Move past the current separator character. */
1055 if (string[sindex])
1056 sindex++;
1057
1058 /* Now skip sequences of space, tab, or newline characters if they are
1059 in the list of separators. */
1060 while (string[sindex] && spctabnl (string[sindex]) && issep (string[sindex]))
1061 sindex++;
1062
1063 }
1064 return (REVERSE_LIST (result, WORD_LIST *));
1065}
1066
1067/* Parse a single word from STRING, using SEPARATORS to separate fields.
1068 ENDPTR is set to the first character after the word. This is used by
1069 the `read' builtin.
1070 XXX - this function is very similar to list_string; they should be
1071 combined - XXX */
1072char *
1073get_word_from_string (stringp, separators, endptr)
1074 char **stringp, *separators, **endptr;
1075{
1076 register char *s;
1077 char *current_word;
1078 int sindex, sh_style_split;
1079
1080 if (!stringp || !*stringp || !**stringp)
1081 return ((char *)NULL);
1082
1083 s = *stringp;
1084
1085 sh_style_split =
1086 separators && *separators && (STREQ (separators, " \t\n"));
1087
1088 /* Remove sequences of whitespace at the beginning of STRING, as
1089 long as those characters appear in IFS. */
1090 if (sh_style_split || !separators || !*separators)
1091 {
1092 for (; *s && spctabnl (*s) && issep (*s); s++);
1093
1094 /* If the string is nothing but whitespace, update it and return. */
1095 if (!*s)
1096 {
1097 *stringp = s;
1098 if (endptr)
1099 *endptr = s;
1100 return ((char *)NULL);
1101 }
1102 }
1103
1104 /* OK, S points to a word that does not begin with white space.
1105 Now extract a word, stopping at a separator, save a pointer to
1106 the first character after the word, then skip sequences of spc,
1107 tab, or nl as long as they are separators.
1108
1109 This obeys the field splitting rules in Posix.2. */
1110 sindex = 0;
1111 current_word = string_extract_verbatim (s, &sindex, separators);
1112
1113 /* Set ENDPTR to the first character after the end of the word. */
1114 if (endptr)
1115 *endptr = s + sindex;
1116
1117 /* Move past the current separator character. */
1118 if (s[sindex])
1119 sindex++;
1120
1121 /* Now skip sequences of space, tab, or newline characters if they are
1122 in the list of separators. */
1123 while (s[sindex] && spctabnl (s[sindex]) && issep (s[sindex]))
1124 sindex++;
1125
1126 /* Update STRING to point to the next field. */
1127 *stringp = s + sindex;
1128 return (current_word);
1129}
1130
1131/* Remove IFS white space at the end of STRING. Start at the end
1132 of the string and walk backwards until the beginning of the string
1133 or we find a character that's not IFS white space and not CTLESC.
1134 Only let CTLESC escape a white space character if SAW_ESCAPE is
1135 non-zero. */
1136char *
1137strip_trailing_ifs_whitespace (string, separators, saw_escape)
1138 char *string, *separators;
1139 int saw_escape;
1140{
1141 char *s;
1142
1143 s = string + STRLEN (string) - 1;
1144 while (s > string && ((spctabnl (*s) && issep (*s)) ||
1145 (saw_escape && *s == CTLESC && spctabnl (s[1]))))
1146 s--;
1147 *++s = '\0';
1148 return string;
1149}
1150
1151#if defined (PROCESS_SUBSTITUTION)
1152#define EXP_CHAR(s) (s == '$' || s == '`' || s == '<' || s == '>' || s == CTLESC)
1153#else
1154#define EXP_CHAR(s) (s == '$' || s == '`' || s == CTLESC)
1155#endif
1156
1157/* If there are any characters in STRING that require full expansion,
1158 then call FUNC to expand STRING; otherwise just perform quote
1159 removal if necessary. This returns a new string. */
1160static char *
1161maybe_expand_string (string, quoted, func)
1162 char *string;
1163 int quoted;
1164 WORD_LIST *(*func)();
1165{
1166 WORD_LIST *list;
1167 int i, saw_quote;
1168 char *ret;
1169
1170 for (i = saw_quote = 0; string[i]; i++)
1171 {
1172 if (EXP_CHAR (string[i]))
1173 break;
1174 else if (string[i] == '\'' || string[i] == '\\' || string[i] == '"')
1175 saw_quote = 1;
1176 }
1177
1178 if (string[i])
1179 {
1180 list = (*func) (string, quoted);
1181 if (list)
1182 {
1183 ret = string_list (list);
1184 dispose_words (list);
1185 }
1186 else
1187 ret = (char *)NULL;
1188 }
1189 else if (saw_quote && !quoted)
1190 ret = string_quote_removal (string, quoted);
1191 else
1192 ret = savestring (string);
1193 return ret;
1194}
1195
1196/* Given STRING, an assignment string, get the value of the right side
1197 of the `=', and bind it to the left side. If EXPAND is true, then
1198 perform parameter expansion, command substitution, and arithmetic
1199 expansion on the right-hand side. Perform tilde expansion in any
1200 case. Do not perform word splitting on the result of expansion. */
1201static int
1202do_assignment_internal (string, expand)
1203 char *string;
1204 int expand;
1205{
1206 int offset = assignment (string);
1207 char *name = savestring (string);
1208 char *value = (char *)NULL;
1209 SHELL_VAR *entry = (SHELL_VAR *)NULL;
1210
1211 if (name[offset] == '=')
1212 {
1213 char *temp;
1214
1215 name[offset] = 0;
1216 temp = name + offset + 1;
1217
1218 if (expand && temp[0])
1219 {
1220 if (strchr (temp, '~') && unquoted_member ('~', temp))
1221 temp = tilde_expand (temp);
1222 else
1223 temp = savestring (temp);
1224
1225 value = maybe_expand_string (temp, 0, expand_string_unsplit);
1226 free (temp);
1227 }
1228 else
1229 value = savestring (temp);
1230 }
1231
1232 if (value == 0)
1233 value = savestring ("");
1234
1235 entry = bind_variable (name, value);
1236
1237 if (echo_command_at_execute)
1238 fprintf (stderr, "%s%s=%s\n", indirection_level_string (), name, value);
1239
1240 stupidly_hack_special_variables (name);
1241
1242 if (entry)
1243 entry->attributes &= ~att_invisible;
1244
1245 FREE (value);
1246 free (name);
1247
1248 /* Return 1 if the assignment seems to have been performed correctly. */
1249 return (entry ? ((entry->attributes & att_readonly) == 0) : 0);
1250}
1251
1252/* Perform the assignment statement in STRING, and expand the
1253 right side by doing command and parameter expansion. */
1254do_assignment (string)
1255 char *string;
1256{
1257 return do_assignment_internal (string, 1);
1258}
1259
1260/* Given STRING, an assignment string, get the value of the right side
1261 of the `=', and bind it to the left side. Do not do command and
1262 parameter substitution on the right hand side. */
1263do_assignment_no_expand (string)
1264 char *string;
1265{
1266 return do_assignment_internal (string, 0);
1267}
1268
1269/* Most of the substitutions must be done in parallel. In order
1270 to avoid using tons of unclear goto's, I have some functions
1271 for manipulating malloc'ed strings. They all take INDX, a
1272 pointer to an integer which is the offset into the string
1273 where manipulation is taking place. They also take SIZE, a
1274 pointer to an integer which is the current length of the
1275 character array for this string. */
1276
1277/* Append SOURCE to TARGET at INDEX. SIZE is the current amount
1278 of space allocated to TARGET. SOURCE can be NULL, in which
1279 case nothing happens. Gets rid of SOURCE by free ()ing it.
1280 Returns TARGET in case the location has changed. */
1281inline char *
1282sub_append_string (source, target, indx, size)
1283 char *source, *target;
1284 int *indx, *size;
1285{
1286 if (source)
1287 {
1288 int srclen, n;
1289
1290 srclen = strlen (source);
1291 if (srclen >= (int)(*size - *indx))
1292 {
1293 n = srclen + *indx;
1294 n = (n + DEFAULT_ARRAY_SIZE) - (n % DEFAULT_ARRAY_SIZE);
1295 target = xrealloc (target, (*size = n));
1296 }
1297
1298 FASTCOPY (source, target + *indx, srclen);
1299 *indx += srclen;
1300 target[*indx] = '\0';
1301
1302 free (source);
1303 }
1304 return (target);
1305}
1306
1307/* Append the textual representation of NUMBER to TARGET.
1308 INDX and SIZE are as in SUB_APPEND_STRING. */
1309char *
1310sub_append_number (number, target, indx, size)
1311 int number, *indx, *size;
1312 char *target;
1313{
1314 char *temp;
1315
1316 temp = itos (number);
1317 return (sub_append_string (temp, target, indx, size));
1318}
1319
1320/* Return the word list that corresponds to `$*'. */
1321WORD_LIST *
1322list_rest_of_args ()
1323{
1324 register WORD_LIST *list = (WORD_LIST *)NULL;
1325 register WORD_LIST *args = rest_of_args;
1326 int i;
1327
1328 /* Break out of the loop as soon as one of the dollar variables is null. */
1329 for (i = 1; i < 10 && dollar_vars[i]; i++)
1330 list = make_word_list (make_word (dollar_vars[i]), list);
1331
1332 while (args)
1333 {
1334 list = make_word_list (make_word (args->word->word), list);
1335 args = args->next;
1336 }
1337 return (REVERSE_LIST (list, WORD_LIST *));
1338}
1339
1340/* Make a single large string out of the dollar digit variables,
1341 and the rest_of_args. If DOLLAR_STAR is 1, then obey the special
1342 case of "$*" with respect to IFS. */
1343char *
1344string_rest_of_args (dollar_star)
1345 int dollar_star;
1346{
1347 register WORD_LIST *list = list_rest_of_args ();
1348 char *string;
1349
1350 string = dollar_star ? string_list_dollar_star (list) : string_list (list);
1351 dispose_words (list);
1352 return (string);
1353}
1354
1355/***************************************************
1356 * *
1357 * Functions to Expand a String *
1358 * *
1359 ***************************************************/
1360/* Call expand_word_internal to expand W and handle error returns.
1361 A convenience function for functions that don't want to handle
1362 any errors or free any memory before aborting. */
1363static WORD_LIST *
1364call_expand_word_internal (w, q, c, e)
1365 WORD_DESC *w;
1366 int q, *c, *e;
1367{
1368 WORD_LIST *result;
1369
1370 result = expand_word_internal (w, q, c, e);
1371 if (result == &expand_word_error)
1372 longjmp (top_level, DISCARD);
1373 else if (result == &expand_word_fatal)
1374 longjmp (top_level, FORCE_EOF);
1375 else
1376 return (result);
1377}
1378
1379/* Perform parameter expansion, command substitution, and arithmetic
1380 expansion on STRING, as if it were a word. Leave the result quoted. */
1381static WORD_LIST *
1382expand_string_internal (string, quoted)
1383 char *string;
1384 int quoted;
1385{
1386 WORD_DESC td;
1387 WORD_LIST *tresult;
1388
1389 if (!string || !*string)
1390 return ((WORD_LIST *)NULL);
1391
1392 bzero (&td, sizeof (td));
1393 td.word = string;
1394 tresult = call_expand_word_internal (&td, quoted, (int *)NULL, (int *)NULL);
1395 return (tresult);
1396}
1397
1398/* Expand STRING by performing parameter expansion, command substitution,
1399 and arithmetic expansion. Dequote the resulting WORD_LIST before
1400 returning it, but do not perform word splitting. The call to
1401 remove_quoted_nulls () is in here because word splitting normally
1402 takes care of quote removal. */
1403WORD_LIST *
1404expand_string_unsplit (string, quoted)
1405 char *string;
1406 int quoted;
1407{
1408 WORD_LIST *value;
1409
1410 if (!string || !*string)
1411 return ((WORD_LIST *)NULL);
1412
1413 value = expand_string_internal (string, quoted);
1414 if (value)
1415 {
1416 if (value->word)
1417 remove_quoted_nulls (value->word->word);
1418 dequote_list (value);
1419 }
1420 return (value);
1421}
1422
1423/* This does not perform word splitting or dequote the WORD_LIST
1424 it returns. */
1425static WORD_LIST *
1426expand_string_for_rhs (string, quoted, dollar_at_p, has_dollar_at)
1427 char *string;
1428 int quoted, *dollar_at_p, *has_dollar_at;
1429{
1430 WORD_DESC td;
1431 WORD_LIST *tresult;
1432
1433 if (string == 0 || *string == '\0')
1434 return (WORD_LIST *)NULL;
1435
1436 bzero (&td, sizeof (td));
1437 td.word = string;
1438 tresult = call_expand_word_internal (&td, quoted, dollar_at_p, has_dollar_at);
1439 return (tresult);
1440}
1441
1442/* Expand STRING just as if you were expanding a word, but do not dequote
1443 the resultant WORD_LIST. This is called only from within this file,
1444 and is used to correctly preserve quoted characters when expanding
1445 things like ${1+"$@"}. This does parameter expansion, command
1446 subsitution, arithmetic expansion, and word splitting. */
1447static WORD_LIST *
1448expand_string_leave_quoted (string, quoted)
1449 char *string;
1450 int quoted;
1451{
1452 WORD_LIST *tlist;
1453 WORD_LIST *tresult;
1454
1455 if (!string || !*string)
1456 return ((WORD_LIST *)NULL);
1457
1458 tlist = expand_string_internal (string, quoted);
1459
1460 if (tlist)
1461 {
1462 tresult = word_list_split (tlist);
1463 dispose_words (tlist);
1464 return (tresult);
1465 }
1466 return ((WORD_LIST *)NULL);
1467}
1468
1469/* Expand STRING just as if you were expanding a word. This also returns
1470 a list of words. Note that filename globbing is *NOT* done for word
1471 or string expansion, just when the shell is expanding a command. This
1472 does parameter expansion, command substitution, arithmetic expansion,
1473 and word splitting. Dequote the resultant WORD_LIST before returning. */
1474WORD_LIST *
1475expand_string (string, quoted)
1476 char *string;
1477 int quoted;
1478{
1479 WORD_LIST *result;
1480
1481 if (!string || !*string)
1482 return ((WORD_LIST *)NULL);
1483
1484 result = expand_string_leave_quoted (string, quoted);
1485
1486 if (result)
1487 dequote_list (result);
1488 return (result);
1489}
1490
1491/***************************************************
1492 * *
1493 * Functions to handle quoting chars *
1494 * *
1495 ***************************************************/
1496
1497/* I'm going to have to rewrite expansion because filename globbing is
1498 beginning to make the entire arrangement ugly. I'll do this soon. */
1499static void
1500dequote_list (list)
1501 register WORD_LIST *list;
1502{
1503 register char *s;
1504
1505 while (list)
1506 {
1507 s = dequote_string (list->word->word);
1508 free (list->word->word);
1509 list->word->word = s;
1510 list = list->next;
1511 }
1512}
1513
1514static char *
1515make_quoted_char (c)
1516 int c;
1517{
1518 char *temp;
1519
1520 temp = xmalloc (3);
1521 if (c == 0)
1522 {
1523 temp[0] = CTLNUL;
1524 temp[1] = '\0';
1525 }
1526 else
1527 {
1528 temp[0] = CTLESC;
1529 temp[1] = c;
1530 temp[2] = '\0';
1531 }
1532 return (temp);
1533}
1534
1535/* Quote STRING. Return a new string. */
1536static char *
1537quote_string (string)
1538 char *string;
1539{
1540 char *result;
1541
1542 if (!*string)
1543 {
1544 result = xmalloc (2);
1545 result[0] = CTLNUL;
1546 result[1] = '\0';
1547 }
1548 else
1549 {
1550 register char *t;
1551
1552 result = xmalloc ((strlen (string) * 2) + 1);
1553
1554 for (t = result; string && *string; )
1555 {
1556 *t++ = CTLESC;
1557 *t++ = *string++;
1558 }
1559 *t = '\0';
1560 }
1561 return (result);
1562}
1563
1564/* De-quoted quoted characters in STRING. */
1565char *
1566dequote_string (string)
1567 char *string;
1568{
1569 register char *t;
1570 char *result;
1571
1572 result = xmalloc (strlen (string) + 1);
1573
1574 if (QUOTED_NULL (string))
1575 {
1576 result[0] = '\0';
1577 return (result);
1578 }
1579
1580 /* If no character in the string can be quoted, don't bother examining
1581 each character. Just return a copy of the string passed to us. */
1582 if (strchr (string, CTLESC) == NULL) /* XXX */
1583 { /* XXX */
1584 strcpy (result, string); /* XXX */
1585 return (result); /* XXX */
1586 }
1587
1588 for (t = result; string && *string; string++)
1589 {
1590 if (*string == CTLESC)
1591 {
1592 string++;
1593
1594 if (!*string)
1595 break;
1596 }
1597
1598 *t++ = *string;
1599 }
1600
1601 *t = '\0';
1602 return (result);
1603}
1604
1605/* Quote the entire WORD_LIST list. */
1606static void
1607quote_list (list)
1608 WORD_LIST *list;
1609{
1610 register WORD_LIST *w;
1611
1612 for (w = list; w; w = w->next)
1613 {
1614 char *t = w->word->word;
1615 w->word->word = quote_string (t);
1616 free (t);
1617 w->word->quoted = 1;
1618 }
1619}
1620
1621/* **************************************************************** */
1622/* */
1623/* Functions for Removing Patterns */
1624/* */
1625/* **************************************************************** */
1626
1627/* Remove the portion of PARAM matched by PATTERN according to OP, where OP
1628 can have one of 4 values:
1629 RP_LONG_LEFT remove longest matching portion at start of PARAM
1630 RP_SHORT_LEFT remove shortest matching portion at start of PARAM
1631 RP_LONG_RIGHT remove longest matching portion at end of PARAM
1632 RP_SHORT_RIGHT remove shortest matching portion at end of PARAM
1633*/
1634
1635#define RP_LONG_LEFT 1
1636#define RP_SHORT_LEFT 2
1637#define RP_LONG_RIGHT 3
1638#define RP_SHORT_RIGHT 4
1639
1640static char *
1641remove_pattern (param, pattern, op)
1642 char *param, *pattern;
1643 int op;
1644{
1645 register int len = param ? strlen (param) : 0;
1646 register char *end = param + len;
1647 register char *p, *ret, c;
1648
1649 if (pattern == NULL || *pattern == '\0') /* minor optimization */
1650 return (savestring (param));
1651
1652 if (param == NULL || *param == '\0')
1653 return (param);
1654
1655 switch (op)
1656 {
1657 case RP_LONG_LEFT: /* remove longest match at start */
1658 for (p = end; p >= param; p--)
1659 {
1660 c = *p; *p = '\0';
1661 if (fnmatch (pattern, param, 0) != FNM_NOMATCH)
1662 {
1663 *p = c;
1664 return (savestring (p));
1665 }
1666 *p = c;
1667 }
1668 break;
1669
1670 case RP_SHORT_LEFT: /* remove shortest match at start */
1671 for (p = param; p <= end; p++)
1672 {
1673 c = *p; *p = '\0';
1674 if (fnmatch (pattern, param, 0) != FNM_NOMATCH)
1675 {
1676 *p = c;
1677 return (savestring (p));
1678 }
1679 *p = c;
1680 }
1681 break;
1682
1683 case RP_LONG_RIGHT: /* remove longest match at end */
1684 for (p = param; p <= end; p++)
1685 {
1686 if (fnmatch (pattern, p, 0) != FNM_NOMATCH)
1687 {
1688 c = *p;
1689 *p = '\0';
1690 ret = savestring (param);
1691 *p = c;
1692 return (ret);
1693 }
1694 }
1695 break;
1696
1697 case RP_SHORT_RIGHT: /* remove shortest match at end */
1698 for (p = end; p >= param; p--)
1699 {
1700 if (fnmatch (pattern, p, 0) != FNM_NOMATCH)
1701 {
1702 c = *p;
1703 *p = '\0';
1704 ret = savestring (param);
1705 *p = c;
1706 return (ret);
1707 }
1708 }
1709 break;
1710 }
1711 return (savestring (param)); /* no match, return original string */
1712}
1713
1714/*******************************************
1715 * *
1716 * Functions to expand WORD_DESCs *
1717 * *
1718 *******************************************/
1719
1720/* Expand WORD, performing word splitting on the result. This does
1721 parameter expansion, command substitution, arithmetic expansion,
1722 word splitting, and quote removal. */
1723
1724WORD_LIST *
1725expand_word (word, quoted)
1726 WORD_DESC *word;
1727 int quoted;
1728{
1729 WORD_LIST *result, *tresult;
1730
1731 tresult = call_expand_word_internal (word, quoted, (int *)NULL, (int *)NULL);
1732 result = word_list_split (tresult);
1733 dispose_words (tresult);
1734 if (result)
1735 dequote_list (result);
1736 return (result);
1737}
1738
1739/* Expand WORD, but do not perform word splitting on the result. This
1740 does parameter expansion, command substitution, arithmetic expansion,
1741 and quote removal. */
1742WORD_LIST *
1743expand_word_no_split (word, quoted)
1744 WORD_DESC *word;
1745 int quoted;
1746{
1747 WORD_LIST *result;
1748
1749 result = call_expand_word_internal (word, quoted, (int *)NULL, (int *)NULL);
1750 if (result)
1751 dequote_list (result);
1752 return (result);
1753}
1754
1755/* Perform shell expansions on WORD, but do not perform word splitting or
1756 quote removal on the result. */
1757WORD_LIST *
1758expand_word_leave_quoted (word, quoted)
1759 WORD_DESC *word;
1760 int quoted;
1761{
1762 WORD_LIST *result;
1763
1764 result = call_expand_word_internal (word, quoted, (int *)NULL, (int *)NULL);
1765 return (result);
1766}
1767
1768/* Return the value of a positional parameter. This handles values > 10. */
1769char *
1770get_dollar_var_value (ind)
1771 int ind;
1772{
1773 char *temp;
1774
1775 if (ind < 10)
1776 {
1777 if (dollar_vars[ind])
1778 temp = savestring (dollar_vars[ind]);
1779 else
1780 temp = (char *)NULL;
1781 }
1782 else /* We want something like ${11} */
1783 {
1784 WORD_LIST *p = rest_of_args;
1785
1786 ind -= 10;
1787 while (p && ind--)
1788 p = p->next;
1789 if (p)
1790 temp = savestring (p->word->word);
1791 else
1792 temp = (char *)NULL;
1793 }
1794 return (temp);
1795}
1796
1797#if defined (PROCESS_SUBSTITUTION)
1798
1799/* **************************************************************** */
1800/* */
1801/* Hacking Process Substitution */
1802/* */
1803/* **************************************************************** */
1804
1805extern struct fd_bitmap *current_fds_to_close;
1806extern char *mktemp ();
1807
1808#if !defined (HAVE_DEV_FD)
1809/* Named pipes must be removed explicitly with `unlink'. This keeps a list
1810 of FIFOs the shell has open. unlink_fifo_list will walk the list and
1811 unlink all of them. add_fifo_list adds the name of an open FIFO to the
1812 list. NFIFO is a count of the number of FIFOs in the list. */
1813#define FIFO_INCR 20
1814
1815static char **fifo_list = (char **)NULL;
1816static int nfifo = 0;
1817static int fifo_list_size = 0;
1818
1819static void
1820add_fifo_list (pathname)
1821 char *pathname;
1822{
1823 if (nfifo >= fifo_list_size - 1)
1824 {
1825 fifo_list_size += FIFO_INCR;
1826 fifo_list = (char **)xrealloc (fifo_list,
1827 fifo_list_size * sizeof (char *));
1828 }
1829
1830 fifo_list[nfifo++] = savestring (pathname);
1831}
1832
1833void
1834unlink_fifo_list ()
1835{
1836 if (!nfifo)
1837 return;
1838
1839 while (nfifo--)
1840 {
1841 unlink (fifo_list[nfifo]);
1842 free (fifo_list[nfifo]);
1843 fifo_list[nfifo] = (char *)NULL;
1844 }
1845 nfifo = 0;
1846}
1847
1848static char *
1849make_named_pipe ()
1850{
1851 char *tname;
1852
1853 tname = mktemp (savestring ("/tmp/sh-np-XXXXXX"));
1854 if (mkfifo (tname, 0600) < 0)
1855 {
1856 free (tname);
1857 return ((char *)NULL);
1858 }
1859
1860 add_fifo_list (tname);
1861 return (tname);
1862}
1863
1864#if !defined (_POSIX_VERSION)
1865int
1866mkfifo (path, mode)
1867 char *path;
1868 int mode;
1869{
1870#if defined (S_IFIFO)
1871 return (mknod (path, (mode | S_IFIFO), 0));
1872#else /* !S_IFIFO */
1873 return (-1);
1874#endif /* !S_IFIFO */
1875}
1876#endif /* !_POSIX_VERSION */
1877
1878#else /* HAVE_DEV_FD */
1879
1880/* DEV_FD_LIST is a bitmap of file descriptors attached to pipes the shell
1881 has open to children. NFDS is a count of the number of bits currently
1882 set in DEV_FD_LIST. TOTFDS is a count of the highest possible number
1883 of open files. */
1884static char *dev_fd_list = (char *)NULL;
1885static int nfds = 0;
1886static int totfds; /* The highest possible number of open files. */
1887
1888static void
1889add_fifo_list (fd)
1890 int fd;
1891{
1892 if (!dev_fd_list || fd >= totfds)
1893 {
1894 int ofds;
1895
1896 ofds = totfds;
1897 totfds = getdtablesize ();
1898 if (totfds < 0 || totfds > 256)
1899 totfds = 256;
1900 if (fd > totfds)
1901 totfds = fd + 2;
1902
1903 dev_fd_list = xrealloc (dev_fd_list, totfds);
1904 bzero (dev_fd_list + ofds, totfds - ofds);
1905 }
1906
1907 dev_fd_list[fd] = 1;
1908 nfds++;
1909}
1910
1911void
1912unlink_fifo_list ()
1913{
1914 register int i;
1915
1916 if (!nfds)
1917 return;
1918
1919 for (i = 0; nfds && i < totfds; i++)
1920 if (dev_fd_list[i])
1921 {
1922 close (i);
1923 dev_fd_list[i] = 0;
1924 nfds--;
1925 }
1926
1927 nfds = 0;
1928}
1929
1930#if defined (NOTDEF)
1931print_dev_fd_list ()
1932{
1933 register int i;
1934
1935 fprintf (stderr, "pid %d: dev_fd_list:", getpid ());
1936 fflush (stderr);
1937
1938 for (i = 0; i < totfds; i++)
1939 {
1940 if (dev_fd_list[i])
1941 fprintf (stderr, " %d", i);
1942 }
1943 fprintf (stderr, "\n");
1944}
1945#endif /* NOTDEF */
1946
1947static char *
1948make_dev_fd_filename (fd)
1949 int fd;
1950{
1951 char *ret;
1952
1953 ret = xmalloc (16 * sizeof (char));
1954 sprintf (ret, "/dev/fd/%d", fd);
1955 add_fifo_list (fd);
1956 return (ret);
1957}
1958
1959#endif /* HAVE_DEV_FD */
1960
1961/* Return a filename that will open a connection to the process defined by
1962 executing STRING. HAVE_DEV_FD, if defined, means open a pipe and return
1963 a filename in /dev/fd corresponding to a descriptor that is one of the
1964 ends of the pipe. If not defined, we use named pipes on systems that have
1965 them. Systems without /dev/fd and named pipes are out of luck.
1966
1967 OPEN_FOR_READ_IN_CHILD, if 1, means open the named pipe for reading or
1968 use the read end of the pipe and dup that file descriptor to fd 0 in
1969 the child. If OPEN_FOR_READ_IN_CHILD is 0, we open the named pipe for
1970 writing or use the write end of the pipe in the child, and dup that
1971 file descriptor to fd 1 in the child. The parent does the opposite. */
1972
1973static char *
1974process_substitute (string, open_for_read_in_child)
1975 char *string;
1976 int open_for_read_in_child;
1977{
1978 char *pathname;
1979 int fd, result;
1980 pid_t old_pid, pid;
1981#if defined (HAVE_DEV_FD)
1982 int parent_pipe_fd, child_pipe_fd;
1983 int fildes[2];
1984#endif /* HAVE_DEV_FD */
1985#if defined (JOB_CONTROL)
1986 pid_t old_pipeline_pgrp;
1987#endif
1988
1989 if (!string || !*string)
1990 return ((char *)NULL);
1991
1992#if !defined (HAVE_DEV_FD)
1993 pathname = make_named_pipe ();
1994#else /* HAVE_DEV_FD */
1995 if (pipe (fildes) < 0)
1996 {
1997 internal_error ("can't make pipes for process substitution: %s",
1998 strerror (errno));
1999 return ((char *)NULL);
2000 }
2001 /* If OPEN_FOR_READ_IN_CHILD == 1, we want to use the write end of
2002 the pipe in the parent, otherwise the read end. */
2003 parent_pipe_fd = fildes[open_for_read_in_child];
2004 child_pipe_fd = fildes[1 - open_for_read_in_child];
2005 pathname = make_dev_fd_filename (parent_pipe_fd);
2006#endif /* HAVE_DEV_FD */
2007
2008 if (!pathname)
2009 {
2010 internal_error ("cannot make pipe for process subsitution: %s",
2011 strerror (errno));
2012 return ((char *)NULL);
2013 }
2014
2015 old_pid = last_made_pid;
2016
2017#if defined (JOB_CONTROL)
2018 old_pipeline_pgrp = pipeline_pgrp;
2019 pipeline_pgrp = shell_pgrp;
2020 cleanup_the_pipeline ();
2021 pid = make_child ((char *)NULL, 1);
2022 if (pid == 0)
2023 {
2024 /* Cancel traps, in trap.c. */
2025 restore_original_signals ();
2026 setup_async_signals ();
2027 subshell_environment++;
2028 }
2029 set_sigchld_handler ();
2030 stop_making_children ();
2031 pipeline_pgrp = old_pipeline_pgrp;
2032#else /* !JOB_CONTROL */
2033 pid = make_child ((char *)NULL, 1);
2034 if (pid == 0)
2035 {
2036 /* Cancel traps, in trap.c. */
2037 restore_original_signals ();
2038 setup_async_signals ();
2039 subshell_environment++;
2040 }
2041#endif /* !JOB_CONTROL */
2042
2043 if (pid < 0)
2044 {
2045 internal_error ("cannot make a child for process substitution: %s",
2046 strerror (errno));
2047 free (pathname);
2048#if defined (HAVE_DEV_FD)
2049 close (parent_pipe_fd);
2050 close (child_pipe_fd);
2051#endif /* HAVE_DEV_FD */
2052 return ((char *)NULL);
2053 }
2054
2055 if (pid > 0)
2056 {
2057 last_made_pid = old_pid;
2058
2059#if defined (JOB_CONTROL) && defined (PGRP_PIPE)
2060 close_pgrp_pipe ();
2061#endif /* JOB_CONTROL && PGRP_PIPE */
2062
2063#if defined (HAVE_DEV_FD)
2064 close (child_pipe_fd);
2065#endif /* HAVE_DEV_FD */
2066
2067 return (pathname);
2068 }
2069
2070 set_sigint_handler ();
2071
2072#if defined (JOB_CONTROL)
2073 set_job_control (0);
2074#endif /* JOB_CONTROL */
2075
2076#if !defined (HAVE_DEV_FD)
2077 /* Open the named pipe in the child. */
2078 fd = open (pathname, open_for_read_in_child ? O_RDONLY : O_WRONLY);
2079 if (fd < 0)
2080 {
2081 internal_error ("cannot open named pipe %s for %s: %s", pathname,
2082 open_for_read_in_child ? "reading" : "writing", strerror (errno));
2083 exit (127);
2084 }
2085#else /* HAVE_DEV_FD */
2086 fd = child_pipe_fd;
2087#endif /* HAVE_DEV_FD */
2088
2089 if (dup2 (fd, open_for_read_in_child ? 0 : 1) < 0)
2090 {
2091 internal_error ("cannot duplicate named pipe %s as fd %d: %s",
2092 pathname, open_for_read_in_child ? 0 : 1, strerror (errno));
2093 exit (127);
2094 }
2095
2096 close (fd);
2097
2098 /* Need to close any files that this process has open to pipes inherited
2099 from its parent. */
2100 if (current_fds_to_close)
2101 {
2102 close_fd_bitmap (current_fds_to_close);
2103 current_fds_to_close = (struct fd_bitmap *)NULL;
2104 }
2105
2106#if defined (HAVE_DEV_FD)
2107 /* Make sure we close the parent's end of the pipe and clear the slot
2108 in the fd list so it is not closed later, if reallocated by, for
2109 instance, pipe(2). */
2110 close (parent_pipe_fd);
2111 dev_fd_list[parent_pipe_fd] = 0;
2112#endif /* HAVE_DEV_FD */
2113
2114 result = parse_and_execute (string, "process substitution", 0);
2115
2116#if !defined (HAVE_DEV_FD)
2117 /* Make sure we close the named pipe in the child before we exit. */
2118 close (open_for_read_in_child ? 0 : 1);
2119#endif /* !HAVE_DEV_FD */
2120
2121 exit (result);
2122 /*NOTREACHED*/
2123}
2124#endif /* PROCESS_SUBSTITUTION */
2125
2126/* Perform command substitution on STRING. This returns a string,
2127 possibly quoted. */
2128static char *
2129command_substitute (string, quoted)
2130 char *string;
2131 int quoted;
2132{
2133 pid_t pid, old_pid;
2134 int fildes[2];
2135 char *istring = (char *)NULL;
2136 int istring_index, istring_size, c = 1;
2137 int result;
2138
2139 istring_index = istring_size = 0;
2140
2141 /* Don't fork () if there is no need to. In the case of no command to
2142 run, just return NULL. */
2143 if (!string || !*string || (string[0] == '\n' && !string[1]))
2144 return ((char *)NULL);
2145
2146 /* Pipe the output of executing STRING into the current shell. */
2147 if (pipe (fildes) < 0)
2148 {
2149 internal_error ("Can't make pipes for command substitution!");
2150 goto error_exit;
2151 }
2152
2153 old_pid = last_made_pid;
2154#if defined (JOB_CONTROL)
2155 {
2156 pid_t old_pipeline_pgrp = pipeline_pgrp;
2157
2158 pipeline_pgrp = shell_pgrp;
2159 cleanup_the_pipeline ();
2160 pid = make_child ((char *)NULL, 0);
2161 if (pid == 0)
2162 /* Reset the signal handlers in the child, but don't free the
2163 trap strings. */
2164 reset_signal_handlers ();
2165 set_sigchld_handler ();
2166 stop_making_children ();
2167 pipeline_pgrp = old_pipeline_pgrp;
2168 }
2169#else /* !JOB_CONTROL */
2170 pid = make_child ((char *)NULL, 0);
2171
2172 if (pid == 0)
2173 /* Reset the signal handlers in the child, but don't free the
2174 trap strings. */
2175 reset_signal_handlers ();
2176#endif /* !JOB_CONTROL */
2177
2178 if (pid < 0)
2179 {
2180 internal_error ("Can't make a child for command substitution: %s",
2181 strerror (errno));
2182 error_exit:
2183
2184 FREE (istring);
2185 close (fildes[0]);
2186 close (fildes[1]);
2187 return ((char *)NULL);
2188 }
2189
2190 if (pid == 0)
2191 {
2192 set_sigint_handler (); /* XXX */
2193#if defined (JOB_CONTROL)
2194 set_job_control (0);
2195#endif
2196 if (dup2 (fildes[1], 1) < 0)
2197 {
2198 internal_error
2199 ("command_substitute: cannot duplicate pipe as fd 1: %s",
2200 strerror (errno));
2201 exit (EXECUTION_FAILURE);
2202 }
2203
2204 /* If standard output is closed in the parent shell
2205 (such as after `exec >&-'), file descriptor 1 will be
2206 the lowest available file descriptor, and end up in
2207 fildes[0]. This can happen for stdin and stderr as well,
2208 but stdout is more important -- it will cause no output
2209 to be generated from this command. */
2210 if ((fildes[1] != fileno (stdin)) &&
2211 (fildes[1] != fileno (stdout)) &&
2212 (fildes[1] != fileno (stderr)))
2213 close (fildes[1]);
2214
2215 if ((fildes[0] != fileno (stdin)) &&
2216 (fildes[0] != fileno (stdout)) &&
2217 (fildes[0] != fileno (stderr)))
2218 close (fildes[0]);
2219
2220 /* The currently executing shell is not interactive. */
2221 interactive = 0;
2222
2223 /* Command substitution does not inherit the -e flag. */
2224 exit_immediately_on_error = 0;
2225
2226 remove_quoted_escapes (string);
2227
2228 /* Give command substitution a place to jump back to on failure,
2229 so we don't go back up to main (). */
2230 result = setjmp (top_level);
2231
2232 if (result == EXITPROG)
2233 exit (last_command_exit_value);
2234 else if (result)
2235 exit (EXECUTION_FAILURE);
2236 else
2237 exit (parse_and_execute (string, "command substitution", -1));
2238 }
2239 else
2240 {
2241 FILE *istream;
2242
2243 istream = fdopen (fildes[0], "r");
2244
2245#if defined (JOB_CONTROL) && defined (PGRP_PIPE)
2246 close_pgrp_pipe ();
2247#endif /* JOB_CONTROL && PGRP_PIPE */
2248
2249 close (fildes[1]);
2250
2251 if (!istream)
2252 {
2253 internal_error ("Can't reopen pipe to command substitution (fd %d): %s",
2254 fildes[0], strerror (errno));
2255 goto error_exit;
2256 }
2257
2258 /* Read the output of the command through the pipe. */
2259 while (1)
2260 {
2261#if defined (NO_READ_RESTART_ON_SIGNAL)
2262 c = getc_with_restart (istream);
2263#else
2264 c = getc (istream);
2265#endif /* !NO_READ_RESTART_ON_SIGNAL */
2266
2267 if (c == EOF)
2268 break;
2269
2270 /* Add the character to ISTRING. */
2271 if (istring_index + 2 >= istring_size)
2272 {
2273 while (istring_index + 2 >= istring_size)
2274 istring_size += DEFAULT_ARRAY_SIZE;
2275 istring = xrealloc (istring, istring_size);
2276 }
2277
2278 if (quoted || c == CTLESC || c == CTLNUL)
2279 istring[istring_index++] = CTLESC;
2280
2281 istring[istring_index++] = c;
2282 istring[istring_index] = '\0';
2283 }
2284
2285 fclose (istream);
2286 close (fildes[0]);
2287
2288 last_command_exit_value = wait_for (pid);
2289 last_command_subst_pid = pid;
2290 last_made_pid = old_pid;
2291
2292#if defined (JOB_CONTROL)
2293 /* If last_command_exit_value > 128, then the substituted command
2294 was terminated by a signal. If that signal was SIGINT, then send
2295 SIGINT to ourselves. This will break out of loops, for instance. */
2296 if (last_command_exit_value == (128 + SIGINT))
2297 kill (getpid (), SIGINT);
2298
2299 /* wait_for gives the terminal back to shell_pgrp. If some other
2300 process group should have it, give it away to that group here. */
2301 if (interactive && pipeline_pgrp != (pid_t)0)
2302 give_terminal_to (pipeline_pgrp);
2303#endif /* JOB_CONTROL */
2304
2305 /* If we read no output, just return now and save ourselves some
2306 trouble. */
2307 if (istring_index == 0)
2308 goto error_exit;
2309
2310 /* Strip trailing newlines from the output of the command. */
2311 if (quoted)
2312 {
2313 while (istring_index > 0)
2314 {
2315 if (istring[istring_index - 1] == '\n')
2316 {
2317 --istring_index;
2318
2319 /* If the newline was quoted, remove the quoting char. */
2320 if (istring[istring_index - 1] == CTLESC)
2321 --istring_index;
2322 }
2323 else
2324 break;
2325 }
2326 istring[istring_index] = '\0';
2327 }
2328 else
2329 strip_trailing (istring, 1);
2330
2331 return (istring);
2332 }
2333}
2334
2335/********************************************************
2336 * *
2337 * Utility functions for parameter expansion *
2338 * *
2339 ********************************************************/
2340
2341/* Handle removing a pattern from a string as a result of ${name%[%]value}
2342 or ${name#[#]value}. */
2343static char *
2344parameter_brace_remove_pattern (value, temp, c)
2345 char *value, *temp;
2346 int c;
2347{
2348 int pattern_specifier;
2349 WORD_LIST *l;
2350 char *pattern, *t, *tword;
2351
2352 if (c == '#')
2353 {
2354 if (*value == '#')
2355 {
2356 value++;
2357 pattern_specifier = RP_LONG_LEFT;
2358 }
2359 else
2360 pattern_specifier = RP_SHORT_LEFT;
2361 }
2362 else /* c == '%' */
2363 {
2364 if (*value == '%')
2365 {
2366 value++;
2367 pattern_specifier = RP_LONG_RIGHT;
2368 }
2369 else
2370 pattern_specifier = RP_SHORT_RIGHT;
2371 }
2372
2373 /* Posix.2 says that the WORD should be run through tilde expansion,
2374 parameter expansion, command substitution and arithmetic expansion.
2375 This leaves the result quoted, so quote_string_for_globbing () has
2376 to be called to fix it up for fnmatch (). */
2377 if (strchr (value, '~'))
2378 tword = tilde_expand (value);
2379 else
2380 tword = savestring (value);
2381
2382 /* expand_string_internal () leaves WORD quoted and does not perform
2383 word splitting. */
2384 l = expand_string_internal (tword, 0);
2385 free (tword);
2386 pattern = string_list (l);
2387 dispose_words (l);
2388
2389 if (pattern)
2390 {
2391 tword = quote_string_for_globbing (pattern, 1);
2392 free (pattern);
2393 pattern = tword;
2394 }
2395
2396 t = remove_pattern (temp, pattern, pattern_specifier);
2397
2398 FREE (pattern);
2399 return (t);
2400}
2401
2402static int
2403valid_brace_expansion_word (name, var_is_special)
2404 char *name;
2405 int var_is_special;
2406{
2407 if (digit (*name) && all_digits (name))
2408 return 1;
2409 else if (var_is_special)
2410 return 1;
2411 else if (legal_identifier (name))
2412 return 1;
2413 else
2414 return 0;
2415}
2416/* Parameter expand NAME, and return a new string which is the expansion,
2417 or NULL if there was no expansion.
2418 VAR_IS_SPECIAL is non-zero if NAME is one of the special variables in
2419 the shell, e.g., "@", "$", "*", etc. QUOTED, if non-zero, means that
2420 NAME was found inside of a double-quoted expression. */
2421static char *
2422parameter_brace_expand_word (name, var_is_special, quoted)
2423 char *name;
2424 int var_is_special, quoted;
2425{
2426 char *temp = (char *)NULL;
2427
2428 /* Handle multiple digit arguments, as in ${11}. */
2429 if (digit (*name))
2430 {
2431 int arg_index = atoi (name);
2432
2433 temp = get_dollar_var_value (arg_index);
2434 }
2435 else if (var_is_special) /* ${@} */
2436 {
2437 char *tt;
2438 WORD_LIST *l;
2439
2440 tt = xmalloc (2 + strlen (name));
2441 tt[0] = '$'; tt[1] = '\0';
2442 strcpy (tt + 1, name);
2443 l = expand_string_leave_quoted (tt, quoted);
2444 free (tt);
2445 temp = string_list (l);
2446 dispose_words (l);
2447 }
2448 else
2449 {
2450 SHELL_VAR *var = find_variable (name);
2451
2452 if (var && !invisible_p (var) && (temp = value_cell (var)))
2453 temp = quoted && temp && *temp ? quote_string (temp)
2454 : quote_escapes (temp);
2455 }
2456 return (temp);
2457}
2458
2459/* Expand the right side of a parameter expansion of the form ${NAMEcVALUE},
2460 depending on the value of C, the separating character. C can be one of
2461 "-", "+", or "=". */
2462static char *
2463parameter_brace_expand_rhs (name, value, c, quoted)
2464 char *name, *value;
2465 int c, quoted;
2466{
2467 WORD_LIST *l;
2468 char *t, *t1, *temp;
2469 int i, lquote, hasdol;
2470
2471 if (value[0] == '~' ||
2472 (strchr (value, '~') && unquoted_substring ("=~", value)))
2473 temp = tilde_expand (value);
2474 else
2475 temp = savestring (value);
2476
2477 /* This is a hack. A better fix is coming later. */
2478 lquote = 0;
2479 if (*temp == '"' && temp[strlen (temp) - 1] == '"')
2480 {
2481 i = 1;
2482 t = string_extract_double_quoted (temp, &i); /* XXX */
2483 free (temp);
2484 temp = t;
2485 lquote = 1; /* XXX */
2486 }
2487 hasdol = 0;
2488 /* XXX was quoted not lquote */
2489 l = *temp ? expand_string_for_rhs (temp, quoted||lquote, &hasdol, (int *)NULL)
2490 : (WORD_LIST *)NULL;
2491 free (temp);
2492 /* expand_string_for_rhs does not dequote the word list it returns, but
2493 there are a few cases in which we need to add quotes. */
2494 if (lquote && quoted == 0 && hasdol == 0 && l && l->word->quoted == 0)
2495 quote_list (l);
2496
2497 if (l)
2498 {
2499 temp = string_list (l);
2500 dispose_words (l);
2501 }
2502 else if (lquote)
2503 {
2504 temp = xmalloc (2);
2505 temp[0] = CTLNUL;
2506 temp[1] = '\0';
2507 }
2508 else
2509 temp = (char *)NULL;
2510
2511 if (c == '-' || c == '+')
2512 return (temp);
2513
2514 /* c == '=' */
2515 if (temp)
2516 t = savestring (temp);
2517 else
2518 t = savestring ("");
2519 t1 = dequote_string (t);
2520 free (t);
2521 bind_variable (name, t1);
2522 free (t1);
2523 return (temp);
2524}
2525
2526/* Deal with the right hand side of a ${name:?value} expansion in the case
2527 that NAME is null or not set. If VALUE is non-null it is expanded and
2528 used as the error message to print, otherwise a standard message is
2529 printed. */
2530static void
2531parameter_brace_expand_error (name, value)
2532 char *name, *value;
2533{
2534 if (value && *value)
2535 {
2536 WORD_LIST *l = expand_string (value, 0);
2537 char *temp1 = string_list (l);
2538 report_error ("%s: %s", name, temp1 ? temp1 : value);
2539 FREE (temp1);
2540 dispose_words (l);
2541 }
2542 else
2543 report_error ("%s: parameter null or not set", name);
2544
2545 /* Free the data we have allocated during this expansion, since we
2546 are about to longjmp out. */
2547 free (name);
2548 FREE (value);
2549}
2550
2551/* Return 1 if NAME is something for which parameter_brace_expand_length is
2552 OK to do. */
2553static int
2554valid_length_expression (name)
2555 char *name;
2556{
2557 return (!name[1] || /* ${#} */
2558 ((name[1] == '@' || name[1] == '*') && !name[2]) || /* ${#@}, ${#*} */
2559 (digit (name[1]) && all_digits (name + 1)) || /* ${#11} */
2560 legal_identifier (name + 1)); /* ${#PS1} */
2561}
2562
2563/* Handle the parameter brace expansion that requires us to return the
2564 length of a parameter. */
2565static int
2566parameter_brace_expand_length (name)
2567 char *name;
2568{
2569 char *t;
2570 int number = 0;
2571
2572 if (name[1] == '\0') /* ${#} */
2573 {
2574 WORD_LIST *l = list_rest_of_args ();
2575 number = list_length (l);
2576 dispose_words (l);
2577 }
2578 else if (name[1] != '*' && name[1] != '@')
2579 {
2580 number = 0;
2581
2582 if (digit (name[1])) /* ${#1} */
2583 {
2584 if (t = get_dollar_var_value (atoi (name + 1)))
2585 {
2586 number = strlen (t);
2587 free (t);
2588 }
2589 }
2590 else /* ${#PS1} */
2591 {
2592 WORD_LIST *list;
2593 char *newname;
2594
2595 newname = savestring (name);
2596 newname[0] = '$';
2597 list = expand_string (newname, 0);
2598 t = string_list (list);
2599 free (newname);
2600 dispose_words (list);
2601
2602 if (t)
2603 number = strlen (t);
2604
2605 FREE (t);
2606 }
2607 }
2608 else /* ${#@} and ${#*} */
2609 {
2610#if !defined (KSH_INCOMPATIBLE)
2611 WORD_LIST *l = list_rest_of_args ();
2612 number = l ? list_length (l) : 0;
2613 dispose_words (l);
2614#else
2615 if (t = string_rest_of_args (1))
2616 {
2617 number = strlen (t);
2618 free (t);
2619 }
2620#endif /* KSH_INCOMPATIBLE */
2621 }
2622 return (number);
2623}
2624
2625/* Make a word list which is the parameter and variable expansion,
2626 command substitution, arithmetic substitution, and quote removed
2627 expansion of WORD. Return a pointer to a WORD_LIST which is the
2628 result of the expansion. If WORD contains a null word, the word
2629 list returned is also null.
2630
2631 QUOTED, when non-zero specifies that the text of WORD is treated
2632 as if it were surrounded by double quotes.
2633 CONTAINS_DOLLAR_AT and EXPANDED_SOMETHING are return values; when non-null
2634 they point to an integer value which receives information about expansion.
2635 CONTAINS_DOLLAR_AT gets non-zero if WORD contained "$@", else zero.
2636 EXPANDED_SOMETHING get non-zero if WORD contained any parameter expansions,
2637 else zero.
2638
2639 This only does word splitting in the case of $@ expansion. In that
2640 case, we split on ' '. */
2641
2642/* Values for the local variable quoted_state. */
2643#define UNQUOTED 0
2644#define PARTIALLY_QUOTED 1
2645#define WHOLLY_QUOTED 2
2646
2647static WORD_LIST *
2648expand_word_internal (word, quoted, contains_dollar_at, expanded_something)
2649 WORD_DESC *word;
2650 int quoted;
2651 int *contains_dollar_at;
2652 int *expanded_something;
2653{
2654 /* The thing that we finally output. */
2655 WORD_LIST *result = (WORD_LIST *)NULL;
2656
2657 /* The intermediate string that we build while expanding. */
2658 char *istring = xmalloc (DEFAULT_ARRAY_SIZE);
2659
2660 /* The current size of the above object. */
2661 int istring_size = DEFAULT_ARRAY_SIZE;
2662
2663 /* Index into ISTRING. */
2664 int istring_index = 0;
2665
2666 /* Temporary string storage. */
2667 char *temp = (char *)NULL;
2668
2669 /* The text of WORD. */
2670 register char *string = word->word;
2671
2672 /* The index into STRING. */
2673 int sindex = 0;
2674
2675 /* This gets 1 if we see a $@ while quoted. */
2676 int quoted_dollar_at = 0;
2677
2678 /* One of UNQUOTED, PARTIALLY_QUOTED, or WHOLLY_QUOTED, depending on
2679 whether WORD contains no quoting characters, a partially quoted
2680 string (e.g., "xx"ab), or is fully quoted (e.g., "xxab"). */
2681 int quoted_state = UNQUOTED;
2682
2683 register int c; /* Current character. */
2684 int number; /* Temporary number value. */
2685 int t_index; /* For calls to string_extract_xxx. */
2686 char *command_subst_result; /* For calls to command_substitute (). */
2687
2688 istring[0] = '\0';
2689
2690 if (!string) goto final_exit;
2691
2692 if (contains_dollar_at)
2693 *contains_dollar_at = 0;
2694
2695 /* Begin the expansion. */
2696
2697 for (;;)
2698 {
2699 c = string[sindex];
2700
2701 /* Case on toplevel character. */
2702 switch (c)
2703 {
2704 case '\0':
2705 goto finished_with_string;
2706
2707 case CTLESC:
2708 temp = xmalloc (3);
2709 temp[0] = CTLESC;
2710 temp[1] = c = string[++sindex];
2711 temp[2] = '\0';
2712
2713 if (string[sindex])
2714 sindex++;
2715
2716 goto add_string;
2717
2718#if defined (PROCESS_SUBSTITUTION)
2719 /* Process substitution. */
2720 case '<':
2721 case '>':
2722 {
2723 char *temp1;
2724 int old_index;
2725
2726 if (string[++sindex] != '(' || quoted || posixly_correct)
2727 {
2728 sindex--;
2729 goto add_character;
2730 }
2731 else
2732 old_index = ++sindex; /* skip past both '<' and '(' */
2733
2734 temp1 = extract_process_subst
2735 (string, (c == '<') ? "<(" : ">(", &old_index);
2736 sindex = old_index;
2737
2738 /* If the process substitution specification is `<()', we want to
2739 open the pipe for writing in the child and produce output; if
2740 it is `>()', we want to open the pipe for reading in the child
2741 and consume input. */
2742 temp = process_substitute (temp1, (c == '>'));
2743
2744 FREE (temp1);
2745
2746 goto dollar_add_string;
2747 }
2748#endif /* PROCESS_SUBSTITUTION */
2749
2750 /* See about breaking this into a separate function:
2751 char *
2752 param_expand (string, sindex, quoted, expanded_something,
2753 contains_dollar_at, quoted_dollar_at)
2754 char *string;
2755 int *sindex, quoted, *expanded_something, *contains_dollar_at;
2756 int *quoted_dollar_at;
2757 */
2758 case '$':
2759
2760 if (expanded_something)
2761 *expanded_something = 1;
2762
2763 c = string[++sindex];
2764
2765 /* Do simple cases first. Switch on what follows '$'. */
2766 switch (c)
2767 {
2768 /* $0 .. $9? */
2769 case '0':
2770 case '1':
2771 case '2':
2772 case '3':
2773 case '4':
2774 case '5':
2775 case '6':
2776 case '7':
2777 case '8':
2778 case '9':
2779 temp = dollar_vars[digit_value (c)];
2780 if (unbound_vars_is_error && temp == (char *)NULL)
2781 {
2782 report_error ("$%c: unbound variable", c);
2783 free (string);
2784 free (istring);
2785 last_command_exit_value = 1;
2786 return (&expand_word_error);
2787 }
2788 if (temp)
2789 temp = savestring (temp);
2790 goto dollar_add_string;
2791
2792 /* $$ -- pid of the invoking shell. */
2793 case '$':
2794 number = dollar_dollar_pid;
2795
2796 add_number:
2797 temp = itos (number);
2798 dollar_add_string:
2799 if (string[sindex]) sindex++;
2800
2801 /* Add TEMP to ISTRING. */
2802 add_string:
2803 istring = sub_append_string
2804 (temp, istring, &istring_index, &istring_size);
2805 temp = (char *)NULL;
2806 break;
2807
2808 /* $# -- number of positional parameters. */
2809 case '#':
2810 {
2811 WORD_LIST *list = list_rest_of_args ();
2812 number = list_length (list);
2813 dispose_words (list);
2814 goto add_number;
2815 }
2816
2817 /* $? -- return value of the last synchronous command. */
2818 case '?':
2819 number = last_command_exit_value;
2820 goto add_number;
2821
2822 /* $- -- flags supplied to the shell on invocation or
2823 by `set'. */
2824 case '-':
2825 temp = which_set_flags ();
2826 goto dollar_add_string;
2827
2828 /* $! -- Pid of the last asynchronous command. */
2829 case '!':
2830 number = (int)last_asynchronous_pid;
2831
2832 /* If no asynchronous pids have been created, echo nothing. */
2833 if (number == (int)NO_PID)
2834 {
2835 if (string[sindex])
2836 sindex++;
2837 if (expanded_something)
2838 *expanded_something = 0;
2839 break;
2840 }
2841 goto add_number;
2842
2843 /* The only difference between this and $@ is when the
2844 arg is quoted. */
2845 case '*': /* `$*' */
2846 temp = string_rest_of_args (quoted);
2847
2848 if (quoted && temp && *temp == '\0' /* && istring_index > 0 */)
2849 {
2850 free (temp);
2851 temp = (char *)NULL;
2852 }
2853
2854 /* In the case of a quoted string, quote the entire arg-list.
2855 "$1 $2 $3". */
2856 if (quoted && temp)
2857 {
2858 char *james_brown = temp;
2859 temp = quote_string (temp);
2860 free (james_brown);
2861 }
2862 goto dollar_add_string;
2863
2864 /* When we have "$@" what we want is "$1" "$2" "$3" ... This
2865 means that we have to turn quoting off after we split into
2866 the individually quoted arguments so that the final split
2867 on the first character of $IFS is still done. */
2868 case '@': /* `$@' */
2869 {
2870 WORD_LIST *tlist = list_rest_of_args ();
2871 if (quoted && tlist)
2872 quote_list (tlist);
2873
2874 /* We want to flag the fact that we saw this. We can't turn
2875 off quoting entirely, because other characters in the
2876 string might need it (consider "\"$@\""), but we need some
2877 way to signal that the final split on the first character
2878 of $IFS should be done, even though QUOTED is 1. */
2879 if (quoted)
2880 quoted_dollar_at = 1;
2881 if (contains_dollar_at)
2882 *contains_dollar_at = 1;
2883 temp = string_list (tlist);
2884 dispose_words (tlist);
2885 goto dollar_add_string;
2886 }
2887
2888 /* ${[#]name[[:]#[#]%[%]-=?+[word]]} */
2889 case '{':
2890 {
2891 int check_nullness = 0;
2892 int var_is_set = 0;
2893 int var_is_null = 0;
2894 int var_is_special = 0;
2895 char *name, *value;
2896
2897 t_index = ++sindex;
2898 name = string_extract (string, &t_index, "#%:-=?+}");
2899 value = (char *)NULL;
2900
2901 /* If the name really consists of a special variable, then
2902 make sure that we have the entire name. */
2903 if (sindex == t_index &&
2904 (string[sindex] == '-' ||
2905 string[sindex] == '?' ||
2906 string[sindex] == '#'))
2907 {
2908 char *tt;
2909 t_index++;
2910 free (name);
2911 tt = string_extract (string, &t_index, "#%:-=?+}");
2912 name = xmalloc (2 + (strlen (tt)));
2913 *name = string[sindex];
2914 strcpy (name + 1, tt);
2915 free (tt);
2916 }
2917 sindex = t_index;
2918
2919 /* Find out what character ended the variable name. Then
2920 do the appropriate thing. */
2921 if (c = string[sindex])
2922 sindex++;
2923
2924 if (c == ':')
2925 {
2926 check_nullness++;
2927 if (c = string[sindex])
2928 sindex++;
2929 }
2930
2931 /* Determine the value of this variable. */
2932 if ((digit (*name) && all_digits (name)) ||
2933 (strlen (name) == 1 && member (*name, "#-?$!@*")))
2934 var_is_special++;
2935
2936 /* Check for special expansion things. */
2937 if (*name == '#')
2938 {
2939 /* Handle ${#-} and ${#?}. They return the lengths of
2940 $- and $?, respectively. */
2941 if (string[sindex] == '}' &&
2942 !name[1] &&
2943 !check_nullness &&
2944 (c == '-' || c == '?'))
2945 {
2946 char *s;
2947
2948 free (name);
2949
2950 if (c == '-')
2951 s = which_set_flags ();
2952 else
2953 s = itos (last_command_exit_value);
2954
2955 number = STRLEN (s);
2956 FREE (s);
2957 goto add_number;
2958 }
2959
2960 /* Don't allow things like ${#:-foo} to go by; they are
2961 errors. If we are not pointing at the character just
2962 after the closing brace, then we haven't gotten all of
2963 the name. Since it begins with a special character,
2964 this is a bad substitution. Explicitly check for ${#:},
2965 which the rules do not catch. */
2966 if (string[sindex - 1] != '}' || member (c, "?-=+") ||
2967 (string[sindex - 1] == '}' && !name[1] && c == '}' &&
2968 check_nullness))
2969 {
2970 free (name);
2971 name = string;
2972 goto bad_substitution;
2973 }
2974
2975 /* Check NAME for validity before trying to go on. */
2976 if (!valid_length_expression (name))
2977 {
2978 free (name);
2979 name = string;
2980 goto bad_substitution;
2981 }
2982
2983 number = parameter_brace_expand_length (name);
2984 free (name);
2985 /* We are pointing one character after the brace which
2986 closes this expression. Since the code at add_number
2987 increments SINDEX, we back up a single character. */
2988 sindex--;
2989 goto add_number;
2990 }
2991
2992 /* ${@} is identical to $@. */
2993 if (name[0] == '@' && name[1] == '\0')
2994 {
2995 if (quoted)
2996 quoted_dollar_at = 1;
2997
2998 if (contains_dollar_at)
2999 *contains_dollar_at = 1;
3000 }
3001
3002 /* Make sure that NAME is valid before trying to go on. */
3003 if (!valid_brace_expansion_word (name, var_is_special))
3004 {
3005 free (name);
3006 name = string;
3007 goto bad_substitution;
3008 }
3009
3010 temp =
3011 parameter_brace_expand_word (name, var_is_special, quoted);
3012
3013 if (temp)
3014 var_is_set++;
3015
3016 if (!var_is_set || !temp || !*temp)
3017 var_is_null++;
3018
3019 if (!check_nullness)
3020 var_is_null = 0;
3021
3022 /* Get the rest of the stuff inside the braces. */
3023 if (c && c != '}')
3024 {
3025 /* Extract the contents of the ${ ... } expansion
3026 according to the Posix.2 rules. It's much less of
3027 a hack that the former extract_delimited_string ()
3028 scheme. */
3029 value = extract_dollar_brace_string (string, &sindex);
3030
3031 if (string[sindex] == '}')
3032 sindex++;
3033 else
3034 {
3035 free (name);
3036 name = string;
3037 goto bad_substitution;
3038 }
3039 }
3040 else
3041 value = (char *)NULL;
3042
3043 /* Do the right thing based on which character ended the
3044 variable name. */
3045 switch (c)
3046 {
3047 default:
3048 free (name);
3049 name = string;
3050 /* FALL THROUGH */
3051
3052 case '\0':
3053 bad_substitution:
3054 report_error ("%s: bad substitution", name ? name : "??");
3055 FREE (value);
3056 free (temp);
3057 free (name);
3058 free (istring);
3059 return &expand_word_error;
3060
3061 case '}':
3062 if (!var_is_set && unbound_vars_is_error)
3063 {
3064 report_error ("%s: unbound variable", name);
3065 FREE (value);
3066 free (temp);
3067 free (name);
3068 free (string);
3069 last_command_exit_value = 1;
3070 free (istring);
3071 return &expand_word_error;
3072 }
3073 break;
3074
3075 case '#': /* ${param#[#]pattern} */
3076 case '%': /* ${param%[%]pattern} */
3077 {
3078 char *t;
3079 if (!value || !*value || !temp || !*temp)
3080 break;
3081 if (quoted)
3082 {
3083 t = dequote_string (temp);
3084 free (temp);
3085 temp = t;
3086 }
3087 t = parameter_brace_remove_pattern (value, temp, c);
3088 free (temp);
3089 free (value);
3090 temp = t;
3091 }
3092 break;
3093
3094 case '-':
3095 case '=':
3096 case '?':
3097 case '+':
3098 if (var_is_set && !var_is_null)
3099 {
3100 /* We don't want the value of the named variable for
3101 anything, just the value of the right hand side. */
3102 if (c == '+')
3103 {
3104 FREE (temp);
3105 if (value)
3106 {
3107 temp = parameter_brace_expand_rhs
3108 (name, value, c, quoted);
3109 /* XXX - this is a hack. A better fix is
3110 coming later. */
3111 if ((value[0] == '$' && value[1] == '@') ||
3112 (value[0] == '"' && value[1] == '$' && value[2] == '@'))
3113 {
3114 if (quoted)
3115 quoted_dollar_at++;
3116 if (contains_dollar_at)
3117 *contains_dollar_at = 1;
3118 }
3119 free (value);
3120 }
3121 else
3122 temp = (char *)NULL;
3123 }
3124 else
3125 {
3126 FREE (value);
3127 }
3128 /* Otherwise do nothing; just use the value in TEMP. */
3129 }
3130 else /* VAR not set or VAR is NULL. */
3131 {
3132 FREE (temp);
3133 temp = (char *)NULL;
3134 if (c == '=' && var_is_special)
3135 {
3136 report_error
3137 ("$%s: cannot assign in this way", name);
3138 free (name);
3139 free (value);
3140 free (string);
3141 free (istring);
3142 return &expand_word_error;
3143 }
3144 else if (c == '?')
3145 {
3146 free (string);
3147 free (istring);
3148 parameter_brace_expand_error (name, value);
3149 if (!interactive)
3150 return &expand_word_fatal;
3151 else
3152 return &expand_word_error;
3153 }
3154 else if (c != '+')
3155 temp = parameter_brace_expand_rhs
3156 (name, value, c, quoted);
3157 free (value);
3158 }
3159 break;
3160 } /* end case on closing character. */
3161 free (name);
3162 goto add_string;
3163 } /* end case '{' */
3164 /* break; */
3165
3166 /* Do command or arithmetic substitution. */
3167 case '(':
3168 /* We have to extract the contents of this paren substitution. */
3169 {
3170 int old_index = ++sindex;
3171
3172 temp = extract_command_subst (string, &old_index);
3173 sindex = old_index;
3174
3175 /* For Posix.2-style `$(( ))' arithmetic substitution,
3176 extract the expression and pass it to the evaluator. */
3177 if (temp && *temp == '(')
3178 {
3179 char *t = temp + 1;
3180 int last = strlen (t) - 1;
3181
3182 if (t[last] != ')')
3183 {
3184 report_error ("%s: bad arithmetic substitution", temp);
3185 free (temp);
3186 free (string);
3187 free (istring);
3188 return &expand_word_error;
3189 }
3190
3191 /* Cut off ending `)' */
3192 t[last] = '\0';
3193
3194 /* Expand variables found inside the expression. */
3195 {
3196 WORD_LIST *l;
3197
3198 l = expand_string (t, 1);
3199 t = string_list (l);
3200 dispose_words (l);
3201 }
3202
3203 /* No error messages. */
3204 this_command_name = (char *)NULL;
3205
3206 number = evalexp (t);
3207 free (temp);
3208 free (t);
3209
3210 goto add_number;
3211 }
3212
3213 goto handle_command_substitution;
3214 }
3215
3216 /* Do straight arithmetic substitution. */
3217 case '[':
3218 /* We have to extract the contents of this
3219 arithmetic substitution. */
3220 {
3221 char *t;
3222 int old_index = ++sindex;
3223 WORD_LIST *l;
3224
3225 temp = extract_arithmetic_subst (string, &old_index);
3226 sindex = old_index;
3227
3228 /* Do initial variable expansion. */
3229 l = expand_string (temp, 1);
3230 t = string_list (l);
3231 dispose_words (l);
3232
3233 /* No error messages. */
3234 this_command_name = (char *)NULL;
3235 number = evalexp (t);
3236 free (t);
3237 free (temp);
3238
3239 goto add_number;
3240 }
3241
3242 default:
3243 {
3244 /* Find the variable in VARIABLE_LIST. */
3245 int old_index;
3246 char *name;
3247 SHELL_VAR *var;
3248
3249 temp = (char *)NULL;
3250
3251 for (old_index = sindex;
3252 (c = string[sindex]) &&
3253 (isletter (c) || digit (c) || c == '_');
3254 sindex++);
3255 name = substring (string, old_index, sindex);
3256
3257 /* If this isn't a variable name, then just output the `$'. */
3258 if (!name || !*name)
3259 {
3260 FREE (name);
3261 temp = savestring ("$");
3262 if (expanded_something)
3263 *expanded_something = 0;
3264 goto add_string;
3265 }
3266
3267 /* If the variable exists, return its value cell. */
3268 var = find_variable (name);
3269
3270 if (var && !invisible_p (var) && value_cell (var))
3271 {
3272 temp = value_cell (var);
3273 temp = quoted && temp && *temp ? quote_string (temp)
3274 : quote_escapes (temp);
3275 free (name);
3276 goto add_string;
3277 }
3278 else
3279 temp = (char *)NULL;
3280
3281 if (unbound_vars_is_error)
3282 report_error ("%s: unbound variable", name);
3283 else
3284 {
3285 free (name);
3286 goto add_string;
3287 }
3288
3289 free (name);
3290 free (string);
3291 last_command_exit_value = 1;
3292 free (istring);
3293 return &expand_word_error;
3294 }
3295 }
3296 break; /* End case '$': */
3297
3298 case '`': /* Backquoted command substitution. */
3299 {
3300 sindex++;
3301
3302 if (expanded_something)
3303 *expanded_something = 1;
3304
3305 temp = string_extract (string, &sindex, "`");
3306 de_backslash (temp);
3307
3308 handle_command_substitution:
3309 command_subst_result = command_substitute (temp, quoted);
3310
3311 FREE (temp);
3312
3313 temp = command_subst_result;
3314
3315 if (string[sindex])
3316 sindex++;
3317
3318 goto add_string;
3319 }
3320
3321 case '\\':
3322 if (string[sindex + 1] == '\n')
3323 {
3324 sindex += 2;
3325 continue;
3326 }
3327 else
3328 {
3329 char *slashify_chars = "";
3330
3331 c = string[++sindex];
3332
3333 if (quoted == Q_HERE_DOCUMENT)
3334 slashify_chars = slashify_in_here_document;
3335 else if (quoted == Q_DOUBLE_QUOTES)
3336 slashify_chars = slashify_in_quotes;
3337
3338 if (quoted && !member (c, slashify_chars))
3339 {
3340 temp = xmalloc (3);
3341 temp[0] = '\\'; temp[1] = c; temp[2] = '\0';
3342 if (c)
3343 sindex++;
3344 goto add_string;
3345 }
3346 else
3347 {
3348 /* This character is quoted, so add it in quoted mode. */
3349 temp = make_quoted_char (c);
3350 if (c)
3351 sindex++;
3352 goto add_string;
3353 }
3354 }
3355
3356 case '"':
3357 if (quoted)
3358 goto add_character;
3359 sindex++;
3360 {
3361 WORD_LIST *tresult = (WORD_LIST *)NULL;
3362
3363 t_index = sindex;
3364 temp = string_extract_double_quoted (string, &sindex);
3365
3366 /* If the quotes surrounded the entire string, then the
3367 whole word was quoted. */
3368 if (t_index == 1 && !string[sindex])
3369 quoted_state = WHOLLY_QUOTED;
3370 else
3371 quoted_state = PARTIALLY_QUOTED;
3372
3373 if (temp && *temp)
3374 {
3375 int dollar_at_flag;
3376 int quoting_flags = Q_DOUBLE_QUOTES;
3377 WORD_DESC *temp_word = make_word (temp);
3378
3379 free (temp);
3380
3381 tresult = expand_word_internal
3382 (temp_word, quoting_flags, &dollar_at_flag, (int *)NULL);
3383
3384 if (tresult == &expand_word_error || tresult == &expand_word_fatal)
3385 {
3386 free (istring);
3387 free (string);
3388 /* expand_word_internal has already freed temp_word->word
3389 for us because of the way it prints error messages. */
3390 temp_word->word = (char *)NULL;
3391 dispose_word (temp_word);
3392 return tresult;
3393 }
3394
3395 dispose_word (temp_word);
3396
3397 /* "$@" (a double-quoted dollar-at) expands into nothing,
3398 not even a NULL word, when there are no positional
3399 parameters. */
3400 if (!tresult && dollar_at_flag)
3401 {
3402 quoted_dollar_at++;
3403 break;
3404 }
3405
3406 /* If we get "$@", we know we have expanded something, so we
3407 need to remember it for the final split on $IFS. This is
3408 a special case; it's the only case where a quoted string
3409 can expand into more than one word. It's going to come back
3410 from the above call to expand_word_internal as a list with
3411 a single word, in which all characters are quoted and
3412 separated by blanks. What we want to do is to turn it back
3413 into a list for the next piece of code. */
3414 dequote_list (tresult);
3415
3416 if (dollar_at_flag)
3417 {
3418 quoted_dollar_at++;
3419 if (expanded_something)
3420 *expanded_something = 1;
3421 }
3422 }
3423 else
3424 {
3425 /* What we have is "". This is a minor optimization. */
3426 free (temp);
3427 tresult = (WORD_LIST *)NULL;
3428 }
3429
3430 /* The code above *might* return a list (consider the case of "$@",
3431 where it returns "$1", "$2", etc.). We can't throw away the
3432 rest of the list, and we have to make sure each word gets added
3433 as quoted. We test on tresult->next: if it is non-NULL, we
3434 quote the whole list, save it to a string with string_list, and
3435 add that string. We don't need to quote the results of this
3436 (and it would be wrong, since that would quote the separators
3437 as well), so we go directly to add_string. */
3438 if (tresult)
3439 {
3440 if (tresult->next)
3441 {
3442 quote_list (tresult);
3443 temp = string_list (tresult);
3444 dispose_words (tresult);
3445 goto add_string;
3446 }
3447 else
3448 {
3449 temp = savestring (tresult->word->word);
3450 dispose_words (tresult);
3451 }
3452 }
3453 else
3454 temp = (char *)NULL;
3455
3456 /* We do not want to add quoted nulls to strings that are only
3457 partially quoted; we can throw them away. */
3458 if (!temp && (quoted_state == PARTIALLY_QUOTED))
3459 continue;
3460
3461 add_quoted_string:
3462
3463 if (temp)
3464 {
3465 char *t = temp;
3466 temp = quote_string (temp);
3467 free (t);
3468 }
3469 else
3470 {
3471 /* Add NULL arg. */
3472 temp = xmalloc (2);
3473 temp[0] = CTLNUL;
3474 temp[1] = '\0';
3475 }
3476 goto add_string;
3477 }
3478 /* break; */
3479
3480 case '\'':
3481 {
3482 if (!quoted)
3483 {
3484 sindex++;
3485
3486 t_index = sindex;
3487 temp = string_extract_single_quoted (string, &sindex);
3488
3489 /* If the entire STRING was surrounded by single quotes,
3490 then the string is wholly quoted. */
3491 if (t_index == 1 && !string[sindex])
3492 quoted_state = WHOLLY_QUOTED;
3493 else
3494 quoted_state = PARTIALLY_QUOTED;
3495
3496 /* If all we had was '', it is a null expansion. */
3497 if (!*temp)
3498 {
3499 free (temp);
3500 temp = (char *)NULL;
3501 }
3502 else
3503 remove_quoted_escapes (temp);
3504
3505 /* We do not want to add quoted nulls to strings that are only
3506 partially quoted; such nulls are discarded. */
3507 if (!temp && (quoted_state == PARTIALLY_QUOTED))
3508 continue;
3509
3510 goto add_quoted_string;
3511 }
3512 else
3513 goto add_character;
3514
3515 break;
3516 }
3517
3518 default:
3519
3520 /* This is the fix for " $@ " */
3521 if (quoted)
3522 {
3523 temp = make_quoted_char (c);
3524 if (string[sindex])
3525 sindex++;
3526 goto add_string;
3527 }
3528
3529 add_character:
3530 if (istring_index + 1 >= istring_size)
3531 {
3532 while (istring_index + 1 >= istring_size)
3533 istring_size += DEFAULT_ARRAY_SIZE;
3534 istring = xrealloc (istring, istring_size);
3535 }
3536 istring[istring_index++] = c;
3537 istring[istring_index] = '\0';
3538
3539 /* Next character. */
3540 sindex++;
3541 }
3542 }
3543
3544finished_with_string:
3545final_exit:
3546 /* OK, we're ready to return. If we have a quoted string, and
3547 quoted_dollar_at is not set, we do no splitting at all; otherwise
3548 we split on ' '. The routines that call this will handle what to
3549 do if nothing has been expanded. */
3550 if (istring)
3551 {
3552 WORD_LIST *temp_list;
3553
3554 /* Partially and wholly quoted strings which expand to the empty
3555 string are retained as an empty arguments. Unquoted strings
3556 which expand to the empty string are discarded. The single
3557 exception is the case of expanding "$@" when there are no
3558 positional parameters. In that case, we discard the expansion. */
3559
3560 /* Because of how the code that handles "" and '' in partially
3561 quoted strings works, we need to make ISTRING into a QUOTED_NULL
3562 if we saw quoting characters, but the expansion was empty.
3563 "" and '' are tossed away before we get to this point when
3564 processing partially quoted strings. This makes "" and $xxx""
3565 equivalent when xxx is unset. */
3566 if (!*istring && quoted_state == PARTIALLY_QUOTED)
3567 {
3568 if (istring_size < 2)
3569 istring = xrealloc (istring, istring_size += 2);
3570 istring[0] = CTLNUL;
3571 istring[1] = '\0';
3572 }
3573
3574 /* If we expand to nothing and there were no single or double quotes
3575 in the word, we throw it away. Otherwise, we return a NULL word.
3576 The single exception is for $@ surrounded by double quotes when
3577 there are no positional parameters. In that case, we also throw
3578 the word away. */
3579 if (!*istring)
3580 {
3581 if (quoted_state == UNQUOTED ||
3582 (quoted_dollar_at && quoted_state == WHOLLY_QUOTED))
3583 temp_list = (WORD_LIST *)NULL;
3584 else
3585 {
3586 temp_list = make_word_list
3587 (make_word (istring), (WORD_LIST *)NULL);
3588 temp_list->word->quoted = quoted;
3589 }
3590 }
3591 else if (word->assignment)
3592 {
3593 temp_list = make_word_list (make_word (istring), (WORD_LIST *)NULL);
3594 temp_list->word->quoted = quoted;
3595 temp_list->word->assignment = assignment (temp_list->word->word);
3596 }
3597 else
3598 {
3599 char *ifs_chars = (char *)NULL;
3600
3601 if (quoted_dollar_at)
3602 {
3603 SHELL_VAR *ifs = find_variable ("IFS");
3604 if (ifs)
3605 ifs_chars = value_cell (ifs);
3606 else
3607 ifs_chars = " \t\n";
3608 }
3609
3610 /* According to Posix.2, "$@" expands to a single word if
3611 IFS="" and the positional parameters are not empty. */
3612 if (quoted_dollar_at && ifs_chars && *ifs_chars)
3613 {
3614 temp_list = list_string (istring, " ", 1);
3615#if 0
3616 /* This turns quoted null strings back into CTLNULs */
3617 dequote_list (temp_list);
3618 quote_list (temp_list);
3619#endif
3620 }
3621 else
3622 {
3623 WORD_DESC *tword;
3624 tword = make_word (istring);
3625 temp_list = make_word_list (tword, (WORD_LIST *)NULL);
3626 tword->quoted = quoted || (quoted_state == WHOLLY_QUOTED);
3627 tword->assignment = word->assignment;
3628 }
3629 }
3630
3631 free (istring);
3632 result = (WORD_LIST *)
3633 list_append (REVERSE_LIST (result, WORD_LIST *), temp_list);
3634 }
3635 else
3636 result = (WORD_LIST *)NULL;
3637
3638 return (result);
3639}
3640
3641/* **************************************************************** */
3642/* */
3643/* Functions for Quote Removal */
3644/* */
3645/* **************************************************************** */
3646
3647/* Perform quote removal on STRING. If QUOTED > 0, assume we are obeying the
3648 backslash quoting rules for within double quotes. */
3649char *
3650string_quote_removal (string, quoted)
3651 char *string;
3652 int quoted;
3653{
3654 char *r, *result_string, *temp, *temp1;
3655 int sindex, tindex, c, dquote;
3656
3657 /* The result can be no longer than the original string. */
3658 r = result_string = xmalloc (strlen (string) + 1);
3659
3660 for (sindex = dquote = 0; c = string[sindex];)
3661 {
3662 switch (c)
3663 {
3664 case '\\':
3665 c = string[++sindex];
3666 if ((quoted || dquote) && !member (c, slashify_in_quotes))
3667 *r++ = '\\';
3668
3669 default:
3670 *r++ = c;
3671 sindex++;
3672 break;
3673
3674 case '\'':
3675 if (quoted || dquote)
3676 {
3677 *r++ = c;
3678 sindex++;
3679 }
3680 else
3681 {
3682 tindex = ++sindex;
3683 temp = string_extract_single_quoted (string, &tindex);
3684 sindex = tindex;
3685
3686 if (temp)
3687 {
3688 strcpy (r, temp);
3689 r += strlen (r);
3690 free (temp);
3691 }
3692 }
3693 break;
3694
3695 case '"':
3696 dquote = 1 - dquote;
3697 sindex++;
3698 break;
3699 }
3700 }
3701 *r = '\0';
3702 return (result_string);
3703}
3704
3705/* Perform quote removal on word WORD. This allocates and returns a new
3706 WORD_DESC *. */
3707WORD_DESC *
3708word_quote_removal (word, quoted)
3709 WORD_DESC *word;
3710 int quoted;
3711{
3712 WORD_DESC *w;
3713 char *t;
3714
3715 t = string_quote_removal (word->word, quoted);
3716 w = make_word (t);
3717 return (w);
3718}
3719
3720/* Perform quote removal on all words in LIST. If QUOTED is non-zero,
3721 the members of the list are treated as if they are surrounded by
3722 double quotes. Return a new list, or NULL if LIST is NULL. */
3723WORD_LIST *
3724word_list_quote_removal (list, quoted)
3725 WORD_LIST *list;
3726 int quoted;
3727{
3728 WORD_LIST *result = (WORD_LIST *)NULL, *t, *tresult;
3729
3730 t = list;
3731 while (t)
3732 {
3733 tresult = (WORD_LIST *)xmalloc (sizeof (WORD_LIST));
3734 tresult->word = word_quote_removal (t->word, quoted);
3735 tresult->next = (WORD_LIST *)NULL;
3736 result = (WORD_LIST *) list_append (result, tresult);
3737 t = t->next;
3738 }
3739 return (result);
3740}
3741
3742/* Return 1 if CHARACTER appears in an unquoted portion of
3743 STRING. Return 0 otherwise. */
3744static int
3745unquoted_member (character, string)
3746 int character;
3747 char *string;
3748{
3749 int sindex, tindex, c;
3750 char *temp;
3751
3752 sindex = 0;
3753
3754 while (c = string[sindex])
3755 {
3756 if (c == character)
3757 return (1);
3758
3759 switch (c)
3760 {
3761 case '\\':
3762 sindex++;
3763 if (string[sindex])
3764 sindex++;
3765 break;
3766
3767 case '"':
3768 case '\'':
3769
3770 tindex = ++sindex;
3771 if (c == '"')
3772 temp = string_extract_double_quoted (string, &tindex);
3773 else
3774 temp = string_extract_single_quoted (string, &tindex);
3775 sindex = tindex;
3776
3777 FREE (temp);
3778 break;
3779
3780 default:
3781 sindex++;
3782 break;
3783 }
3784 }
3785 return (0);
3786}
3787
3788/* Return 1 if SUBSTR appears in an unquoted portion of STRING. */
3789static int
3790unquoted_substring (substr, string)
3791 char *substr, *string;
3792{
3793 int sindex, tindex, c, sublen;
3794 char *temp;
3795
3796 if (!substr || !*substr)
3797 return (0);
3798
3799 sublen = strlen (substr);
3800 sindex = 0;
3801
3802 while (c = string[sindex])
3803 {
3804 if (STREQN (string + sindex, substr, sublen))
3805 return (1);
3806
3807 switch (c)
3808 {
3809 case '\\':
3810 sindex++;
3811
3812 if (string[sindex])
3813 sindex++;
3814 break;
3815
3816 case '"':
3817 case '\'':
3818
3819 tindex = ++sindex;
3820
3821 if (c == '"')
3822 temp = string_extract_double_quoted (string, &tindex);
3823 else
3824 temp = string_extract_single_quoted (string, &tindex);
3825 sindex = tindex;
3826
3827 FREE (temp);
3828
3829 break;
3830
3831 default:
3832 sindex++;
3833 break;
3834 }
3835 }
3836 return (0);
3837}
3838
3839/*******************************************
3840 * *
3841 * Functions to perform word splitting *
3842 * *
3843 *******************************************/
3844
3845/* This splits a single word into a WORD LIST on $IFS, but only if the word
3846 is not quoted. list_string () performs quote removal for us, even if we
3847 don't do any splitting. */
3848WORD_LIST *
3849word_split (w)
3850 WORD_DESC *w;
3851{
3852 WORD_LIST *result;
3853
3854 if (w)
3855 {
3856 SHELL_VAR *ifs = find_variable ("IFS");
3857 char *ifs_chars;
3858
3859 /* If IFS is unset, it defaults to " \t\n". */
3860 if (ifs)
3861 ifs_chars = value_cell (ifs);
3862 else
3863 ifs_chars = " \t\n";
3864
3865 if (w->quoted || !ifs_chars)
3866 ifs_chars = "";
3867
3868#ifdef NOT_YET_MAYBE_LATER
3869 if (!*ifs)
3870 {
3871 /* No splitting done if word quoted or ifs set to "". */
3872 WORD_DESC *wtemp;
3873 wtemp = make_word (w->word);
3874 wtemp->quoted = w->quoted;
3875 result = make_word_list (wtemp);
3876 }
3877 else
3878#endif
3879 result = list_string (w->word, ifs_chars, w->quoted);
3880 }
3881 else
3882 result = (WORD_LIST *)NULL;
3883 return (result);
3884}
3885
3886/* Perform word splitting on LIST and return the RESULT. It is possible
3887 to return (WORD_LIST *)NULL. */
3888static WORD_LIST *
3889word_list_split (list)
3890 WORD_LIST *list;
3891{
3892 WORD_LIST *result = (WORD_LIST *)NULL, *t, *tresult;
3893
3894 t = list;
3895 while (t)
3896 {
3897 tresult = word_split (t->word);
3898 result = (WORD_LIST *) list_append (result, tresult);
3899 t = t->next;
3900 }
3901 return (result);
3902}
3903
3904/**************************************************
3905 * *
3906 * Functions to expand an entire WORD_LIST *
3907 * *
3908 **************************************************/
3909
3910static WORD_LIST *varlist = (WORD_LIST *)NULL;
3911
3912/* Separate out any initial variable assignments from TLIST. If set -k has
3913 been executed, remove all assignment statements from TLIST. Initial
3914 variable assignments and other environment assignments are placed
3915 on VARLIST. */
3916static WORD_LIST *
3917separate_out_assignments (tlist)
3918 WORD_LIST *tlist;
3919{
3920 register WORD_LIST *vp, *lp;
3921
3922 if (!tlist)
3923 return ((WORD_LIST *)NULL);
3924
3925 varlist = (WORD_LIST *)NULL;
3926 vp = lp = tlist;
3927
3928 /* Separate out variable assignments at the start of the command.
3929 Loop invariant: vp->next == lp
3930 Loop postcondition:
3931 lp = list of words left after assignment statements skipped
3932 tlist = original list of words
3933 */
3934 while (lp && lp->word->assignment)
3935 {
3936 vp = lp;
3937 lp = lp->next;
3938 }
3939
3940 /* If lp != tlist, we have some initial assignment statements. */
3941 /* We make VARLIST point to the list of assignment words and
3942 TLIST point to the remaining words. */
3943 if (lp != tlist)
3944 {
3945 varlist = tlist;
3946 /* ASSERT(vp->next == lp); */
3947 vp->next = (WORD_LIST *)NULL; /* terminate variable list */
3948 tlist = lp; /* remainder of word list */
3949 }
3950
3951 /* vp == end of variable list */
3952 /* tlist == remainder of original word list without variable assignments */
3953 if (!tlist)
3954 /* All the words in tlist were assignment statements */
3955 return ((WORD_LIST *)NULL);
3956
3957 /* ASSERT(tlist != NULL); */
3958 /* ASSERT(tlist->word->assignment == 0); */
3959
3960 /* If the -k option is in effect, we need to go through the remaining
3961 words, separate out the assignment words, and place them on VARLIST. */
3962 if (place_keywords_in_env)
3963 {
3964 WORD_LIST *tp; /* tp == running pointer into tlist */
3965
3966 tp = tlist;
3967 lp = tlist->next;
3968
3969 /* Loop Invariant: tp->next == lp */
3970 /* Loop postcondition: tlist == word list without assignment statements */
3971 while (lp)
3972 {
3973 if (lp->word->assignment)
3974 {
3975 /* Found an assignment statement, add this word to end of
3976 varlist (vp). */
3977 if (!varlist)
3978 varlist = vp = lp;
3979 else
3980 {
3981 vp->next = lp;
3982 vp = lp;
3983 }
3984
3985 /* Remove the word pointed to by LP from TLIST. */
3986 tp->next = lp->next;
3987 /* ASSERT(vp == lp); */
3988 lp->next = (WORD_LIST *)NULL;
3989 lp = tp->next;
3990 }
3991 else
3992 {
3993 tp = lp;
3994 lp = lp->next;
3995 }
3996 }
3997 }
3998 return (tlist);
3999}
4000
4001/* Take the list of words in LIST and do the various substitutions. Return
4002 a new list of words which is the expanded list, and without things like
4003 variable assignments. */
4004
4005WORD_LIST *
4006expand_words (list)
4007 WORD_LIST *list;
4008{
4009 return (expand_words_internal (list, 1));
4010}
4011
4012/* Same as expand_words (), but doesn't hack variable or environment
4013 variables. */
4014WORD_LIST *
4015expand_words_no_vars (list)
4016 WORD_LIST *list;
4017{
4018 return (expand_words_internal (list, 0));
4019}
4020
4021/* Non-zero means to allow unmatched globbed filenames to expand to
4022 a null file. */
4023static int allow_null_glob_expansion = 0;
4024
4025/* The workhorse for expand_words () and expand_words_no_var ().
4026 First arg is LIST, a WORD_LIST of words.
4027 Second arg DO_VARS is non-zero if you want to do environment and
4028 variable assignments, else zero.
4029
4030 This does all of the substitutions: brace expansion, tilde expansion,
4031 parameter expansion, command substitution, arithmetic expansion,
4032 process substitution, word splitting, and pathname expansion.
4033 Words with the `quoted' or `assignment' bits set, or for which no
4034 expansion is done, do not undergo word splitting. Words with the
4035 `assignment' but set do not undergo pathname expansion. */
4036static WORD_LIST *
4037expand_words_internal (list, do_vars)
4038 WORD_LIST *list;
4039 int do_vars;
4040{
4041 register WORD_LIST *tlist, *new_list = (WORD_LIST *)NULL;
4042 WORD_LIST *orig_list;
4043
4044 if (!list)
4045 return ((WORD_LIST *)NULL);
4046
4047 tlist = copy_word_list (list);
4048
4049 if (do_vars)
4050 {
4051 tlist = separate_out_assignments (tlist);
4052 if (!tlist)
4053 {
4054 if (varlist)
4055 {
4056 /* All the words were variable assignments, so they are placed
4057 into the shell's environment. */
4058 register WORD_LIST *lp;
4059 for (lp = varlist; lp; lp = lp->next)
4060 do_assignment (lp->word->word);
4061 dispose_words (varlist);
4062 varlist = (WORD_LIST *)NULL;
4063 }
4064 return ((WORD_LIST *)NULL);
4065 }
4066 }
4067
4068 /* Begin expanding the words that remain. The expansions take place on
4069 things that aren't really variable assignments. */
4070
4071#if defined (BRACE_EXPANSION)
4072 /* Do brace expansion on this word if there are any brace characters
4073 in the string. */
4074 if (!no_brace_expansion)
4075 {
4076 register char **expansions;
4077 WORD_LIST *braces = (WORD_LIST *)NULL, *disposables = (WORD_LIST *)NULL;
4078 int eindex;
4079
4080 while (tlist)
4081 {
4082 WORD_LIST *next;
4083
4084 next = tlist->next;
4085
4086 /* Only do brace expansion if the word has a brace character. If
4087 not, just add the word list element to BRACES and continue. In
4088 the common case, at least when running shell scripts, this will
4089 degenerate to a bunch of calls to `strchr', and then what is
4090 basically a reversal of TLIST into BRACES, which is corrected
4091 by a call to reverse_list () on BRACES when the end of TLIST
4092 is reached. */
4093 if (strchr (tlist->word->word, '{'))
4094 {
4095 expansions = brace_expand (tlist->word->word);
4096
4097 for (eindex = 0; expansions[eindex]; eindex++)
4098 {
4099 braces = make_word_list (make_word (expansions[eindex]),
4100 braces);
4101 free (expansions[eindex]);
4102 }
4103 free (expansions);
4104
4105 /* Add TLIST to the list of words to be freed after brace
4106 expansion has been performed. */
4107 tlist->next = disposables;
4108 disposables = tlist;
4109 }
4110 else
4111 {
4112 tlist->next = braces;
4113 braces = tlist;
4114 }
4115
4116 tlist = next;
4117 }
4118
4119 dispose_words (disposables);
4120 tlist = REVERSE_LIST (braces, WORD_LIST *);
4121 }
4122#endif /* BRACE_EXPANSION */
4123
4124 orig_list = tlist;
4125
4126 /* We do tilde expansion all the time. This is what 1003.2 says. */
4127 while (tlist)
4128 {
4129 register char *current_word;
4130 WORD_LIST *expanded, *t, *reversed, *next;
4131 int expanded_something = 0;
4132
4133 current_word = tlist->word->word;
4134
4135 next = tlist->next;
4136
4137 /* Posix.2 section 3.6.1 says that tildes following `=' in words
4138 which are not assignment statements are not expanded. We do
4139 this only if POSIXLY_CORRECT is enabled. */
4140 if (current_word[0] == '~' ||
4141 (!posixly_correct && strchr (current_word, '~') &&
4142 unquoted_substring ("=~", current_word)))
4143 {
4144 char *tt;
4145
4146 tt = tlist->word->word;
4147 tlist->word->word = tilde_expand (tt);
4148 free (tt);
4149 }
4150
4151 expanded = expand_word_internal
4152 (tlist->word, 0, (int *)NULL, &expanded_something);
4153
4154 if (expanded == &expand_word_error || expanded == &expand_word_fatal)
4155 {
4156 /* By convention, each time this error is returned,
4157 tlist->word->word has already been freed. */
4158 tlist->word->word = (char *)NULL;
4159
4160 /* Dispose our copy of the original list. */
4161 dispose_words (orig_list);
4162 /* Dispose the new list we're building. */
4163 dispose_words (new_list);
4164
4165 if (expanded == &expand_word_error)
4166 longjmp (top_level, DISCARD);
4167 else
4168 longjmp (top_level, FORCE_EOF);
4169 }
4170
4171 /* Don't split assignment words, even when they do not precede a
4172 command name. */
4173 if (expanded_something && tlist->word->assignment == 0)
4174 {
4175 t = word_list_split (expanded);
4176 dispose_words (expanded);
4177 }
4178 else
4179 {
4180 /* If no parameter expansion, command substitution, process
4181 substitution, or arithmetic substitution took place, then
4182 do not do word splitting. We still have to remove quoted
4183 null characters from the result. */
4184 word_list_remove_quoted_nulls (expanded);
4185 t = expanded;
4186 }
4187
4188 /* In the most common cases, t will be a list containing only one
4189 element, so the call to reverse_list would be wasted. */
4190 reversed = REVERSE_LIST (t, WORD_LIST *);
4191 new_list = (WORD_LIST *)list_append (reversed, new_list);
4192
4193 tlist = next;
4194 }
4195
4196 new_list = REVERSE_LIST (new_list, WORD_LIST *);
4197
4198 dispose_words (orig_list);
4199
4200#if defined (USE_POSIX_GLOB_LIBRARY)
4201# define GLOB_FAILED(glist) !(glist)
4202#else /* !USE_POSIX_GLOB_LIBRARY */
4203# define GLOB_FAILED(glist) (glist) == (char **)&glob_error_return
4204#endif /* !USE_POSIX_GLOB_LIBRARY */
4205
4206 /* Okay, we're almost done. Now let's just do some filename
4207 globbing. */
4208 if (new_list)
4209 {
4210 char **temp_list = (char **)NULL;
4211 register int list_index;
4212 WORD_LIST *glob_list, *disposables;
4213
4214 orig_list = disposables = (WORD_LIST *)NULL;
4215 tlist = new_list;
4216
4217 /* orig_list == output list, despite the name. */
4218 if (!disallow_filename_globbing)
4219 {
4220 while (tlist)
4221 {
4222 /* For each word, either globbing is attempted or the word is
4223 added to orig_list. If globbing succeeds, the results are
4224 added to orig_list and the word (tlist) is added to the list
4225 of disposable words. If globbing fails and failed glob
4226 expansions are left unchanged (the shell default), the
4227 original word is added to orig_list. If globbing fails and
4228 failed glob expansions are removed, the original word is
4229 added to the list of disposable words. orig_list ends up
4230 in reverse order and requires a call to reverse_list to
4231 be set right. After all words are examined, the disposable
4232 words are freed. */
4233 WORD_LIST *next;
4234
4235 next = tlist->next;
4236
4237 /* If the word isn't quoted and there is an unquoted pattern
4238 matching character in the word, then glob it. */
4239 if (!tlist->word->quoted && !tlist->word->assignment &&
4240 unquoted_glob_pattern_p (tlist->word->word))
4241 {
4242 temp_list = shell_glob_filename (tlist->word->word);
4243
4244 /* Handle error cases.
4245 I don't think we should report errors like "No such file
4246 or directory". However, I would like to report errors
4247 like "Read failed". */
4248
4249 if (GLOB_FAILED (temp_list))
4250 {
4251 temp_list = (char **) xmalloc (sizeof (char *));
4252 temp_list[0] = (char *)NULL;
4253 }
4254
4255 /* Dequote the current word in case we have to use it. */
4256 if (!temp_list[0])
4257 {
4258 register char *t = dequote_string (tlist->word->word);
4259 free (tlist->word->word);
4260 tlist->word->word = t;
4261 }
4262
4263 /* Make the array into a word list. */
4264 glob_list = (WORD_LIST *)NULL;
4265 for (list_index = 0; temp_list[list_index]; list_index++)
4266 glob_list = make_word_list
4267 (make_word (temp_list[list_index]), glob_list);
4268
4269 if (glob_list)
4270 {
4271 orig_list = (WORD_LIST *)list_append
4272 (glob_list, orig_list);
4273 tlist->next = disposables;
4274 disposables = tlist;
4275 }
4276 else
4277 if (!allow_null_glob_expansion)
4278 {
4279 /* Failed glob expressions are left unchanged. */
4280 tlist->next = orig_list;
4281 orig_list = tlist;
4282 }
4283 else
4284 {
4285 /* Failed glob expressions are removed. */
4286 tlist->next = disposables;
4287 disposables = tlist;
4288 }
4289 }
4290 else
4291 {
4292 /* Dequote the string. */
4293 register char *t = dequote_string (tlist->word->word);
4294 free (tlist->word->word);
4295 tlist->word->word = t;
4296 tlist->next = orig_list;
4297 orig_list = tlist;
4298 }
4299
4300 free_array (temp_list);
4301 temp_list = (char **)NULL;
4302
4303 tlist = next;
4304 }
4305
4306 if (disposables)
4307 dispose_words (disposables);
4308
4309 new_list = REVERSE_LIST (orig_list, WORD_LIST *);
4310 }
4311 else
4312 {
4313 /* Dequote the words, because we're not performing globbing. */
4314 register WORD_LIST *wl = new_list;
4315 register char *wp;
4316 while (wl)
4317 {
4318 wp = dequote_string (wl->word->word);
4319 free (wl->word->word);
4320 wl->word->word = wp;
4321 wl = wl->next;
4322 }
4323 }
4324 }
4325
4326 if (do_vars)
4327 {
4328 register WORD_LIST *lp;
4329 Function *assign_func;
4330
4331 /* If the remainder of the words expand to nothing, Posix.2 requires
4332 that the variable and environment assignments affect the shell's
4333 environment. */
4334 assign_func = new_list ? assign_in_env : do_assignment;
4335
4336 for (lp = varlist; lp; lp = lp->next)
4337 (*assign_func) (lp->word->word);
4338
4339 dispose_words (varlist);
4340 varlist = (WORD_LIST *)NULL;
4341 }
4342
4343 return (new_list);
4344}
4345
4346/* Return nonzero if S has any unquoted special globbing chars in it. */
4347static int
4348unquoted_glob_pattern_p (string)
4349 register char *string;
4350{
4351 register int c;
4352 int open = 0;
4353
4354 while (c = *string++)
4355 {
4356 switch (c)
4357 {
4358 case '?':
4359 case '*':
4360 return (1);
4361
4362 case '[':
4363 open++;
4364 continue;
4365
4366 case ']':
4367 if (open)
4368 return (1);
4369 continue;
4370
4371 case CTLESC:
4372 case '\\':
4373 if (*string++ == '\0')
4374 return (0);
4375 }
4376 }
4377 return (0);
4378}
4379
4380/* PATHNAME can contain characters prefixed by CTLESC; this indicates
4381 that the character is to be quoted. We quote it here in the style
4382 that the glob library recognizes. If CONVERT_QUOTED_NULLS is non-zero,
4383 we change quoted null strings (pathname[0] == CTLNUL) into empty
4384 strings (pathname[0] == 0). If this is called after quote removal
4385 is performed, CONVERT_QUOTED_NULLS should be 0; if called when quote
4386 removal has not been done (for example, before attempting to match a
4387 pattern while executing a case statement), CONVERT_QUOTED_NULLS should
4388 be 1. */
4389char *
4390quote_string_for_globbing (pathname, convert_quoted_nulls)
4391 char *pathname;
4392 int convert_quoted_nulls;
4393{
4394 char *temp;
4395 register int i;
4396
4397 temp = savestring (pathname);
4398
4399 if (convert_quoted_nulls && QUOTED_NULL (pathname))
4400 {
4401 temp[0] = '\0';
4402 return temp;
4403 }
4404
4405 for (i = 0; temp[i]; i++)
4406 {
4407 if (temp[i] == CTLESC)
4408 temp[i++] = '\\';
4409 }
4410
4411 return (temp);
4412}
4413
4414/* Call the glob library to do globbing on PATHNAME. */
4415char **
4416shell_glob_filename (pathname)
4417 char *pathname;
4418{
4419#if defined (USE_POSIX_GLOB_LIBRARY)
4420 extern int glob_dot_filenames;
4421 register int i;
4422 char *temp, **return_value;
4423 glob_t filenames;
4424 int glob_flags;
4425
4426 temp = quote_string_for_globbing (pathname, 0);
4427
4428 filenames.gl_offs = 0;
4429
4430 glob_flags = glob_dot_filenames ? GLOB_PERIOD : 0;
4431 glob_flags |= (GLOB_ERR | GLOB_DOOFFS);
4432
4433 i = glob (temp, glob_flags, (Function *)NULL, &filenames);
4434
4435 free (temp);
4436
4437 if (i == GLOB_NOSPACE || i == GLOB_ABEND)
4438 return ((char **)NULL);
4439
4440 if (i == GLOB_NOMATCH)
4441 filenames.gl_pathv[0] = (char *)NULL;
4442
4443 return (filenames.gl_pathv);
4444
4445#else /* !USE_POSIX_GLOB_LIBRARY */
4446
4447 char *temp, **results;
4448
4449 noglob_dot_filenames = !glob_dot_filenames;
4450
4451 temp = quote_string_for_globbing (pathname, 0);
4452
4453 results = glob_filename (temp);
4454 free (temp);
4455
4456 if (results && !(GLOB_FAILED(results)))
4457 sort_char_array (results);
4458
4459 return (results);
4460#endif /* !USE_POSIX_GLOB_LIBRARY */
4461}
4462
4463/*************************************************
4464 * *
4465 * Functions to manage special variables *
4466 * *
4467 *************************************************/
4468
4469/* An alist of name.function for each special variable. Most of the
4470 functions don't do much, and in fact, this would be faster with a
4471 switch statement, but by the end of this file, I am sick of switch
4472 statements. */
4473
4474/* The functions that get called. */
4475void
4476 sv_path (), sv_mail (), sv_uids (), sv_ignoreeof (),
4477 sv_glob_dot_filenames (), sv_nolinks (),
4478 sv_noclobber (), sv_allow_null_glob_expansion (), sv_strict_posix ();
4479
4480#if defined (READLINE)
4481void sv_terminal (), sv_hostname_completion_file ();
4482#endif
4483
4484#if defined (HISTORY)
4485void sv_histsize (), sv_histfilesize (),
4486 sv_history_control (), sv_command_oriented_history ();
4487# if defined (BANG_HISTORY)
4488void sv_histchars ();
4489# endif
4490#endif /* HISTORY */
4491
4492#if defined (GETOPTS_BUILTIN)
4493void sv_optind (), sv_opterr ();
4494#endif /* GETOPTS_BUILTIN */
4495
4496#if defined (JOB_CONTROL)
4497void sv_notify ();
4498#endif
4499
4500#define SET_INT_VAR(name, intvar) intvar = find_variable (name) != 0
4501
4502struct name_and_function {
4503 char *name;
4504 VFunction *function;
4505} special_vars[] = {
4506 { "PATH", sv_path },
4507 { "MAIL", sv_mail },
4508 { "MAILPATH", sv_mail },
4509 { "MAILCHECK", sv_mail },
4510
4511 { "POSIXLY_CORRECT", sv_strict_posix },
4512 { "POSIX_PEDANTIC", sv_strict_posix },
4513 /* Variables which only do something special when READLINE is defined. */
4514#if defined (READLINE)
4515 { "TERM", sv_terminal },
4516 { "TERMCAP", sv_terminal },
4517 { "TERMINFO", sv_terminal },
4518 { "hostname_completion_file", sv_hostname_completion_file },
4519 { "HOSTFILE", sv_hostname_completion_file },
4520#endif /* READLINE */
4521
4522 /* Variables which only do something special when HISTORY is defined. */
4523#if defined (HISTORY)
4524 { "HISTSIZE", sv_histsize },
4525 { "HISTFILESIZE", sv_histfilesize },
4526 { "command_oriented_history", sv_command_oriented_history },
4527# if defined (BANG_HISTORY)
4528 { "histchars", sv_histchars },
4529# endif
4530 { "history_control", sv_history_control },
4531 { "HISTCONTROL", sv_history_control },
4532#endif /* HISTORY */
4533
4534 { "EUID", sv_uids},
4535 { "UID", sv_uids},
4536 { "IGNOREEOF", sv_ignoreeof },
4537 { "ignoreeof", sv_ignoreeof },
4538
4539#if defined (GETOPTS_BUILTIN)
4540 { "OPTIND", sv_optind },
4541 { "OPTERR", sv_opterr },
4542#endif /* GETOPTS_BUILTIN */
4543
4544#if defined (JOB_CONTROL)
4545 { "notify", sv_notify },
4546#endif /* JOB_CONTROL */
4547
4548 { "glob_dot_filenames", sv_glob_dot_filenames },
4549 { "allow_null_glob_expansion", sv_allow_null_glob_expansion },
4550 { "noclobber", sv_noclobber },
4551 { "nolinks", sv_nolinks },
4552 { (char *)0x00, (VFunction *)0x00 }
4553};
4554
4555/* The variable in NAME has just had its state changed. Check to see if it
4556 is one of the special ones where something special happens. */
4557void
4558stupidly_hack_special_variables (name)
4559 char *name;
4560{
4561 int i = 0;
4562
4563 while (special_vars[i].name)
4564 {
4565 if (STREQ (special_vars[i].name, name))
4566 {
4567 (*(special_vars[i].function)) (name);
4568 return;
4569 }
4570 i++;
4571 }
4572}
4573
4574/* Set/unset noclobber. */
4575void
4576sv_noclobber (name)
4577 char *name;
4578{
4579 SET_INT_VAR (name, noclobber);
4580}
4581
4582/* What to do just after the PATH variable has changed. */
4583void
4584sv_path (name)
4585 char *name;
4586{
4587 /* hash -r */
4588 WORD_LIST *args;
4589
4590 args = make_word_list (make_word ("-r"), NULL);
4591 hash_builtin (args);
4592 dispose_words (args);
4593}
4594
4595/* What to do just after one of the MAILxxxx variables has changed. NAME
4596 is the name of the variable. This is called with NAME set to one of
4597 MAIL, MAILCHECK, or MAILPATH. */
4598void
4599sv_mail (name)
4600 char *name;
4601{
4602 /* If the time interval for checking the files has changed, then
4603 reset the mail timer. Otherwise, one of the pathname vars
4604 to the users mailbox has changed, so rebuild the array of
4605 filenames. */
4606 if (name[4] == 'C') /* if (strcmp (name, "MAILCHECK") == 0) */
4607 reset_mail_timer ();
4608 else
4609 {
4610 free_mail_files ();
4611 remember_mail_dates ();
4612 }
4613}
4614
4615#if defined (READLINE)
4616/* What to do just after one of the TERMxxx variables has changed.
4617 If we are an interactive shell, then try to reset the terminal
4618 information in readline. */
4619void
4620sv_terminal (name)
4621 char *name;
4622{
4623 if (interactive_shell && !no_line_editing)
4624 rl_reset_terminal (get_string_value ("TERM"));
4625}
4626
4627void
4628sv_hostname_completion_file (name)
4629 char *name;
4630{
4631 hostname_list_initialized = 0;
4632}
4633#endif /* READLINE */
4634
4635#if defined (HISTORY)
4636/* What to do after the HISTSIZE variable changes.
4637 If there is a value for this variable (and it is numeric), then stifle
4638 the history. Otherwise, if there is NO value for this variable,
4639 unstifle the history. */
4640void
4641sv_histsize (name)
4642 char *name;
4643{
4644 char *temp = get_string_value (name);
4645
4646 if (temp && *temp)
4647 {
4648 int num;
4649 if (sscanf (temp, "%d", &num) == 1)
4650 {
4651 stifle_history (num);
4652 if (history_lines_this_session > where_history ())
4653 history_lines_this_session = where_history ();
4654 }
4655 }
4656 else
4657 unstifle_history ();
4658}
4659
4660/* What to do if the HISTFILESIZE variable changes. */
4661void
4662sv_histfilesize (name)
4663 char *name;
4664{
4665 char *temp = get_string_value (name);
4666
4667 if (temp && *temp)
4668 {
4669 int num;
4670 if (sscanf (temp, "%d", &num) == 1)
4671 {
4672 history_truncate_file (get_string_value ("HISTFILE"), num);
4673 if (num <= history_lines_in_file)
4674 history_lines_in_file = num;
4675 }
4676 }
4677}
4678
4679/* What to do after the HISTORY_CONTROL variable changes. */
4680void
4681sv_history_control (name)
4682 char *name;
4683{
4684 char *temp = get_string_value (name);
4685
4686 history_control = 0;
4687
4688 if (temp && *temp)
4689 {
4690 if (strcmp (temp, "ignorespace") == 0)
4691 history_control = 1;
4692 else if (strcmp (temp, "ignoredups") == 0)
4693 history_control = 2;
4694 else if (strcmp (temp, "ignoreboth") == 0)
4695 history_control = 3;
4696 }
4697}
4698
4699/* What to do after the COMMAND_ORIENTED_HISTORY variable changes. */
4700void
4701sv_command_oriented_history (name)
4702 char *name;
4703{
4704 SET_INT_VAR (name, command_oriented_history);
4705}
4706
4707# if defined (BANG_HISTORY)
4708/* Setting/unsetting of the history expansion character. */
4709
4710void
4711sv_histchars (name)
4712 char *name;
4713{
4714 char *temp = get_string_value (name);
4715
4716 if (temp)
4717 {
4718 history_expansion_char = *temp;
4719 if (temp[0] && temp[1])
4720 {
4721 history_subst_char = temp[1];
4722 if (temp[2])
4723 history_comment_char = temp[2];
4724 }
4725 }
4726 else
4727 {
4728 history_expansion_char = '!';
4729 history_subst_char = '^';
4730 history_comment_char = '#';
4731 }
4732}
4733# endif /* BANG_HISTORY */
4734#endif /* HISTORY */
4735
4736void
4737sv_allow_null_glob_expansion (name)
4738 char *name;
4739{
4740 SET_INT_VAR (name, allow_null_glob_expansion);
4741}
4742
4743/* If the variable exists, then the value of it can be the number
4744 of times we actually ignore the EOF. The default is small,
4745 (smaller than csh, anyway). */
4746void
4747sv_ignoreeof (name)
4748 char *name;
4749{
4750 SHELL_VAR *tmp_var;
4751 char *temp;
4752 int new_limit;
4753
4754 eof_encountered = 0;
4755
4756 tmp_var = find_variable (name);
4757 ignoreeof = tmp_var != 0;
4758 temp = tmp_var ? value_cell (tmp_var) : (char *)NULL;
4759 if (temp)
4760 {
4761 if (sscanf (temp, "%d", &new_limit) == 1)
4762 eof_encountered_limit = new_limit;
4763 else
4764 eof_encountered_limit = 10; /* csh uses 26. */
4765 }
4766}
4767
4768/* Control whether * matches .files in globbing. Yechh. */
4769int glob_dot_filenames = 0;
4770
4771void
4772sv_glob_dot_filenames (name)
4773 char *name;
4774{
4775 SET_INT_VAR (name, glob_dot_filenames);
4776}
4777
4778#if defined (JOB_CONTROL)
4779/* Job notification feature desired? */
4780void
4781sv_notify (name)
4782 char *name;
4783{
4784 SET_INT_VAR (name, asynchronous_notification);
4785}
4786#endif /* JOB_CONTROL */
4787
4788/* If the variable `nolinks' exists, it specifies that symbolic links are
4789 not to be followed in `cd' commands. */
4790void
4791sv_nolinks (name)
4792 char *name;
4793{
4794 SET_INT_VAR (name, no_symbolic_links);
4795}
4796
4797/* Don't let users hack the user id variables. */
4798void
4799sv_uids (name)
4800 char *name;
4801{
4802 char *buff;
4803 register SHELL_VAR *v;
4804
4805 buff = itos (current_user.uid);
4806 v = find_variable ("UID");
4807 if (v)
4808 v->attributes &= ~att_readonly;
4809
4810 v = bind_variable ("UID", buff);
4811 v->attributes |= (att_readonly | att_integer);
4812 free (buff);
4813
4814 buff = itos (current_user.euid);
4815 v = find_variable ("EUID");
4816 if (v)
4817 v->attributes &= ~att_readonly;
4818
4819 v = bind_variable ("EUID", buff);
4820 v->attributes |= (att_readonly | att_integer);
4821 free (buff);
4822}
4823
4824#if defined (GETOPTS_BUILTIN)
4825void
4826sv_optind (name)
4827 char *name;
4828{
4829 char *tt = get_string_value ("OPTIND");
4830 int s = 0;
4831
4832 if (tt && *tt)
4833 {
4834 s = atoi (tt);
4835
4836 /* According to POSIX, setting OPTIND=1 resets the internal state
4837 of getopt (). */
4838 if (s < 0 || s == 1)
4839 s = 0;
4840 }
4841 getopts_reset (s);
4842}
4843
4844void
4845sv_opterr (name)
4846 char *name;
4847{
4848 char *tt = get_string_value ("OPTERR");
4849 int s = 1;
4850
4851 if (tt && *tt)
4852 s = atoi (tt);
4853 sh_opterr = s;
4854}
4855#endif /* GETOPTS_BUILTIN */
4856
4857void
4858sv_strict_posix (name)
4859 char *name;
4860{
4861 SET_INT_VAR (name, posixly_correct);
4862 if (posixly_correct)
4863 interactive_comments = 1;
4864#if defined (READLINE)
4865 posix_readline_initialize (posixly_correct);
4866#endif /* READLINE */
4867}