1 /* subst.c -- The part of the shell that does parameter, command, and
2 globbing substitutions. */
4 /* Copyright (C) 1987,1989 Free Software Foundation, Inc.
6 This file is part of GNU Bash, the Bourne Again SHell.
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
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
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. */
24 #include "bashtypes.h"
30 #if defined (HAVE_UNISTD_H)
35 #include "posixstat.h"
40 #include "execute_cmd.h"
44 #include "mailcheck.h"
46 #include "builtins/getopt.h"
47 #include "builtins/common.h"
49 #if defined (READLINE)
50 # include "bashline.h"
51 # include <readline/readline.h>
53 # include <tilde/tilde.h>
57 # include "bashhist.h"
58 # include <readline/history.h>
61 #include <glob/fnmatch.h>
67 /* The size that strings change by. */
68 #define DEFAULT_ARRAY_SIZE 128
75 /* Flags for quoted_strchr */
76 #define ST_BACKSL 0x01
77 #define ST_CTLESC 0x02
79 /* How to quote character C. */
80 static char *make_quoted_char ();
82 /* Process ID of the last command executed within command substitution. */
83 pid_t last_command_subst_pid = NO_PID;
85 /* Extern functions and variables from different files. */
86 extern int last_command_exit_value, interactive, interactive_shell;
87 extern int subshell_environment, startup_state;
88 extern int dollar_dollar_pid;
89 extern int posixly_correct;
90 extern int eof_encountered, eof_encountered_limit, ignoreeof;
91 extern char *this_command_name;
92 extern struct fd_bitmap *current_fds_to_close;
93 #if defined (READLINE)
94 extern int no_line_editing;
95 extern int hostname_list_initialized;
98 extern void getopts_reset ();
100 /* Non-zero means to allow unmatched globbed filenames to expand to
102 int allow_null_glob_expansion;
104 /* Variables to keep track of which words in an expanded word list (the
105 output of expand_word_list_internal) are the result of globbing
106 expansions. GLOB_ARGV_FLAGS is used by execute_cmd.c. */
107 char *glob_argv_flags;
108 static int glob_argv_flags_size;
110 static WORD_LIST expand_word_error, expand_word_fatal;
111 static char expand_param_error, expand_param_fatal;
113 static WORD_LIST *expand_string_internal ();
114 static WORD_LIST *expand_word_internal (), *expand_word_list_internal ();
115 static WORD_LIST *expand_string_leave_quoted ();
116 static WORD_LIST *expand_string_for_rhs ();
117 static WORD_LIST *word_list_split ();
118 static WORD_LIST *quote_list (), *dequote_list ();
119 static int unquoted_substring (), unquoted_member ();
120 static int do_assignment_internal ();
121 static char *string_extract_verbatim (), *string_extract ();
122 static char *string_extract_double_quoted (), *string_extract_single_quoted ();
123 static int skip_single_quoted (), skip_double_quoted ();
124 static char *extract_delimited_string ();
125 static char *extract_dollar_brace_string ();
127 /* **************************************************************** */
129 /* Utility Functions */
131 /* **************************************************************** */
133 /* Cons a new string from STRING starting at START and ending at END,
134 not including END. */
136 substring (string, start, end)
141 register char *result;
144 result = xmalloc (len + 1);
145 strncpy (result, string + start, len);
151 quoted_substring (string, start, end)
156 register char *result, *s, *r;
160 /* Move to string[start], skipping quoted characters. */
161 for (s = string, l = 0; *s && l < start; )
173 r = result = xmalloc (2*len + 1); /* save room for quotes */
175 /* Copy LEN characters, including quote characters. */
177 for (l = 0; l < len; s++)
190 /* Find the first occurrence of character C in string S, obeying shell
191 quoting rules. If (FLAGS & ST_BACKSL) is non-zero, backslash-escaped
192 characters are skipped. If (FLAGS & ST_CTLESC) is non-zero, characters
193 escaped with CTLESC are skipped. */
195 quoted_strchr (s, c, flags)
203 if (((flags & ST_BACKSL) && *p == '\\')
204 || ((flags & ST_CTLESC) && *p == CTLESC))
208 return ((char *)NULL);
214 return ((char *)NULL);
219 A string with s[0] == CTLNUL && s[1] == 0 is a quoted null string.
220 The parser passes CTLNUL as CTLESC CTLNUL. */
222 /* The parser passes us CTLESC as CTLESC CTLESC and CTLNUL as CTLESC CTLNUL.
223 This is necessary to make unquoted CTLESC and CTLNUL characters in the
224 data stream pass through properly.
225 Here we remove doubled CTLESC characters inside quoted strings before
226 quoting the entire string, so we do not double the number of CTLESC
229 remove_quoted_escapes (string)
239 t1 = t = xmalloc (strlen (string) + 1);
240 for (docopy = 0, s = string; *s; s++, t1++)
242 if (*s == CTLESC && (s[1] == CTLESC || s[1] == CTLNUL))
256 /* Quote escape characters in string s, but no other characters. This is
257 used to protect CTLESC and CTLNUL in variable values from the rest of
258 the word expansion process after the variable is expanded. */
260 quote_escapes (string)
263 register char *s, *t;
266 result = xmalloc ((strlen (string) * 2) + 1);
267 for (s = string, t = result; *s; )
269 if (*s == CTLESC || *s == CTLNUL)
278 dequote_escapes (string)
281 register char *s, *t;
284 result = xmalloc (strlen (string) + 1);
285 for (s = string, t = result; *s; )
287 if (*s == CTLESC && (s[1] == CTLESC || s[1] == CTLNUL))
299 /* Extract a substring from STRING, starting at SINDEX and ending with
300 one of the characters in CHARLIST. Don't make the ending character
301 part of the string. Leave SINDEX pointing at the ending character.
302 Understand about backslashes in the string. If VARNAME is non-zero,
303 and array variables have been compiled into the shell, everything
304 between a `[' and a corresponding `]' is skipped over. */
306 string_extract (string, sindex, charlist, varname)
307 char *string, *charlist;
308 int *sindex, varname;
313 for (i = *sindex; c = string[i]; i++)
320 #if defined (ARRAY_VARS)
321 else if (varname && c == '[')
324 /* If this is an array subscript, skip over it and continue. */
325 ni = skipsubscript (string, i);
326 if (string[ni] == ']')
330 else if (MEMBER (c, charlist))
334 temp = xmalloc (1 + c);
335 strncpy (temp, string + *sindex, c);
341 /* Extract the contents of STRING as if it is enclosed in double quotes.
342 SINDEX, when passed in, is the offset of the character immediately
343 following the opening double quote; on exit, SINDEX is left pointing after
344 the closing double quote. If STRIPDQ is non-zero, unquoted double
345 quotes are stripped and the string is terminated by a null byte.
346 Backslashes between the embedded double quotes are processed. If STRIPDQ
347 is zero, an unquoted `"' terminates the string. */
349 string_extract_double_quoted (string, sindex, stripdq)
351 int *sindex, stripdq;
354 char *temp, *ret; /* The new string we return. */
355 int pass_next, backquote, si; /* State variables for the machine. */
358 pass_next = backquote = dquote = 0;
359 temp = xmalloc (1 + strlen (string) - *sindex);
361 for (j = 0, i = *sindex; c = string[i]; i++)
363 /* Process a character that was quoted by a backslash. */
368 ``The backslash shall retain its special meaning as an escape
369 character only when followed by one of the characters:
372 If STRIPDQ is zero, we handle the double quotes here and let
373 expand_word_internal handle the rest. If STRIPDQ is non-zero,
374 we have already been through one round of backslash stripping,
375 and want to strip these backslashes only if DQUOTE is non-zero,
376 indicating that we are inside an embedded double-quoted string. */
378 /* If we are in an embedded quoted string, then don't strip
379 backslashes before characters for which the backslash
380 retains its special meaning, but remove backslashes in
381 front of other characters. If we are not in an
382 embedded quoted string, don't strip backslashes at all.
383 This mess is necessary because the string was already
384 surrounded by double quotes (and sh has some really weird
386 The returned string will be run through expansion as if
387 it were double-quoted. */
388 if ((stripdq == 0 && c != '"') ||
389 (stripdq && ((dquote && strchr (slashify_in_quotes, c)) || dquote == 0)))
396 /* A backslash protects the next character. The code just above
397 handles preserving the backslash in front of any character but
405 /* Inside backquotes, ``the portion of the quoted string from the
406 initial backquote and the characters up to the next backquote
407 that is not preceded by a backslash, having escape characters
408 removed, defines that command''. */
424 /* Pass everything between `$(' and the matching `)' or a quoted
425 ${ ... } pair through according to the Posix.2 specification. */
426 if (c == '$' && ((string[i + 1] == '(') || (string[i + 1] == '{')))
429 if (string[i + 1] == '(')
430 ret = extract_delimited_string (string, &si, "$(", "(", ")");
432 ret = extract_dollar_brace_string (string, &si, 1);
435 temp[j++] = string[i + 1];
437 for (t = 0; ret[t]; t++, j++)
439 temp[j++] = string[si];
446 /* Add any character but a double quote to the quoted string we're
465 /* Point to after the closing quote. */
473 /* This should really be another option to string_extract_double_quoted. */
475 skip_double_quoted (string, sind)
481 int pass_next, backquote, si;
483 pass_next = backquote = 0;
485 for (j = 0, i = sind; c = string[i]; i++)
508 else if (c == '$' && ((string[i + 1] == '(') || (string[i + 1] == '{')))
511 if (string[i + 1] == '(')
512 ret = extract_delimited_string (string, &si, "$(", "(", ")");
514 ret = extract_dollar_brace_string (string, &si, 0);
532 /* Extract the contents of STRING as if it is enclosed in single quotes.
533 SINDEX, when passed in, is the offset of the character immediately
534 following the opening single quote; on exit, SINDEX is left pointing after
535 the closing single quote. */
537 string_extract_single_quoted (string, sindex)
544 for (i = *sindex; string[i] && string[i] != '\''; i++)
549 strncpy (t, string + *sindex, j);
560 skip_single_quoted (string, sind)
566 for (i = sind; string[i] && string[i] != '\''; i++)
573 /* Just like string_extract, but doesn't hack backslashes or any of
574 that other stuff. Obeys quoting. Used to do splitting on $IFS. */
576 string_extract_verbatim (string, sindex, charlist)
577 char *string, *charlist;
580 register int i = *sindex;
584 if (charlist[0] == '\'' && charlist[1] == '\0')
586 temp = string_extract_single_quoted (string, sindex);
587 --*sindex; /* leave *sindex at separator character */
591 for (i = *sindex; c = string[i]; i++)
599 if (MEMBER (c, charlist))
604 temp = xmalloc (1 + c);
605 strncpy (temp, string + *sindex, c);
612 /* Extract the $( construct in STRING, and return a new string.
613 Start extracting at (SINDEX) as if we had just seen "$(".
614 Make (SINDEX) get the position of the matching ")". */
616 extract_command_subst (string, sindex)
620 return (extract_delimited_string (string, sindex, "$(", "(", ")"));
623 /* Extract the $[ construct in STRING, and return a new string.
624 Start extracting at (SINDEX) as if we had just seen "$[".
625 Make (SINDEX) get the position of the matching "]". */
627 extract_arithmetic_subst (string, sindex)
631 return (extract_delimited_string (string, sindex, "$[", "[", "]"));
634 #if defined (PROCESS_SUBSTITUTION)
635 /* Extract the <( or >( construct in STRING, and return a new string.
636 Start extracting at (SINDEX) as if we had just seen "<(".
637 Make (SINDEX) get the position of the matching ")". */
639 extract_process_subst (string, starter, sindex)
644 return (extract_delimited_string (string, sindex, starter, "(", ")"));
646 #endif /* PROCESS_SUBSTITUTION */
648 #if defined (ARRAY_VARS)
650 extract_array_assignment_list (string, sindex)
654 return (extract_delimited_string (string, sindex, "(", (char *)NULL, ")"));
658 /* Extract and create a new string from the contents of STRING, a
659 character string delimited with OPENER and CLOSER. SINDEX is
660 the address of an int describing the current offset in STRING;
661 it should point to just after the first OPENER found. On exit,
662 SINDEX gets the position of the last character of the matching CLOSER.
663 If OPENER is more than a single character, ALT_OPENER, if non-null,
664 contains a character string that can also match CLOSER and thus
665 needs to be skipped. */
667 extract_delimited_string (string, sindex, opener, alt_opener, closer)
670 char *opener, *alt_opener, *closer;
674 int pass_character, nesting_level;
675 int len_closer, len_opener, len_alt_opener;
677 len_opener = STRLEN (opener);
678 len_alt_opener = STRLEN (alt_opener);
679 len_closer = STRLEN (closer);
686 while (nesting_level)
693 if (pass_character) /* previous char was backslash */
708 if (c == '\\' && delimiter == '"' &&
709 (member (string[i], slashify_in_quotes)))
719 /* Process a nested OPENER. */
720 if (STREQN (string + i, opener, len_opener))
723 t = extract_delimited_string (string, &si, opener, alt_opener, closer);
729 /* Process a nested ALT_OPENER */
730 if (len_alt_opener && STREQN (string + i, alt_opener, len_alt_opener))
732 si = i + len_alt_opener;
733 t = extract_delimited_string (string, &si, alt_opener, alt_opener, closer);
739 /* If the current substring terminates the delimited string, decrement
740 the nesting level. */
741 if (STREQN (string + i, closer, len_closer))
743 i += len_closer - 1; /* move to last char of the closer */
745 if (nesting_level == 0)
749 /* Pass old-style command substitution through verbatim. */
753 t = string_extract (string, &si, "`", 0);
759 /* Pass single-quoted strings through verbatim. */
763 i = skip_single_quoted (string, si);
767 /* Pass embedded double-quoted strings through verbatim as well. */
771 i = skip_double_quoted (string, si);
775 i++; /* move past this character, which was not special. */
778 si = i - *sindex - len_closer + 1;
779 result = xmalloc (1 + si);
780 strncpy (result, string + *sindex, si);
784 if (c == 0 && nesting_level)
786 report_error ("bad substitution: no `%s' in %s", closer, string);
788 jump_to_top_level (DISCARD);
794 /* Extract a parameter expansion expression within ${ and } from STRING.
795 Obey the Posix.2 rules for finding the ending `}': count braces while
796 skipping over enclosed quoted strings and command substitutions.
797 SINDEX is the address of an int describing the current offset in STRING;
798 it should point to just after the first `{' found. On exit, SINDEX
799 gets the position of the matching `}'. QUOTED is non-zero if this
800 occurs inside double quotes. */
801 /* XXX -- this is very similar to extract_delimited_string -- XXX */
803 extract_dollar_brace_string (string, sindex, quoted)
807 register int i, c, l;
808 int pass_character, nesting_level, si;
815 for (i = *sindex; (c = string[i]); i++)
829 /* Backslashes quote the next character. */
836 if (string[i] == '$' && string[i+1] == '{')
846 if (nesting_level == 0)
851 /* Pass the contents of old-style command substitutions through
856 t = string_extract (string, &si, "`", 0);
862 /* Pass the contents of new-style command substitutions through
864 if (string[i] == '$' && string[i+1] == '(')
867 t = extract_delimited_string (string, &si, "$(", "(", ")");
873 /* Pass the contents of single-quoted strings through verbatim. */
877 i = skip_single_quoted (string, si);
878 /* skip_single_quoted leaves index one past close quote */
883 /* Pass embedded double-quoted strings through verbatim as well. */
887 /* skip_double_quoted leaves index one past close quote */
888 i = skip_double_quoted (string, si);
895 result = xmalloc (1 + l);
896 strncpy (result, string + *sindex, l);
900 if (c == 0 && nesting_level)
902 report_error ("bad substitution: no ending `}' in %s", string);
904 jump_to_top_level (DISCARD);
910 /* Remove backslashes which are quoting backquotes from STRING. Modifies
911 STRING, and returns a pointer to it. */
913 de_backslash (string)
918 for (i = 0, l = strlen (string); i < l; i++)
919 if (string[i] == '\\' && (string[i + 1] == '`' || string[i + 1] == '\\' ||
920 string[i + 1] == '$'))
921 strcpy (string + i, string + i + 1); /* XXX - should be memmove */
926 /* Replace instances of \! in a string with !. */
928 unquote_bang (string)
934 temp = xmalloc (1 + strlen (string));
936 for (i = 0, j = 0; (temp[j] = string[i]); i++, j++)
938 if (string[i] == '\\' && string[i + 1] == '!')
944 strcpy (string, temp);
949 #if defined (READLINE)
950 /* Return 1 if the portion of STRING ending at EINDEX is quoted (there is
951 an unclosed quoted string), or if the character at EINDEX is quoted
954 char_is_quoted (string, eindex)
958 int i, pass_next, quoted;
960 for (i = pass_next = quoted = 0; i <= eindex; i++)
965 if (i >= eindex) /* XXX was if (i >= eindex - 1) */
969 else if (string[i] == '\'' || string[i] == '"')
971 i = (string[i] == '\'') ? skip_single_quoted (string, ++i)
972 : skip_double_quoted (string, ++i);
975 i--; /* the skip functions increment past the closing quote. */
977 else if (string[i] == '\\')
987 unclosed_pair (string, eindex, openstr)
992 int i, pass_next, openc, olen;
994 olen = strlen (openstr);
995 for (i = pass_next = openc = 0; i <= eindex; i++)
1000 if (i >= eindex) /* XXX was if (i >= eindex - 1) */
1004 else if (STREQN (string + i, openstr, olen))
1009 else if (string[i] == '\'' || string[i] == '"')
1011 i = (string[i] == '\'') ? skip_single_quoted (string, i)
1012 : skip_double_quoted (string, i);
1016 else if (string[i] == '\\')
1024 #endif /* READLINE */
1028 /* Extract the name of the variable to bind to from the assignment string. */
1030 assignment_name (string)
1036 offset = assignment (string);
1038 return (char *)NULL;
1039 temp = xmalloc (offset + 1);
1040 strncpy (temp, string, offset);
1041 temp[offset] = '\0';
1046 /* Return a single string of all the words in LIST. SEP is the separator
1047 to put between individual elements of LIST in the output string. */
1049 string_list_internal (list, sep)
1053 register WORD_LIST *t;
1055 int word_len, sep_len, result_size;
1058 return ((char *)NULL);
1060 /* This is nearly always called with either sep[0] == 0 or sep[1] == 0. */
1061 sep_len = STRLEN (sep);
1064 for (t = list; t; t = t->next)
1067 result_size += sep_len;
1068 result_size += strlen (t->word->word);
1071 r = result = xmalloc (result_size + 1);
1073 for (t = list; t; t = t->next)
1075 if (t != list && sep_len)
1079 FASTCOPY (sep, r, sep_len);
1086 word_len = strlen (t->word->word);
1087 FASTCOPY (t->word->word, r, word_len);
1095 /* Return a single string of all the words present in LIST, separating
1096 each word with a space. */
1101 return (string_list_internal (list, " "));
1104 /* Return a single string of all the words present in LIST, obeying the
1105 quoting rules for "$*", to wit: (P1003.2, draft 11, 3.5.2) "If the
1106 expansion [of $*] appears within a double quoted string, it expands
1107 to a single field with the value of each parameter separated by the
1108 first character of the IFS variable, or by a <space> if IFS is unset." */
1110 string_list_dollar_star (list)
1115 ifs = get_string_value ("IFS");
1118 else if (*ifs == '\0')
1125 return (string_list_internal (list, sep));
1128 /* Return the list of words present in STRING. Separate the string into
1129 words at any of the characters found in SEPARATORS. If QUOTED is
1130 non-zero then word in the list will have its quoted flag set, otherwise
1131 the quoted flag is left as make_word () deemed fit.
1133 This obeys the P1003.2 word splitting semantics. If `separators' is
1134 exactly <space><tab><newline>, then the splitting algorithm is that of
1135 the Bourne shell, which treats any sequence of characters from `separators'
1136 as a delimiter. If IFS is unset, which results in `separators' being set
1137 to "", no splitting occurs. If separators has some other value, the
1138 following rules are applied (`IFS white space' means zero or more
1139 occurrences of <space>, <tab>, or <newline>, as long as those characters
1140 are in `separators'):
1142 1) IFS white space is ignored at the start and the end of the
1144 2) Each occurrence of a character in `separators' that is not
1145 IFS white space, along with any adjacent occurrences of
1146 IFS white space delimits a field.
1147 3) Any nonzero-length sequence of IFS white space delimits a field.
1150 /* BEWARE! list_string strips null arguments. Don't call it twice and
1151 expect to have "" preserved! */
1153 /* Perform quoted null character removal on STRING. We don't allow any
1154 quoted null characters in the middle or at the ends of strings because
1155 of how expand_word_internal works. remove_quoted_nulls () turns
1156 STRING into an empty string iff it only consists of a quoted null,
1157 and removes all unquoted CTLNUL characters. */
1159 #define remove_quoted_nulls(string) \
1160 do { if (QUOTED_NULL (string)) string[0] ='\0'; } while (0)
1163 remove_quoted_nulls (string)
1168 nstr = savestring (string);
1170 for (p = nstr, s = string; *s; s++)
1174 *p++ = *s++; /* CTLESC */
1177 *p++ = *s; /* quoted char */
1185 strcpy (string, nstr);
1189 /* Perform quoted null character removal on each element of LIST.
1190 This modifies LIST. */
1192 word_list_remove_quoted_nulls (list)
1195 register WORD_LIST *t;
1197 for (t = list; t; t = t->next)
1198 remove_quoted_nulls (t->word->word);
1201 /* This performs word splitting and quoted null character removal on
1203 #define issep(c) (member ((c), separators))
1206 list_string (string, separators, quoted)
1207 register char *string, *separators;
1212 char *current_word, *s;
1213 int sindex, sh_style_split;
1215 if (!string || !*string)
1216 return ((WORD_LIST *)NULL);
1219 separators && *separators && (STREQ (separators, " \t\n"));
1221 /* Remove sequences of whitespace at the beginning of STRING, as
1222 long as those characters appear in IFS. Do not do this if
1223 STRING is quoted or if there are no separator characters. */
1224 if (!quoted || !separators || !*separators)
1226 for (s = string; *s && spctabnl (*s) && issep (*s); s++);
1229 return ((WORD_LIST *)NULL);
1234 /* OK, now STRING points to a word that does not begin with white space.
1235 The splitting algorithm is:
1236 extract a word, stopping at a separator
1237 skip sequences of spc, tab, or nl as long as they are separators
1238 This obeys the field splitting rules in Posix.2. */
1239 for (result = (WORD_LIST *)NULL, sindex = 0; string[sindex]; )
1241 current_word = string_extract_verbatim (string, &sindex, separators);
1242 if (current_word == 0)
1245 /* If we have a quoted empty string, add a quoted null argument. We
1246 want to preserve the quoted null character iff this is a quoted
1247 empty string; otherwise the quoted null characters are removed
1249 if (QUOTED_NULL (current_word))
1251 t = make_bare_word ("");
1252 t->flags |= W_QUOTED;
1254 t->word = make_quoted_char ('\0');
1255 result = make_word_list (t, result);
1257 else if (current_word[0] != '\0')
1259 /* If we have something, then add it regardless. However,
1260 perform quoted null character removal on the current word. */
1261 remove_quoted_nulls (current_word);
1262 result = make_word_list (make_word (current_word), result);
1263 if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
1264 result->word->flags |= W_QUOTED;
1267 /* If we're not doing sequences of separators in the traditional
1268 Bourne shell style, then add a quoted null argument. */
1269 else if (!sh_style_split && !spctabnl (string[sindex]))
1271 t = make_bare_word ("");
1272 t->flags |= W_QUOTED;
1274 t->word = make_quoted_char ('\0');
1275 result = make_word_list (t, result);
1278 free (current_word);
1280 /* Move past the current separator character. */
1284 /* Now skip sequences of space, tab, or newline characters if they are
1285 in the list of separators. */
1286 while (string[sindex] && spctabnl (string[sindex]) && issep (string[sindex]))
1289 return (REVERSE_LIST (result, WORD_LIST *));
1292 /* Parse a single word from STRING, using SEPARATORS to separate fields.
1293 ENDPTR is set to the first character after the word. This is used by
1295 XXX - this function is very similar to list_string; they should be
1298 get_word_from_string (stringp, separators, endptr)
1299 char **stringp, *separators, **endptr;
1303 int sindex, sh_style_split;
1305 if (!stringp || !*stringp || !**stringp)
1306 return ((char *)NULL);
1311 separators && *separators && (STREQ (separators, " \t\n"));
1313 /* Remove sequences of whitespace at the beginning of STRING, as
1314 long as those characters appear in IFS. */
1315 if (sh_style_split || !separators || !*separators)
1317 for (; *s && spctabnl (*s) && issep (*s); s++);
1319 /* If the string is nothing but whitespace, update it and return. */
1325 return ((char *)NULL);
1329 /* OK, S points to a word that does not begin with white space.
1330 Now extract a word, stopping at a separator, save a pointer to
1331 the first character after the word, then skip sequences of spc,
1332 tab, or nl as long as they are separators.
1334 This obeys the field splitting rules in Posix.2. */
1336 current_word = string_extract_verbatim (s, &sindex, separators);
1338 /* Set ENDPTR to the first character after the end of the word. */
1340 *endptr = s + sindex;
1342 /* Move past the current separator character. */
1346 /* Now skip sequences of space, tab, or newline characters if they are
1347 in the list of separators. */
1348 while (s[sindex] && spctabnl (s[sindex]) && issep (s[sindex]))
1351 /* Update STRING to point to the next field. */
1352 *stringp = s + sindex;
1353 return (current_word);
1356 /* Remove IFS white space at the end of STRING. Start at the end
1357 of the string and walk backwards until the beginning of the string
1358 or we find a character that's not IFS white space and not CTLESC.
1359 Only let CTLESC escape a white space character if SAW_ESCAPE is
1362 strip_trailing_ifs_whitespace (string, separators, saw_escape)
1363 char *string, *separators;
1368 s = string + STRLEN (string) - 1;
1369 while (s > string && ((spctabnl (*s) && issep (*s)) ||
1370 (saw_escape && *s == CTLESC && spctabnl (s[1]))))
1377 #if defined (ARRAY_VARS)
1379 list_string_with_quotes (string)
1384 int c, i, tokstart, len;
1386 for (s = string; s && *s && spctabnl (*s); s++)
1388 if (s == 0 || *s == 0)
1389 return ((WORD_LIST *)NULL);
1392 list = (WORD_LIST *)NULL;
1403 i = skip_single_quoted (s, ++i);
1405 i = skip_double_quoted (s, ++i);
1406 else if (c == 0 || spctabnl (c))
1408 /* We have found the end of a token. Make a word out of it and
1409 add it to the word list. */
1411 token = xmalloc (len + 1);
1412 strncpy (token, s + tokstart, len);
1414 list = make_word_list (make_word (token), list);
1416 while (spctabnl (s[i]))
1424 i++; /* normal character */
1426 return (REVERSE_LIST (list, WORD_LIST *));
1428 #endif /* ARRAY_VARS */
1431 #if defined (PROCESS_SUBSTITUTION)
1432 #define EXP_CHAR(s) (s == '$' || s == '`' || s == '<' || s == '>' || s == CTLESC)
1434 #define EXP_CHAR(s) (s == '$' || s == '`' || s == CTLESC)
1437 /* If there are any characters in STRING that require full expansion,
1438 then call FUNC to expand STRING; otherwise just perform quote
1439 removal if necessary. This returns a new string. */
1441 maybe_expand_string (string, quoted, func)
1444 WORD_LIST *(*func)();
1450 for (i = saw_quote = 0; string[i]; i++)
1452 if (EXP_CHAR (string[i]))
1454 else if (string[i] == '\'' || string[i] == '\\' || string[i] == '"')
1460 list = (*func) (string, quoted);
1463 ret = string_list (list);
1464 dispose_words (list);
1469 else if (saw_quote && ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) == 0))
1470 ret = string_quote_removal (string, quoted);
1472 ret = savestring (string);
1476 #if defined (ARRAY_VARS)
1478 do_array_element_assignment (name, value)
1485 t = strchr (name, '[');
1487 return ((SHELL_VAR *)NULL);
1489 ni = skipsubscript (name, ind);
1490 if ((ALL_ELEMENT_SUB (t[1]) && t[2] == ']') || (ni <= ind + 1))
1492 report_error ("%s: bad array subscript", name);
1493 return ((SHELL_VAR *)NULL);
1496 ind = array_expand_index (t, ni - ind);
1499 t[-1] = '['; /* restore original name */
1500 report_error ("%s: bad array subscript", name);
1501 return ((SHELL_VAR *)NULL);
1503 entry = bind_array_variable (name, ind, value);
1504 t[-1] = '['; /* restore original name */
1507 #endif /* ARRAY_VARS */
1509 /* Given STRING, an assignment string, get the value of the right side
1510 of the `=', and bind it to the left side. If EXPAND is true, then
1511 perform parameter expansion, command substitution, and arithmetic
1512 expansion on the right-hand side. Perform tilde expansion in any
1513 case. Do not perform word splitting on the result of expansion. */
1515 do_assignment_internal (string, expand)
1522 #if defined (ARRAY_VARS)
1524 int ni, assign_list = 0;
1527 offset = assignment (string);
1528 name = savestring (string);
1529 value = (char *)NULL;
1531 if (name[offset] == '=')
1536 temp = name + offset + 1;
1538 #if defined (ARRAY_VARS)
1539 if (expand && temp[0] == '(' && strchr (temp, ')'))
1541 assign_list = ni = 1;
1542 value = extract_delimited_string (temp, &ni, "(", (char *)NULL, ")");
1547 /* Perform tilde expansion. */
1548 if (expand && temp[0])
1550 temp = (strchr (temp, '~') && unquoted_member ('~', temp))
1551 ? bash_tilde_expand (temp)
1552 : savestring (temp);
1554 value = maybe_expand_string (temp, 0, expand_string_unsplit);
1558 value = savestring (temp);
1562 value = savestring ("");
1564 if (echo_command_at_execute)
1565 #if defined (ARRAY_VARS)
1567 fprintf (stderr, "%s%s=(%s)\n", indirection_level_string (), name, value);
1570 fprintf (stderr, "%s%s=%s\n", indirection_level_string (), name, value);
1572 #define ASSIGN_RETURN(r) FREE (value); free (name); return (r);
1574 #if defined (ARRAY_VARS)
1575 if (t = strchr (name, '['))
1579 report_error ("%s: cannot assign list to array member", name);
1582 entry = do_array_element_assignment (name, value);
1586 else if (assign_list)
1587 entry = assign_array_from_string (name, value);
1589 #endif /* ARRAY_VARS */
1590 entry = bind_variable (name, value);
1592 stupidly_hack_special_variables (name);
1595 entry->attributes &= ~att_invisible;
1597 /* Return 1 if the assignment seems to have been performed correctly. */
1598 ASSIGN_RETURN (entry ? ((entry->attributes & att_readonly) == 0) : 0);
1601 /* Perform the assignment statement in STRING, and expand the
1602 right side by doing command and parameter expansion. */
1604 do_assignment (string)
1607 return do_assignment_internal (string, 1);
1610 /* Given STRING, an assignment string, get the value of the right side
1611 of the `=', and bind it to the left side. Do not do command and
1612 parameter substitution on the right hand side. */
1614 do_assignment_no_expand (string)
1617 return do_assignment_internal (string, 0);
1620 /* Most of the substitutions must be done in parallel. In order
1621 to avoid using tons of unclear goto's, I have some functions
1622 for manipulating malloc'ed strings. They all take INDX, a
1623 pointer to an integer which is the offset into the string
1624 where manipulation is taking place. They also take SIZE, a
1625 pointer to an integer which is the current length of the
1626 character array for this string. */
1628 /* Append SOURCE to TARGET at INDEX. SIZE is the current amount
1629 of space allocated to TARGET. SOURCE can be NULL, in which
1630 case nothing happens. Gets rid of SOURCE by freeing it.
1631 Returns TARGET in case the location has changed. */
1633 sub_append_string (source, target, indx, size)
1634 char *source, *target;
1641 srclen = STRLEN (source);
1642 if (srclen >= (int)(*size - *indx))
1645 n = (n + DEFAULT_ARRAY_SIZE) - (n % DEFAULT_ARRAY_SIZE);
1646 target = xrealloc (target, (*size = n));
1649 FASTCOPY (source, target + *indx, srclen);
1651 target[*indx] = '\0';
1660 /* Append the textual representation of NUMBER to TARGET.
1661 INDX and SIZE are as in SUB_APPEND_STRING. */
1663 sub_append_number (number, target, indx, size)
1664 int number, *indx, *size;
1669 temp = itos (number);
1670 return (sub_append_string (temp, target, indx, size));
1674 /* Return the word list that corresponds to `$*'. */
1676 list_rest_of_args ()
1678 register WORD_LIST *list, *args;
1681 /* Break out of the loop as soon as one of the dollar variables is null. */
1682 for (i = 1, list = (WORD_LIST *)NULL; i < 10 && dollar_vars[i]; i++)
1683 list = make_word_list (make_bare_word (dollar_vars[i]), list);
1685 for (args = rest_of_args; args; args = args->next)
1686 list = make_word_list (make_bare_word (args->word->word), list);
1688 return (REVERSE_LIST (list, WORD_LIST *));
1694 register WORD_LIST *list;
1697 for (n = 0; n < 9 && dollar_vars[n+1]; n++)
1699 for (list = rest_of_args; list; list = list->next)
1704 /* Make a single large string out of the dollar digit variables,
1705 and the rest_of_args. If DOLLAR_STAR is 1, then obey the special
1706 case of "$*" with respect to IFS. */
1708 string_rest_of_args (dollar_star)
1711 register WORD_LIST *list;
1714 list = list_rest_of_args ();
1715 string = dollar_star ? string_list_dollar_star (list) : string_list (list);
1716 dispose_words (list);
1720 /***************************************************
1722 * Functions to Expand a String *
1724 ***************************************************/
1725 /* Call expand_word_internal to expand W and handle error returns.
1726 A convenience function for functions that don't want to handle
1727 any errors or free any memory before aborting. */
1729 call_expand_word_internal (w, q, c, e)
1735 result = expand_word_internal (w, q, c, e);
1736 if (result == &expand_word_error)
1737 jump_to_top_level (DISCARD);
1738 else if (result == &expand_word_fatal)
1739 jump_to_top_level (FORCE_EOF);
1744 /* Perform parameter expansion, command substitution, and arithmetic
1745 expansion on STRING, as if it were a word. Leave the result quoted. */
1747 expand_string_internal (string, quoted)
1754 if (string == 0 || *string == 0)
1755 return ((WORD_LIST *)NULL);
1757 bzero (&td, sizeof (td));
1759 tresult = call_expand_word_internal (&td, quoted, (int *)NULL, (int *)NULL);
1763 /* Expand STRING by performing parameter expansion, command substitution,
1764 and arithmetic expansion. Dequote the resulting WORD_LIST before
1765 returning it, but do not perform word splitting. The call to
1766 remove_quoted_nulls () is in here because word splitting normally
1767 takes care of quote removal. */
1769 expand_string_unsplit (string, quoted)
1775 if (!string || !*string)
1776 return ((WORD_LIST *)NULL);
1778 value = expand_string_internal (string, quoted);
1782 remove_quoted_nulls (value->word->word);
1783 dequote_list (value);
1788 /* Expand STRING just as if you were expanding a word, but do not dequote
1789 the resultant WORD_LIST. This is called only from within this file,
1790 and is used to correctly preserve quoted characters when expanding
1791 things like ${1+"$@"}. This does parameter expansion, command
1792 subsitution, arithmetic expansion, and word splitting. */
1794 expand_string_leave_quoted (string, quoted)
1801 if (string == 0 || *string == '\0')
1802 return ((WORD_LIST *)NULL);
1804 tlist = expand_string_internal (string, quoted);
1808 tresult = word_list_split (tlist);
1809 dispose_words (tlist);
1812 return ((WORD_LIST *)NULL);
1815 /* This does not perform word splitting or dequote the WORD_LIST
1818 expand_string_for_rhs (string, quoted, dollar_at_p, has_dollar_at)
1820 int quoted, *dollar_at_p, *has_dollar_at;
1825 if (string == 0 || *string == '\0')
1826 return (WORD_LIST *)NULL;
1828 bzero (&td, sizeof (td));
1830 tresult = call_expand_word_internal (&td, quoted, dollar_at_p, has_dollar_at);
1834 /* Expand STRING just as if you were expanding a word. This also returns
1835 a list of words. Note that filename globbing is *NOT* done for word
1836 or string expansion, just when the shell is expanding a command. This
1837 does parameter expansion, command substitution, arithmetic expansion,
1838 and word splitting. Dequote the resultant WORD_LIST before returning. */
1840 expand_string (string, quoted)
1846 if (!string || !*string)
1847 return ((WORD_LIST *)NULL);
1849 result = expand_string_leave_quoted (string, quoted);
1850 return (result ? dequote_list (result) : result);
1853 /***************************************************
1855 * Functions to handle quoting chars *
1857 ***************************************************/
1864 register WORD_LIST *tlist;
1866 for (tlist = list; tlist; tlist = tlist->next)
1868 s = dequote_string (tlist->word->word);
1869 free (tlist->word->word);
1870 tlist->word->word = s;
1876 make_quoted_char (c)
1896 /* Quote STRING. Return a new string. */
1898 quote_string (string)
1906 result = xmalloc (2);
1912 result = xmalloc ((strlen (string) * 2) + 1);
1914 for (t = result; *string; )
1924 /* De-quoted quoted characters in STRING. */
1926 dequote_string (string)
1932 result = xmalloc (strlen (string) + 1);
1934 if (QUOTED_NULL (string))
1940 /* If no character in the string can be quoted, don't bother examining
1941 each character. Just return a copy of the string passed to us. */
1942 if (strchr (string, CTLESC) == NULL) /* XXX */
1944 strcpy (result, string); /* XXX */
1945 return (result); /* XXX */
1948 for (t = result; *string; string++, t++)
1950 if (*string == CTLESC)
1965 /* Quote the entire WORD_LIST list. */
1970 register WORD_LIST *w;
1973 for (w = list; w; w = w->next)
1976 w->word->word = quote_string (t);
1978 w->word->flags |= W_QUOTED;
1983 /* **************************************************************** */
1985 /* Functions for Removing Patterns */
1987 /* **************************************************************** */
1989 /* Remove the portion of PARAM matched by PATTERN according to OP, where OP
1990 can have one of 4 values:
1991 RP_LONG_LEFT remove longest matching portion at start of PARAM
1992 RP_SHORT_LEFT remove shortest matching portion at start of PARAM
1993 RP_LONG_RIGHT remove longest matching portion at end of PARAM
1994 RP_SHORT_RIGHT remove shortest matching portion at end of PARAM
1997 #define RP_LONG_LEFT 1
1998 #define RP_SHORT_LEFT 2
1999 #define RP_LONG_RIGHT 3
2000 #define RP_SHORT_RIGHT 4
2003 remove_pattern (param, pattern, op)
2004 char *param, *pattern;
2009 register char *p, *ret, c;
2011 if (param == NULL || *param == '\0')
2013 if (pattern == NULL || *pattern == '\0') /* minor optimization */
2014 return (savestring (param));
2016 len = STRLEN (param);
2021 case RP_LONG_LEFT: /* remove longest match at start */
2022 for (p = end; p >= param; p--)
2025 if (fnmatch (pattern, param, 0) != FNM_NOMATCH)
2028 return (savestring (p));
2034 case RP_SHORT_LEFT: /* remove shortest match at start */
2035 for (p = param; p <= end; p++)
2038 if (fnmatch (pattern, param, 0) != FNM_NOMATCH)
2041 return (savestring (p));
2047 case RP_LONG_RIGHT: /* remove longest match at end */
2048 for (p = param; p <= end; p++)
2050 if (fnmatch (pattern, p, 0) != FNM_NOMATCH)
2053 ret = savestring (param);
2060 case RP_SHORT_RIGHT: /* remove shortest match at end */
2061 for (p = end; p >= param; p--)
2063 if (fnmatch (pattern, p, 0) != FNM_NOMATCH)
2066 ret = savestring (param);
2073 return (savestring (param)); /* no match, return original string */
2076 /* Return 1 of the first character of STRING could match the first
2077 character of pattern PAT. Used to avoid n2 calls to fnmatch(). */
2079 match_pattern_char (pat, string)
2092 return (*string == c);
2094 return (*string == *pat);
2099 for (np = pat; *np != ']'; np++);
2101 return (*string == '[');
2102 if (neg = (*pat == '!' || *pat == '^'))
2104 for ( ; (c1 = *pat++) != ']'; )
2110 if (*pat != '-' || pat[1] == '\0' || pat[1] == ']')
2111 return (neg ? *string != c1 : *string == c1);
2112 if (c1 <= *string && *string <= pat[1])
2119 /* Match PAT anywhere in STRING and return the match boundaries.
2120 This returns 1 in case of a successful match, 0 otherwise. SP
2121 and EP are pointers into the string where the match begins and
2122 ends, respectively. MTYPE controls what kind of match is attempted.
2123 MATCH_BEG and MATCH_END anchor the match at the beginning and end
2124 of the string, respectively. The longest match is returned. */
2126 match_pattern (string, pat, mtype, sp, ep)
2132 register char *p, *p1;
2135 if (string == 0 || *string == 0 || pat == 0 || *pat == 0)
2138 end = string + STRLEN (string);
2143 for (p = string; p <= end; p++)
2145 if (match_pattern_char (pat, p))
2147 for (p1 = end; p1 >= p; p1--)
2149 c = *p1; *p1 = '\0';
2150 if (fnmatch (pat, p, 0) == 0)
2164 if (match_pattern_char (pat, string) == 0)
2166 for (p = end; p >= string; p--)
2169 if (fnmatch (pat, string, 0) == 0)
2181 for (p = string; p <= end; p++)
2182 if (fnmatch (pat, p, 0) == 0)
2194 /*******************************************
2196 * Functions to expand WORD_DESCs *
2198 *******************************************/
2200 /* Expand WORD, performing word splitting on the result. This does
2201 parameter expansion, command substitution, arithmetic expansion,
2202 word splitting, and quote removal. */
2205 expand_word (word, quoted)
2209 WORD_LIST *result, *tresult;
2211 tresult = call_expand_word_internal (word, quoted, (int *)NULL, (int *)NULL);
2212 result = word_list_split (tresult);
2213 dispose_words (tresult);
2214 return (result ? dequote_list (result) : result);
2217 /* Expand WORD, but do not perform word splitting on the result. This
2218 does parameter expansion, command substitution, arithmetic expansion,
2219 and quote removal. */
2221 expand_word_no_split (word, quoted)
2227 result = call_expand_word_internal (word, quoted, (int *)NULL, (int *)NULL);
2228 return (result ? dequote_list (result) : result);
2231 /* Perform shell expansions on WORD, but do not perform word splitting or
2232 quote removal on the result. */
2234 expand_word_leave_quoted (word, quoted)
2238 return (call_expand_word_internal (word, quoted, (int *)NULL, (int *)NULL));
2241 /* Return the value of a positional parameter. This handles values > 10. */
2243 get_dollar_var_value (ind)
2250 temp = dollar_vars[ind] ? savestring (dollar_vars[ind]) : (char *)NULL;
2251 else /* We want something like ${11} */
2254 for (p = rest_of_args; p && ind--; p = p->next)
2256 temp = p ? savestring (p->word->word) : (char *)NULL;
2261 #if defined (PROCESS_SUBSTITUTION)
2263 /* **************************************************************** */
2265 /* Hacking Process Substitution */
2267 /* **************************************************************** */
2269 #if !defined (HAVE_DEV_FD)
2270 /* Named pipes must be removed explicitly with `unlink'. This keeps a list
2271 of FIFOs the shell has open. unlink_fifo_list will walk the list and
2272 unlink all of them. add_fifo_list adds the name of an open FIFO to the
2273 list. NFIFO is a count of the number of FIFOs in the list. */
2274 #define FIFO_INCR 20
2275 extern char *mktemp ();
2277 static char **fifo_list = (char **)NULL;
2279 static int fifo_list_size;
2282 add_fifo_list (pathname)
2285 if (nfifo >= fifo_list_size - 1)
2287 fifo_list_size += FIFO_INCR;
2288 fifo_list = (char **)xrealloc (fifo_list,
2289 fifo_list_size * sizeof (char *));
2292 fifo_list[nfifo++] = savestring (pathname);
2303 unlink (fifo_list[nfifo]);
2304 free (fifo_list[nfifo]);
2305 fifo_list[nfifo] = (char *)NULL;
2315 tname = mktemp (savestring ("/tmp/sh-np-XXXXXX"));
2316 if (mkfifo (tname, 0600) < 0)
2319 return ((char *)NULL);
2322 add_fifo_list (tname);
2326 #else /* HAVE_DEV_FD */
2328 /* DEV_FD_LIST is a bitmap of file descriptors attached to pipes the shell
2329 has open to children. NFDS is a count of the number of bits currently
2330 set in DEV_FD_LIST. TOTFDS is a count of the highest possible number
2332 static char *dev_fd_list = (char *)NULL;
2334 static int totfds; /* The highest possible number of open files. */
2340 if (!dev_fd_list || fd >= totfds)
2345 totfds = getdtablesize ();
2346 if (totfds < 0 || totfds > 256)
2351 dev_fd_list = xrealloc (dev_fd_list, totfds);
2352 bzero (dev_fd_list + ofds, totfds - ofds);
2355 dev_fd_list[fd] = 1;
2367 for (i = 0; nfds && i < totfds; i++)
2378 #if defined (NOTDEF)
2379 print_dev_fd_list ()
2383 fprintf (stderr, "pid %d: dev_fd_list:", getpid ());
2386 for (i = 0; i < totfds; i++)
2389 fprintf (stderr, " %d", i);
2391 fprintf (stderr, "\n");
2396 make_dev_fd_filename (fd)
2402 sprintf (ret, "%s%d", DEV_FD_PREFIX, fd);
2407 #endif /* HAVE_DEV_FD */
2409 /* Return a filename that will open a connection to the process defined by
2410 executing STRING. HAVE_DEV_FD, if defined, means open a pipe and return
2411 a filename in /dev/fd corresponding to a descriptor that is one of the
2412 ends of the pipe. If not defined, we use named pipes on systems that have
2413 them. Systems without /dev/fd and named pipes are out of luck.
2415 OPEN_FOR_READ_IN_CHILD, if 1, means open the named pipe for reading or
2416 use the read end of the pipe and dup that file descriptor to fd 0 in
2417 the child. If OPEN_FOR_READ_IN_CHILD is 0, we open the named pipe for
2418 writing or use the write end of the pipe in the child, and dup that
2419 file descriptor to fd 1 in the child. The parent does the opposite. */
2422 process_substitute (string, open_for_read_in_child)
2424 int open_for_read_in_child;
2429 #if defined (HAVE_DEV_FD)
2430 int parent_pipe_fd, child_pipe_fd;
2432 #endif /* HAVE_DEV_FD */
2433 #if defined (JOB_CONTROL)
2434 pid_t old_pipeline_pgrp;
2437 if (!string || !*string)
2438 return ((char *)NULL);
2440 #if !defined (HAVE_DEV_FD)
2441 pathname = make_named_pipe ();
2442 #else /* HAVE_DEV_FD */
2443 if (pipe (fildes) < 0)
2445 sys_error ("cannot make pipe for process substitution");
2446 return ((char *)NULL);
2448 /* If OPEN_FOR_READ_IN_CHILD == 1, we want to use the write end of
2449 the pipe in the parent, otherwise the read end. */
2450 parent_pipe_fd = fildes[open_for_read_in_child];
2451 child_pipe_fd = fildes[1 - open_for_read_in_child];
2452 pathname = make_dev_fd_filename (parent_pipe_fd);
2453 #endif /* HAVE_DEV_FD */
2457 sys_error ("cannot make pipe for process substitution");
2458 return ((char *)NULL);
2461 old_pid = last_made_pid;
2463 #if defined (JOB_CONTROL)
2464 old_pipeline_pgrp = pipeline_pgrp;
2465 pipeline_pgrp = shell_pgrp;
2467 cleanup_the_pipeline ();
2471 #endif /* JOB_CONTROL */
2473 pid = make_child ((char *)NULL, 1);
2476 reset_terminating_signals (); /* XXX */
2477 /* Cancel traps, in trap.c. */
2478 restore_original_signals ();
2479 setup_async_signals ();
2480 subshell_environment = SUBSHELL_COMSUB;
2483 #if defined (JOB_CONTROL)
2484 set_sigchld_handler ();
2485 stop_making_children ();
2486 pipeline_pgrp = old_pipeline_pgrp;
2487 #endif /* JOB_CONTROL */
2491 sys_error ("cannot make child for process substitution");
2493 #if defined (HAVE_DEV_FD)
2494 close (parent_pipe_fd);
2495 close (child_pipe_fd);
2496 #endif /* HAVE_DEV_FD */
2497 return ((char *)NULL);
2502 #if defined (JOB_CONTROL)
2503 restore_pipeline (1);
2506 last_made_pid = old_pid;
2508 #if defined (JOB_CONTROL) && defined (PGRP_PIPE)
2510 #endif /* JOB_CONTROL && PGRP_PIPE */
2512 #if defined (HAVE_DEV_FD)
2513 close (child_pipe_fd);
2514 #endif /* HAVE_DEV_FD */
2519 set_sigint_handler ();
2521 #if defined (JOB_CONTROL)
2522 set_job_control (0);
2523 #endif /* JOB_CONTROL */
2525 #if !defined (HAVE_DEV_FD)
2526 /* Open the named pipe in the child. */
2527 fd = open (pathname, open_for_read_in_child ? O_RDONLY|O_NONBLOCK : O_WRONLY);
2530 sys_error ("cannot open named pipe %s for %s", pathname,
2531 open_for_read_in_child ? "reading" : "writing");
2534 #else /* HAVE_DEV_FD */
2536 #endif /* HAVE_DEV_FD */
2538 if (dup2 (fd, open_for_read_in_child ? 0 : 1) < 0)
2540 sys_error ("cannot duplicate named pipe %s as fd %d", pathname,
2541 open_for_read_in_child ? 0 : 1);
2547 /* Need to close any files that this process has open to pipes inherited
2549 if (current_fds_to_close)
2551 close_fd_bitmap (current_fds_to_close);
2552 current_fds_to_close = (struct fd_bitmap *)NULL;
2555 #if defined (HAVE_DEV_FD)
2556 /* Make sure we close the parent's end of the pipe and clear the slot
2557 in the fd list so it is not closed later, if reallocated by, for
2558 instance, pipe(2). */
2559 close (parent_pipe_fd);
2560 dev_fd_list[parent_pipe_fd] = 0;
2561 #endif /* HAVE_DEV_FD */
2563 result = parse_and_execute (string, "process substitution", 0);
2565 #if !defined (HAVE_DEV_FD)
2566 /* Make sure we close the named pipe in the child before we exit. */
2567 close (open_for_read_in_child ? 0 : 1);
2568 #endif /* !HAVE_DEV_FD */
2573 #endif /* PROCESS_SUBSTITUTION */
2575 /* Perform command substitution on STRING. This returns a string,
2578 command_substitute (string, quoted)
2582 pid_t pid, old_pid, old_pipeline_pgrp;
2584 int istring_index, istring_size, c, result, fildes[2];
2587 istring_index = istring_size = 0;
2588 istring = (char *)NULL;
2590 /* Don't fork () if there is no need to. In the case of no command to
2591 run, just return NULL. */
2592 if (!string || !*string || (string[0] == '\n' && !string[1]))
2593 return ((char *)NULL);
2595 /* Pipe the output of executing STRING into the current shell. */
2596 if (pipe (fildes) < 0)
2598 sys_error ("cannot make pipes for command substitution");
2602 old_pid = last_made_pid;
2603 #if defined (JOB_CONTROL)
2604 old_pipeline_pgrp = pipeline_pgrp;
2605 pipeline_pgrp = shell_pgrp;
2606 cleanup_the_pipeline ();
2609 pid = make_child ((char *)NULL, 0);
2611 /* Reset the signal handlers in the child, but don't free the
2613 reset_signal_handlers ();
2615 #if defined (JOB_CONTROL)
2616 set_sigchld_handler ();
2617 stop_making_children ();
2618 pipeline_pgrp = old_pipeline_pgrp;
2619 #endif /* JOB_CONTROL */
2623 sys_error ("cannot make child for command substitution");
2629 return ((char *)NULL);
2634 set_sigint_handler (); /* XXX */
2635 #if defined (JOB_CONTROL)
2636 set_job_control (0);
2638 if (dup2 (fildes[1], 1) < 0)
2640 sys_error ("command_substitute: cannot duplicate pipe as fd 1");
2641 exit (EXECUTION_FAILURE);
2644 /* If standard output is closed in the parent shell
2645 (such as after `exec >&-'), file descriptor 1 will be
2646 the lowest available file descriptor, and end up in
2647 fildes[0]. This can happen for stdin and stderr as well,
2648 but stdout is more important -- it will cause no output
2649 to be generated from this command. */
2650 if ((fildes[1] != fileno (stdin)) &&
2651 (fildes[1] != fileno (stdout)) &&
2652 (fildes[1] != fileno (stderr)))
2655 if ((fildes[0] != fileno (stdin)) &&
2656 (fildes[0] != fileno (stdout)) &&
2657 (fildes[0] != fileno (stderr)))
2660 /* The currently executing shell is not interactive. */
2663 /* This is a subshell environment. */
2664 subshell_environment = SUBSHELL_COMSUB;
2666 /* Command substitution does not inherit the -e flag. */
2667 exit_immediately_on_error = 0;
2669 remove_quoted_escapes (string);
2671 startup_state = 2; /* see if we can avoid a fork */
2672 /* Give command substitution a place to jump back to on failure,
2673 so we don't go back up to main (). */
2674 result = setjmp (top_level);
2676 if (result == EXITPROG)
2677 exit (last_command_exit_value);
2679 exit (EXECUTION_FAILURE);
2681 exit (parse_and_execute (string, "command substitution", -1));
2685 istream = fdopen (fildes[0], "r");
2687 #if defined (JOB_CONTROL) && defined (PGRP_PIPE)
2689 #endif /* JOB_CONTROL && PGRP_PIPE */
2695 sys_error ("cannot reopen pipe to command substitution (fd %d)", fildes[0]);
2699 /* Read the output of the command through the pipe. */
2702 #if !defined (HAVE_RESTARTABLE_SYSCALLS)
2703 c = getc_with_restart (istream);
2706 #endif /* HAVE_RESTARTABLE_SYSCALLS */
2711 /* Add the character to ISTRING, possibly after resizing it. */
2712 RESIZE_MALLOCED_BUFFER (istring, istring_index, 2, istring_size, DEFAULT_ARRAY_SIZE);
2714 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || c == CTLESC || c == CTLNUL)
2715 istring[istring_index++] = CTLESC;
2717 istring[istring_index++] = c;
2721 istring[istring_index] = '\0';
2726 last_command_exit_value = wait_for (pid);
2727 last_command_subst_pid = pid;
2728 last_made_pid = old_pid;
2730 #if defined (JOB_CONTROL)
2731 /* If last_command_exit_value > 128, then the substituted command
2732 was terminated by a signal. If that signal was SIGINT, then send
2733 SIGINT to ourselves. This will break out of loops, for instance. */
2734 if (last_command_exit_value == (128 + SIGINT))
2735 kill (getpid (), SIGINT);
2737 /* wait_for gives the terminal back to shell_pgrp. If some other
2738 process group should have it, give it away to that group here. */
2739 if (interactive && pipeline_pgrp != (pid_t)0)
2740 give_terminal_to (pipeline_pgrp);
2741 #endif /* JOB_CONTROL */
2743 /* If we read no output, just return now and save ourselves some
2745 if (istring_index == 0)
2748 /* Strip trailing newlines from the output of the command. */
2749 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
2751 while (istring_index > 0)
2753 if (istring[istring_index - 1] == '\n')
2757 /* If the newline was quoted, remove the quoting char. */
2758 if (istring[istring_index - 1] == CTLESC)
2764 istring[istring_index] = '\0';
2767 strip_trailing (istring, 1);
2773 /********************************************************
2775 * Utility functions for parameter expansion *
2777 ********************************************************/
2780 getpatspec (c, value)
2785 return ((*value == '#') ? RP_LONG_LEFT : RP_SHORT_LEFT);
2787 return ((*value == '%') ? RP_LONG_RIGHT : RP_SHORT_RIGHT);
2790 /* Posix.2 says that the WORD should be run through tilde expansion,
2791 parameter expansion, command substitution and arithmetic expansion.
2792 This leaves the result quoted, so quote_string_for_globbing () has
2793 to be called to fix it up for fnmatch (). If QUOTED is non-zero,
2794 it means that the entire expression was enclosed in double quotes.
2795 This means that quoting characters in the pattern do not make any
2796 special pattern characters quoted. For example, the `*' in the
2797 following retains its special meaning: "${foo#'*'}". */
2799 getpattern (value, quoted, expandpat)
2801 int quoted, expandpat;
2807 tword = strchr (value, '~') ? bash_tilde_expand (value) : savestring (value);
2809 /* expand_string_internal () leaves WORD quoted and does not perform
2811 if (expandpat && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && *tword)
2814 pat = string_extract_double_quoted (tword, &i, 1);
2819 /* There is a problem here: how to handle single or double quotes in the
2820 pattern string when the whole expression is between double quotes? */
2822 l = *tword ? expand_string_for_rhs (tword, quoted, (int *)NULL, (int *)NULL)
2824 l = *tword ? expand_string_for_rhs (tword,
2825 (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? Q_NOQUOTE : quoted,
2826 (int *)NULL, (int *)NULL)
2830 pat = string_list (l);
2834 tword = quote_string_for_globbing (pat, 1);
2841 /* Handle removing a pattern from a string as a result of ${name%[%]value}
2842 or ${name#[#]value}. */
2844 parameter_brace_remove_pattern (value, temp, c, quoted)
2849 char *pattern, *tword;
2851 patspec = getpatspec (c, value);
2852 if (patspec == RP_LONG_LEFT || patspec == RP_LONG_RIGHT)
2855 pattern = getpattern (value, quoted, 1);
2857 tword = remove_pattern (temp, pattern, patspec);
2864 list_remove_pattern (list, pattern, patspec, type, quoted)
2867 int patspec, type, quoted;
2873 for (new = (WORD_LIST *)NULL, l = list; l; l = l->next)
2875 tword = remove_pattern (l->word->word, pattern, patspec);
2876 w = make_bare_word (tword);
2877 new = make_word_list (w, new);
2880 l = REVERSE_LIST (new, WORD_LIST *);
2882 tword = (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? string_list_dollar_star (l) : string_list (l);
2884 tword = string_list ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? quote_list (l) : l);
2891 parameter_list_remove_pattern (value, type, c, quoted)
2893 int type, c, quoted;
2898 patspec = getpatspec (c, value);
2899 if (patspec == RP_LONG_LEFT || patspec == RP_LONG_RIGHT)
2902 pattern = getpattern (value, quoted, 1);
2904 return (list_remove_pattern (list_rest_of_args (), pattern, patspec, type, quoted));
2907 #if defined (ARRAY_VARS)
2909 array_remove_pattern (value, aspec, aval, c, quoted)
2910 char *value, *aspec, *aval; /* AVAL == evaluated ASPEC */
2918 char *ret, *t, *pattern;
2921 var = array_variable_part (aspec, &t, &len);
2923 return ((char *)NULL);
2925 patspec = getpatspec (c, value);
2926 if (patspec == RP_LONG_LEFT || patspec == RP_LONG_RIGHT)
2929 pattern = getpattern (value, quoted, 1);
2931 if (ALL_ELEMENT_SUB (t[0]) && t[1] == ']')
2933 if (array_p (var) == 0)
2935 report_error ("%s: bad array subscript", aspec);
2936 return ((char *)NULL);
2938 l = array_to_word_list (array_cell (var));
2940 return ((char *)NULL);
2941 ret = list_remove_pattern (l, pattern, patspec, t[0], quoted);
2947 ind = array_expand_index (t, len);
2950 report_error ("%s: bad array subscript", aspec);
2951 return ((char *)NULL);
2953 if (array_p (var) == 0 && ind != 0)
2954 return ((char *)NULL);
2956 t = array_p (var) ? array_reference (array_cell (var), ind) : value_cell (var);
2957 ret = remove_pattern (t, pattern, patspec);
2959 ret = remove_pattern (aval, pattern, patspec);
2962 quote_escapes (ret);
2968 valid_array_reference (name)
2974 t = strchr (name, '[');
2978 r = legal_identifier (name);
2982 /* Check for a properly-terminated non-blank subscript. */
2983 len = skipsubscript (t, 0);
2984 if (t[len] != ']' || len == 1)
2986 for (r = 1; r < len; r++)
2987 if (whitespace (t[r]) == 0)
2994 /* Expand the array index beginning at S and extending LEN characters. */
2996 array_expand_index (s, len)
3003 exp = xmalloc (len);
3004 strncpy (exp, s, len - 1);
3005 exp[len - 1] = '\0';
3006 t = maybe_expand_string (exp, 0, expand_string);
3007 this_command_name = (char *)NULL;
3014 /* Return the variable specified by S without any subscript. If non-null,
3015 return the index of the start of the subscript in *SUBP. If non-null,
3016 the length of the subscript is returned in *LENP. */
3018 array_variable_part (s, subp, lenp)
3026 t = strchr (s, '[');
3028 ni = skipsubscript (s, ind);
3029 if (ni <= ind + 1 || s[ni] != ']')
3031 report_error ("%s: bad array subscript", s);
3032 return ((SHELL_VAR *)NULL);
3036 var = find_variable (s);
3047 array_value_internal (s, quoted, allow_all)
3049 int quoted, allow_all;
3056 var = array_variable_part (s, &t, &len);
3059 return (char *)NULL;
3061 if (ALL_ELEMENT_SUB (t[0]) && t[1] == ']')
3063 if (array_p (var) == 0 || allow_all == 0)
3065 report_error ("%s: bad array subscript", s);
3066 return ((char *)NULL);
3068 l = array_to_word_list (array_cell (var));
3069 if (l == (WORD_LIST *)NULL)
3070 return ((char *) NULL);
3072 if (t[0] == '*') /* ${name[*]} */
3073 retval = (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? string_list_dollar_star (l) : string_list (l);
3074 else /* ${name[@]} */
3075 retval = string_list ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? quote_list (l) : l);
3081 ind = array_expand_index (t, len);
3084 report_error ("%s: bad array subscript", var->name);
3085 return ((char *)NULL);
3087 if (array_p (var) == 0)
3088 return (ind == 0 ? value_cell (var) : (char *)NULL);
3089 retval = array_reference (array_cell (var), ind);
3091 retval = quote_escapes (retval);
3098 array_value (s, quoted)
3102 return (array_value_internal (s, quoted, 1));
3105 /* Return the value of the array indexing expression S as a single string.
3106 If ALLOW_ALL is 0, do not allow `@' and `*' subscripts. This is used
3107 by other parts of the shell such as the arithmetic expression evaluator
3110 get_array_value (s, allow_all)
3114 return (array_value_internal (s, 0, allow_all));
3118 array_length_reference (s)
3126 var = array_variable_part (s, &t, &len);
3128 /* If unbound variables should generate an error, report one and return
3130 if ((var == 0 || array_p (var) == 0) && unbound_vars_is_error)
3134 report_error ("%s: unbound variable", s);
3140 else if (array_p (var) == 0)
3143 array = array_cell (var);
3145 if (ALL_ELEMENT_SUB (t[0]) && t[1] == ']')
3146 return (array_num_elements (array));
3148 ind = array_expand_index (t, len);
3151 report_error ("%s: bad array subscript", t);
3154 t = array_reference (array, ind);
3159 #endif /* ARRAY_VARS */
3162 valid_brace_expansion_word (name, var_is_special)
3166 if (digit (*name) && all_digits (name))
3168 else if (var_is_special)
3170 #if defined (ARRAY_VARS)
3171 else if (valid_array_reference (name))
3173 #endif /* ARRAY_VARS */
3174 else if (legal_identifier (name))
3180 /* Parameter expand NAME, and return a new string which is the expansion,
3181 or NULL if there was no expansion.
3182 VAR_IS_SPECIAL is non-zero if NAME is one of the special variables in
3183 the shell, e.g., "@", "$", "*", etc. QUOTED, if non-zero, means that
3184 NAME was found inside of a double-quoted expression. */
3186 parameter_brace_expand_word (name, var_is_special, quoted)
3188 int var_is_special, quoted;
3195 /* Handle multiple digit arguments, as in ${11}. */
3198 arg_index = atoi (name);
3199 temp = get_dollar_var_value (arg_index);
3201 else if (var_is_special) /* ${@} */
3203 tt = xmalloc (2 + strlen (name));
3205 strcpy (tt + 1, name);
3206 l = expand_string_leave_quoted (tt, quoted);
3208 temp = string_list (l);
3211 #if defined (ARRAY_VARS)
3212 else if (valid_array_reference (name))
3214 temp = array_value (name, quoted);
3217 else if (var = find_variable (name))
3219 if (var && invisible_p (var) == 0)
3221 #if defined (ARRAY_VARS)
3222 temp = array_p (var) ? array_reference (array_cell (var), 0) : value_cell (var);
3224 temp = value_cell (var);
3228 temp = quote_escapes (temp);
3231 temp = (char *)NULL;
3234 temp = (char *)NULL;
3239 /* Expand an indirect reference to a variable: ${!NAME} expands to the
3240 value of the variable whose name is the value of NAME. */
3242 parameter_brace_expand_indir (name, var_is_special, quoted)
3244 int var_is_special, quoted;
3248 t = parameter_brace_expand_word (name, var_is_special, quoted);
3251 temp = parameter_brace_expand_word (t, t[0] == '@' && t[1] == '\0', quoted);
3256 /* Expand the right side of a parameter expansion of the form ${NAMEcVALUE},
3257 depending on the value of C, the separating character. C can be one of
3258 "-", "+", or "=". QUOTED is true if the entire brace expression occurs
3259 between double quotes. */
3261 parameter_brace_expand_rhs (name, value, c, quoted, qdollaratp, hasdollarat)
3263 int c, quoted, *qdollaratp, *hasdollarat;
3266 char *t, *t1, *temp;
3269 temp = (*value == '~' || (strchr (value, '~') && unquoted_substring ("=~", value)))
3270 ? bash_tilde_expand (value)
3271 : savestring (value);
3273 /* If the entire expression is between double quotes, we want to treat
3274 the value as a double-quoted string, with the exception that we strip
3275 embedded unescaped double quotes. */
3276 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && *temp)
3279 t = string_extract_double_quoted (temp, &hasdol, 1);
3285 /* XXX was 0 not quoted */
3286 l = *temp ? expand_string_for_rhs (temp, quoted, &hasdol, (int *)NULL)
3289 *hasdollarat = hasdol || (l && l->next);
3293 /* The expansion of TEMP returned something. We need to treat things
3294 slightly differently if HASDOL is non-zero. */
3295 temp = string_list (l);
3296 /* If l->next is not null, we know that TEMP contained "$@", since that
3297 is the only expansion that creates more than one word. */
3298 if ((hasdol && quoted) || l->next)
3302 else if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && hasdol)
3304 /* The brace expansion occurred between double quotes and there was
3305 a $@ in TEMP. It does not matter if the $@ is quoted, as long as
3306 it does not expand to anything. In this case, we want to return
3307 a quoted empty string. */
3313 temp = (char *)NULL;
3315 if (c == '-' || c == '+')
3319 t = temp ? savestring (temp) : savestring ("");
3320 t1 = dequote_string (t);
3322 bind_variable (name, t1);
3327 /* Deal with the right hand side of a ${name:?value} expansion in the case
3328 that NAME is null or not set. If VALUE is non-null it is expanded and
3329 used as the error message to print, otherwise a standard message is
3332 parameter_brace_expand_error (name, value)
3338 if (value && *value)
3340 l = expand_string (value, 0);
3341 temp = string_list (l);
3342 report_error ("%s: %s", name, temp ? temp : ""); /* XXX was value not "" */
3347 report_error ("%s: parameter null or not set", name);
3349 /* Free the data we have allocated during this expansion, since we
3350 are about to longjmp out. */
3355 /* Return 1 if NAME is something for which parameter_brace_expand_length is
3358 valid_length_expression (name)
3361 return (!name[1] || /* ${#} */
3362 ((name[1] == '@' || name[1] == '*') && !name[2]) || /* ${#@}, ${#*} */
3363 (digit (name[1]) && all_digits (name + 1)) || /* ${#11} */
3364 #if defined (ARRAY_VARS)
3365 valid_array_reference (name + 1) || /* ${#a[7]} */
3367 legal_identifier (name + 1)); /* ${#PS1} */
3370 /* Handle the parameter brace expansion that requires us to return the
3371 length of a parameter. */
3373 parameter_brace_expand_length (name)
3379 #if defined (ARRAY_VARS)
3383 if (name[1] == '\0') /* ${#} */
3384 number = number_of_args ();
3385 #if defined (ARRAY_VARS)
3386 else if (valid_array_reference (name + 1))
3387 number = array_length_reference (name + 1);
3388 #endif /* ARRAY_VARS */
3389 else if (name[1] != '*' && name[1] != '@')
3393 if (digit (name[1])) /* ${#1} */
3395 t = get_dollar_var_value (atoi (name + 1));
3396 number = STRLEN (t);
3399 #if defined (ARRAY_VARS)
3400 else if ((var = find_variable (name + 1)) && array_p (var))
3402 t = array_reference (array_cell (var), 0);
3403 number = STRLEN (t);
3408 newname = savestring (name);
3410 list = expand_string (newname, Q_DOUBLE_QUOTES);
3411 t = list ? string_list (list) : (char *)NULL;
3414 dispose_words (list);
3416 number = STRLEN (t);
3420 else /* ${#@} and ${#*} */
3421 number = number_of_args ();
3426 /* Verify and limit the start and end of the desired substring. If
3427 VTYPE == 0, a regular shell variable is being used; if it is 1,
3428 then the positional paramters are being used; if it is 2, then
3429 VALUE is really a pointer to an array variable that should be used. */
3431 verify_substring_values (value, substr, vtype, e1p, e2p)
3432 char *value, *substr;
3433 int vtype, *e1p, *e2p;
3437 #if defined (ARRAY_VARS)
3441 t = strchr (substr, ':');
3444 temp1 = maybe_expand_string (substr, 1, expand_string);
3445 *e1p = evalexp (temp1);
3451 len = strlen (value);
3454 len = number_of_args () + 1;
3456 #if defined (ARRAY_VARS)
3459 len = array_num_elements (a) + 1;
3464 if (*e1p < 0) /* negative offsets count from end */
3470 temp1 = maybe_expand_string (t, 1, expand_string);
3472 *e2p = evalexp (temp1);
3476 internal_error ("%s: substring expression < 0", t);
3479 *e2p += *e1p; /* want E2 chars starting at E1 */
3489 /* Return a string containing the positional parameters from START to
3490 END, inclusive. If STRING[0] == '*', we obey the rules for $*,
3491 which only makes a difference if QUOTED is non-zero. */
3493 pos_params (string, start, end, quoted)
3495 int start, end, quoted;
3497 WORD_LIST *save, *params, *h, *t;
3501 save = params = list_rest_of_args ();
3503 return ((char *)NULL);
3505 for (i = 1; params && i < start; i++)
3506 params = params->next;
3508 return ((char *)NULL);
3509 for (h = t = params; params && i < end; i++)
3512 params = params->next;
3515 t->next = (WORD_LIST *)NULL;
3516 if (string[0] == '*')
3517 ret = (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? string_list_dollar_star (h) : string_list (h);
3519 ret = string_list ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? quote_list (h) : h);
3522 dispose_words (save);
3526 /* Return the type of variable specified by VARNAME (simple variable,
3527 positional param, or array variable. Also return the value specified
3528 by VARNAME (value of a variable or a reference to an array element). */
3530 get_var_and_type (varname, value, varp, valp)
3531 char *varname, *value;
3537 #if defined (ARRAY_VARS)
3541 vtype = (varname[0] == '@' || varname[0] == '*') && varname[1] == '\0'; /* VT_POSPARMS */
3542 *varp = (SHELL_VAR *)NULL;
3544 #if defined (ARRAY_VARS)
3545 if (valid_array_reference (varname))
3547 v = array_variable_part (varname, &temp, (int *)0);
3548 if (v && array_p (v))
3550 if (temp[0] == '@' && temp[1] == ']')
3552 vtype = VT_ARRAYVAR;
3553 *valp = (char *)array_cell (v);
3557 vtype = VT_VARIABLE;
3558 *valp = array_value (varname, 1);
3565 else if ((v = find_variable (varname)) && array_p (v))
3567 vtype = VT_VARIABLE;
3569 *valp = array_reference (array_cell (v), 0);
3578 /* Process a variable substring expansion: ${name:e1[:e2]}. If VARNAME
3579 is `@', use the positional parameters; otherwise, use the value of
3580 VARNAME. If VARNAME is an array variable, use the array elements. */
3583 parameter_brace_substring (varname, value, substr, quoted)
3584 char *varname, *value, *substr;
3592 return ((char *)NULL);
3594 this_command_name = varname;
3596 vtype = get_var_and_type (varname, value, &v, &val);
3598 return ((char *)NULL);
3600 if (verify_substring_values (val, substr, vtype, &e1, &e2) == 0)
3601 return (&expand_param_error);
3606 temp = quoted ? quoted_substring (value, e1, e2) : substring (value, e1, e2);
3609 temp = pos_params (varname, e1, e2, quoted);
3611 #if defined (ARRAY_VARS)
3613 temp = array_subrange (array_cell (v), e1, e2, quoted);
3622 pat_subst (string, pat, rep, mflags)
3623 char *string, *pat, *rep;
3626 char *ret, *s, *e, *str;
3627 int rsize, rptr, l, replen, mtype;
3629 ret = xmalloc (rsize = 64);
3632 mtype = mflags & MATCH_TYPEMASK;
3634 for (replen = STRLEN (rep), rptr = 0, str = string;;)
3636 if (match_pattern (str, pat, mtype, &s, &e) == 0)
3639 RESIZE_MALLOCED_BUFFER (ret, rptr, (l + replen), rsize, 64);
3641 /* OK, now copy the leading unmatched portion of the string (from
3642 str to s) to ret starting at rptr (the current offset). Then copy
3643 the replacement string at ret + rptr + (s - str). Increment
3644 rptr (if necessary) and str and go on. */
3647 strncpy (ret + rptr, str, l);
3652 strncpy (ret + rptr, rep, replen);
3655 str = e; /* e == end of match */
3656 if (((mflags & MATCH_GLOBREP) == 0) || mtype != MATCH_ANY)
3660 /* Now copy the unmatched portion of the input string */
3662 strcpy (ret + rptr, str);
3669 /* Do pattern match and replacement on the positional parameters. */
3671 pos_params_pat_subst (string, pat, rep, mflags)
3672 char *string, *pat, *rep;
3675 WORD_LIST *save, *params;
3679 save = params = list_rest_of_args ();
3681 return ((char *)NULL);
3683 for ( ; params; params = params->next)
3685 ret = pat_subst (params->word->word, pat, rep, mflags);
3686 w = make_bare_word (ret);
3687 dispose_word (params->word);
3692 ret = string_list ((mflags & MATCH_QUOTED) ? quote_list (save) : save);
3693 dispose_words (save);
3699 parameter_brace_patsub (varname, value, patsub, quoted)
3700 char *varname, *value, *patsub;
3704 char *val, *temp, *pat, *rep, *p;
3708 return ((char *)NULL);
3710 this_command_name = varname;
3712 vtype = get_var_and_type (varname, value, &v, &val);
3714 return ((char *)NULL);
3719 mflags |= MATCH_GLOBREP;
3723 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
3724 mflags |= MATCH_QUOTED;
3726 if (rep = quoted_strchr (patsub, '/', ST_BACKSL))
3731 if (rep && *rep == '\0')
3734 /* Expand PAT and REP for command, variable and parameter, arithmetic,
3735 and process substitution. Also perform quote removal. Do not
3736 perform word splitting or filename generation. */
3737 pat = maybe_expand_string (patsub, quoted, expand_string_unsplit);
3739 rep = maybe_expand_string (rep, quoted, expand_string_unsplit);
3744 mflags |= MATCH_BEG;
3747 else if (pat[0] == '%')
3749 mflags |= MATCH_END;
3753 mflags |= MATCH_ANY;
3755 /* OK, we now want to substitute REP for PAT in VAL. If GLOBAL is 1,
3756 the substitution is done everywhere, otherwise only the first
3757 occurrence of PAT is replaced. */
3761 temp = pat_subst (val, p, rep, mflags);
3764 temp = pos_params_pat_subst (val, p, rep, mflags);
3766 #if defined (ARRAY_VARS)
3768 temp = array_pat_subst (array_cell (v), p, rep, mflags);
3779 /* ${[#][!]name[[:]#[#]%[%]-=?+[word][:e1[:e2]]]} */
3781 parameter_brace_expand (string, indexp, quoted, quoted_dollar_atp, contains_dollar_at)
3783 int *indexp, quoted, *quoted_dollar_atp, *contains_dollar_at;
3785 int check_nullness, var_is_set, var_is_null, var_is_special;
3786 int want_substring, want_indir, want_patsub;
3787 char *name, *value, *temp, *temp1;
3788 int t_index, sindex, c, number;
3792 name = string_extract (string, &t_index, "#%:-=?+/}", 1);
3793 value = (char *)NULL;
3794 var_is_set = var_is_null = var_is_special = check_nullness = 0;
3795 want_substring = want_indir = want_patsub = 0;
3797 /* If the name really consists of a special variable, then
3798 make sure that we have the entire name. Handle indirect
3799 references to special variables here, too. */
3800 if ((sindex == t_index ||
3801 ((sindex == t_index - 1) && string[sindex] == '!')) &&
3802 (string[t_index] == '-' ||
3803 string[t_index] == '?' ||
3804 string[t_index] == '#'))
3808 temp1 = string_extract (string, &t_index, "#%:-=?+/}", 0);
3809 name = xmalloc (3 + (strlen (temp1)));
3810 *name = string[sindex];
3811 if (string[sindex] == '!')
3813 /* indirect ref. of special variable */
3814 name[1] = string[sindex + 1];
3815 strcpy (name + 2, temp1);
3818 strcpy (name + 1, temp1);
3823 /* Find out what character ended the variable name. Then
3824 do the appropriate thing. */
3825 if (c = string[sindex])
3828 /* If c is followed by one of the valid parameter expansion
3829 characters, move past it as normal. If not, assume that
3830 a substring specification is being given, and do not move
3832 if (c == ':' && member (string[sindex], "-=?+"))
3835 if (c = string[sindex])
3843 want_indir = *name == '!';
3845 /* Determine the value of this variable. */
3847 /* Check for special variables, directly and indirectly
3849 if ((digit (*name) && all_digits (name)) ||
3850 (name[1] == '\0' && member (*name, "#-?$!@*")) ||
3851 (want_indir && name[2] == '\0' && member (name[1], "#-?$!@*")))
3854 /* Check for special expansion things. */
3855 if (*name == '#') /* length of a parameter */
3857 /* Take the lengths of some of the shell's special
3859 if (string[sindex] == '}' && name[1] == '\0' &&
3860 check_nullness == 0 && member (c, "-?$!#"))
3866 temp1 = which_set_flags ();
3869 temp1 = itos (last_command_exit_value);
3872 temp1 = itos (dollar_dollar_pid);
3875 if (last_asynchronous_pid == NO_PID)
3876 temp1 = (char *)NULL;
3878 temp1 = itos ((int)last_asynchronous_pid);
3881 temp1 = itos (number_of_args ());
3884 number = STRLEN (temp1);
3886 *indexp = ++sindex; /* { string[sindex] == '}' */
3887 return (itos (number));
3890 /* Don't allow things like ${#:-foo} to go by; they are
3891 errors. If we are not pointing at the character just
3892 after the closing brace, then we haven't gotten all of
3893 the name. Since it begins with a special character,
3894 this is a bad substitution. Explicitly check for ${#:},
3895 which the rules do not catch. Also check NAME for
3896 validity before trying to go on. */
3897 if (string[sindex - 1] != '}' ||
3898 member (c, "?-=+") ||
3899 (name[1] == '\0' && c == '}' && check_nullness) ||
3900 (valid_length_expression (name) == 0))
3902 temp = (char *)NULL;
3903 goto bad_substitution;
3906 number = parameter_brace_expand_length (name);
3910 return ((number < 0) ? &expand_param_error : itos (number));
3913 /* ${@} is identical to $@. */
3914 if (name[0] == '@' && name[1] == '\0')
3916 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
3917 *quoted_dollar_atp = 1;
3919 if (contains_dollar_at)
3920 *contains_dollar_at = 1;
3923 /* Make sure that NAME is valid before trying to go on. */
3924 if (valid_brace_expansion_word (want_indir ? name + 1 : name,
3925 var_is_special) == 0)
3927 temp = (char *)NULL;
3928 goto bad_substitution;
3932 temp = parameter_brace_expand_indir (name + 1, var_is_special, quoted);
3934 temp = parameter_brace_expand_word (name, var_is_special, quoted);
3936 #if defined (ARRAY_VARS)
3937 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && valid_array_reference (name))
3939 temp1 = strchr (name, '[');
3940 if (temp1 && temp1[1] == '@' && temp1[2] == ']')
3942 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
3943 *quoted_dollar_atp = 1;
3944 if (contains_dollar_at)
3945 *contains_dollar_at = 1;
3950 var_is_set = temp != (char *)0;
3951 var_is_null = check_nullness && (var_is_set == 0 || *temp == 0);
3953 /* Get the rest of the stuff inside the braces. */
3956 /* Extract the contents of the ${ ... } expansion
3957 according to the Posix.2 rules. */
3958 value = extract_dollar_brace_string (string, &sindex, quoted);
3960 if (string[sindex] == '}')
3963 goto bad_substitution;
3966 value = (char *)NULL;
3970 /* If this is a substring spec, process it and add the result. */
3973 temp1 = parameter_brace_substring (name, temp, value, quoted);
3979 else if (want_patsub)
3981 temp1 = parameter_brace_patsub (name, temp, value, quoted);
3988 /* Do the right thing based on which character ended the variable name. */
3994 report_error ("%s: bad substitution", string ? string : "??");
3998 return &expand_param_error;
4002 if (var_is_set == 0 && unbound_vars_is_error)
4004 report_error ("%s: unbound variable", name);
4008 last_command_exit_value = EXECUTION_FAILURE;
4009 return &expand_param_error;
4013 case '#': /* ${param#[#]pattern} */
4014 case '%': /* ${param%[%]pattern} */
4015 if (value == 0 || *value == '\0' || temp == 0 || *temp == '\0')
4020 if ((name[0] == '@' || name[0] == '*') && name[1] == '\0')
4021 temp1 = parameter_list_remove_pattern (value, name[0], c, quoted);
4022 #if defined (ARRAY_VARS)
4023 else if (valid_array_reference (name))
4024 temp1 = array_remove_pattern (value, name, temp, c, quoted);
4027 temp1 = parameter_brace_remove_pattern (value, temp, c, quoted);
4037 if (var_is_set && var_is_null == 0)
4039 /* We don't want the value of the named variable for
4040 anything, just the value of the right hand side. */
4046 temp = parameter_brace_expand_rhs (name, value, c,
4049 contains_dollar_at);
4053 temp = (char *)NULL;
4059 /* Otherwise do nothing; just use the value in TEMP. */
4061 else /* VAR not set or VAR is NULL. */
4064 temp = (char *)NULL;
4065 if (c == '=' && var_is_special)
4067 report_error ("$%s: cannot assign in this way", name);
4070 return &expand_param_error;
4074 parameter_brace_expand_error (name, value);
4075 return (interactive ? &expand_param_error : &expand_param_fatal);
4078 temp = parameter_brace_expand_rhs (name, value, c, quoted,
4080 contains_dollar_at);
4089 /* Make a word list which is the parameter and variable expansion,
4090 command substitution, arithmetic substitution, and quote removed
4091 expansion of WORD. Return a pointer to a WORD_LIST which is the
4092 result of the expansion. If WORD contains a null word, the word
4093 list returned is also null.
4095 QUOTED contains flag values defined in shell.h.
4097 CONTAINS_DOLLAR_AT and EXPANDED_SOMETHING are return values; when non-null
4098 they point to an integer value which receives information about expansion.
4099 CONTAINS_DOLLAR_AT gets non-zero if WORD contained "$@", else zero.
4100 EXPANDED_SOMETHING get non-zero if WORD contained any parameter expansions,
4103 This only does word splitting in the case of $@ expansion. In that
4104 case, we split on ' '. */
4106 /* Values for the local variable quoted_state. */
4108 #define PARTIALLY_QUOTED 1
4109 #define WHOLLY_QUOTED 2
4112 expand_word_internal (word, quoted, contains_dollar_at, expanded_something)
4115 int *contains_dollar_at;
4116 int *expanded_something;
4122 /* The intermediate string that we build while expanding. */
4125 /* The current size of the above object. */
4128 /* Index into ISTRING. */
4131 /* Temporary string storage. */
4134 /* The text of WORD. */
4135 register char *string;
4137 /* The index into STRING. */
4140 /* This gets 1 if we see a $@ while quoted. */
4141 int quoted_dollar_at;
4143 /* One of UNQUOTED, PARTIALLY_QUOTED, or WHOLLY_QUOTED, depending on
4144 whether WORD contains no quoting characters, a partially quoted
4145 string (e.g., "xx"ab), or is fully quoted (e.g., "xxab"). */
4148 int had_quoted_null;
4150 register int c; /* Current character. */
4151 int number; /* Temporary number value. */
4152 int t_index; /* For calls to string_extract_xxx. */
4154 istring = xmalloc (istring_size = DEFAULT_ARRAY_SIZE);
4155 istring[istring_index = 0] = '\0';
4157 quoted_dollar_at = had_quoted_null = 0;
4158 quoted_state = UNQUOTED;
4160 string = word->word;
4162 goto finished_with_string;
4164 if (contains_dollar_at)
4165 *contains_dollar_at = 0;
4167 /* Begin the expansion. */
4173 /* Case on toplevel character. */
4177 goto finished_with_string;
4182 temp[1] = c = string[++sindex];
4190 #if defined (PROCESS_SUBSTITUTION)
4191 /* Process substitution. */
4195 if (string[++sindex] != '(' || (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || posixly_correct)
4201 t_index = sindex + 1; /* skip past both '<' and '(' */
4203 temp1 = extract_process_subst (string, (c == '<') ? "<(" : ">(", &t_index);
4206 /* If the process substitution specification is `<()', we want to
4207 open the pipe for writing in the child and produce output; if
4208 it is `>()', we want to open the pipe for reading in the child
4209 and consume input. */
4210 temp = temp1 ? process_substitute (temp1, (c == '>')) : (char *)0;
4214 goto dollar_add_string;
4216 #endif /* PROCESS_SUBSTITUTION */
4218 /* See about breaking this into a separate function:
4220 param_expand (string, sindex, quoted, expanded_something,
4221 contains_dollar_at, quoted_dollar_at)
4223 int *sindex, quoted, *expanded_something, *contains_dollar_at;
4224 int *quoted_dollar_at;
4228 if (expanded_something)
4229 *expanded_something = 1;
4231 c = string[++sindex];
4233 /* Do simple cases first. Switch on what follows '$'. */
4247 temp1 = dollar_vars[digit_value (c)];
4248 if (unbound_vars_is_error && temp1 == (char *)NULL)
4250 report_error ("$%c: unbound variable", c);
4253 last_command_exit_value = EXECUTION_FAILURE;
4254 return (&expand_word_error);
4256 temp = temp1 ? savestring (temp1) : (char *)NULL;
4257 goto dollar_add_string;
4259 /* $$ -- pid of the invoking shell. */
4261 number = dollar_dollar_pid;
4264 temp = itos (number);
4266 if (string[sindex]) sindex++;
4268 /* Add TEMP to ISTRING. */
4272 istring = sub_append_string
4273 (temp, istring, &istring_index, &istring_size);
4279 /* $# -- number of positional parameters. */
4281 number = number_of_args ();
4284 /* $? -- return value of the last synchronous command. */
4286 number = last_command_exit_value;
4289 /* $- -- flags supplied to the shell on invocation or
4292 temp = which_set_flags ();
4293 goto dollar_add_string;
4295 /* $! -- Pid of the last asynchronous command. */
4297 number = (int)last_asynchronous_pid;
4299 /* If no asynchronous pids have been created, expand
4301 if (number == (int)NO_PID)
4305 if (expanded_something)
4306 *expanded_something = 0;
4311 /* The only difference between this and $@ is when the
4313 case '*': /* `$*' */
4314 temp = string_rest_of_args (quoted);
4316 /* If there are no command-line arguments, this should just
4317 disappear if there are other characters in the expansion,
4318 even if it's quoted. */
4319 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && temp && *temp == '\0')
4322 temp = (char *)NULL;
4324 /* In the case of a quoted string, quote the entire arg-list.
4325 "$1 $2 $3". Otherwise quote the special escape characters. */
4329 temp = (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
4330 ? quote_string (temp)
4331 : quote_escapes (temp);
4334 goto dollar_add_string;
4336 /* When we have "$@" what we want is "$1" "$2" "$3" ... This
4337 means that we have to turn quoting off after we split into
4338 the individually quoted arguments so that the final split
4339 on the first character of $IFS is still done. */
4340 case '@': /* `$@' */
4341 list = list_rest_of_args ();
4343 /* We want to flag the fact that we saw this. We can't turn
4344 off quoting entirely, because other characters in the
4345 string might need it (consider "\"$@\""), but we need some
4346 way to signal that the final split on the first character
4347 of $IFS should be done, even though QUOTED is 1. */
4348 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
4349 quoted_dollar_at = 1;
4350 if (contains_dollar_at)
4351 *contains_dollar_at = 1;
4352 temp = string_list (((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && list) ? quote_list (list) : list);
4353 /* If the expansion is not quoted, protect any special escape
4354 characters in the expansion by quoting them. */
4355 if (temp && quoted == 0)
4358 temp = quote_escapes (temp);
4361 dispose_words (list);
4362 goto dollar_add_string;
4365 temp = parameter_brace_expand (string, &sindex, quoted,
4367 contains_dollar_at);
4368 if (temp == &expand_param_error || temp == &expand_param_fatal)
4372 return (temp == &expand_param_error) ? &expand_word_error
4373 : &expand_word_fatal;
4376 /* quoted nulls should be removed if there is anything else
4378 /* Note that we saw the quoted null so we can add one back at
4379 the end of this function if there are no other characters
4380 in the string, discard TEMP, and go on. */
4381 if (temp && QUOTED_NULL (temp))
4383 had_quoted_null = 1;
4391 /* Do command or arithmetic substitution. */
4393 /* We have to extract the contents of this paren substitution. */
4394 t_index = sindex + 1;
4395 temp = extract_command_subst (string, &t_index);
4398 /* For Posix.2-style `$(( ))' arithmetic substitution,
4399 extract the expression and pass it to the evaluator. */
4400 if (temp && *temp == '(')
4403 t_index = strlen (temp1) - 1;
4405 if (temp1[t_index] != ')')
4407 report_error ("%s: bad arithmetic substitution", temp);
4411 return &expand_word_error;
4414 /* Cut off ending `)' */
4415 temp1[t_index] = '\0';
4417 /* Expand variables found inside the expression. */
4418 temp1 = maybe_expand_string (temp1, 1, expand_string);
4420 /* No error messages. */
4421 this_command_name = (char *)NULL;
4422 number = evalexp (temp1);
4429 temp1 = command_substitute (temp, quoted);
4432 goto dollar_add_string;
4434 /* Do straight arithmetic substitution. */
4436 /* We have to extract the contents of this
4437 arithmetic substitution. */
4438 t_index = sindex + 1;
4439 temp = extract_arithmetic_subst (string, &t_index);
4442 /* Do initial variable expansion. */
4443 temp1 = maybe_expand_string (temp, 1, expand_string);
4445 /* No error messages. */
4446 this_command_name = (char *)NULL;
4447 number = evalexp (temp1);
4454 /* Find the variable in VARIABLE_LIST. */
4455 temp = (char *)NULL;
4457 for (t_index = sindex;
4458 (c = string[sindex]) && legal_variable_char (c);
4460 temp1 = substring (string, t_index, sindex);
4462 /* If this isn't a variable name, then just output the `$'. */
4463 if (temp1 == 0 || *temp1 == '\0')
4469 if (expanded_something)
4470 *expanded_something = 0;
4474 /* If the variable exists, return its value cell. */
4475 var = find_variable (temp1);
4477 if (var && invisible_p (var) == 0 && value_cell (var))
4479 #if defined (ARRAY_VARS)
4482 temp = array_reference (array_cell (var), 0);
4484 temp = quote_escapes (temp);
4488 temp = quote_escapes (value_cell (var));
4493 temp = (char *)NULL;
4495 if (unbound_vars_is_error)
4496 report_error ("%s: unbound variable", temp1);
4505 last_command_exit_value = EXECUTION_FAILURE;
4507 return &expand_word_error;
4509 break; /* End case '$': */
4511 case '`': /* Backquoted command substitution. */
4515 if (expanded_something)
4516 *expanded_something = 1;
4518 temp = string_extract (string, &sindex, "`", 0);
4519 de_backslash (temp);
4520 temp1 = command_substitute (temp, quoted);
4523 goto dollar_add_string;
4527 if (string[sindex + 1] == '\n')
4533 c = string[++sindex];
4535 if (quoted & Q_HERE_DOCUMENT)
4536 temp1 = slashify_in_here_document;
4537 else if (quoted & Q_DOUBLE_QUOTES)
4538 temp1 = slashify_in_quotes;
4542 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && member (c, temp1) == 0)
4545 temp[0] = '\\'; temp[1] = c; temp[2] = '\0';
4548 /* This character is quoted, so add it in quoted mode. */
4549 temp = make_quoted_char (c);
4556 if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT|Q_NOQUOTE))
4560 temp = string_extract_double_quoted (string, &sindex, 0);
4562 /* If the quotes surrounded the entire string, then the
4563 whole word was quoted. */
4564 quoted_state = (t_index == 1 && string[sindex] == '\0')
4572 tword = make_word (temp); /* XXX */
4574 temp = (char *)NULL;
4576 list = expand_word_internal (tword, Q_DOUBLE_QUOTES, &dollar_at_flag, (int *)NULL);
4578 if (list == &expand_word_error || list == &expand_word_fatal)
4582 /* expand_word_internal has already freed temp_word->word
4583 for us because of the way it prints error messages. */
4584 tword->word = (char *)NULL;
4585 dispose_word (tword);
4589 dispose_word (tword);
4591 /* "$@" (a double-quoted dollar-at) expands into nothing,
4592 not even a NULL word, when there are no positional
4594 if (list == 0 && dollar_at_flag)
4600 /* If we get "$@", we know we have expanded something, so we
4601 need to remember it for the final split on $IFS. This is
4602 a special case; it's the only case where a quoted string
4603 can expand into more than one word. It's going to come back
4604 from the above call to expand_word_internal as a list with
4605 a single word, in which all characters are quoted and
4606 separated by blanks. What we want to do is to turn it back
4607 into a list for the next piece of code. */
4609 dequote_list (list);
4614 if (contains_dollar_at)
4615 *contains_dollar_at = 1;
4616 if (expanded_something)
4617 *expanded_something = 1;
4622 /* What we have is "". This is a minor optimization. */
4624 list = (WORD_LIST *)NULL;
4627 /* The code above *might* return a list (consider the case of "$@",
4628 where it returns "$1", "$2", etc.). We can't throw away the
4629 rest of the list, and we have to make sure each word gets added
4630 as quoted. We test on tresult->next: if it is non-NULL, we
4631 quote the whole list, save it to a string with string_list, and
4632 add that string. We don't need to quote the results of this
4633 (and it would be wrong, since that would quote the separators
4634 as well), so we go directly to add_string. */
4639 temp = string_list (quote_list (list));
4640 dispose_words (list);
4645 temp = savestring (list->word->word);
4646 dispose_words (list);
4650 temp = (char *)NULL;
4652 /* We do not want to add quoted nulls to strings that are only
4653 partially quoted; we can throw them away. */
4654 if (temp == 0 && quoted_state == PARTIALLY_QUOTED)
4665 temp = quote_string (temp);
4679 if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT|Q_NOQUOTE))
4683 temp = string_extract_single_quoted (string, &sindex);
4685 /* If the entire STRING was surrounded by single quotes,
4686 then the string is wholly quoted. */
4687 quoted_state = (t_index == 1 && string[sindex] == '\0')
4691 /* If all we had was '', it is a null expansion. */
4695 temp = (char *)NULL;
4698 remove_quoted_escapes (temp);
4700 /* We do not want to add quoted nulls to strings that are only
4701 partially quoted; such nulls are discarded. */
4702 if (temp == 0 && (quoted_state == PARTIALLY_QUOTED))
4705 goto add_quoted_string;
4709 /* This is the fix for " $@ " */
4710 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
4712 temp = make_quoted_char (c);
4713 goto dollar_add_string;
4717 RESIZE_MALLOCED_BUFFER (istring, istring_index, 1, istring_size,
4718 DEFAULT_ARRAY_SIZE);
4719 istring[istring_index++] = c;
4720 istring[istring_index] = '\0';
4722 /* Next character. */
4727 finished_with_string:
4728 /* OK, we're ready to return. If we have a quoted string, and
4729 quoted_dollar_at is not set, we do no splitting at all; otherwise
4730 we split on ' '. The routines that call this will handle what to
4731 do if nothing has been expanded. */
4733 /* Partially and wholly quoted strings which expand to the empty
4734 string are retained as an empty arguments. Unquoted strings
4735 which expand to the empty string are discarded. The single
4736 exception is the case of expanding "$@" when there are no
4737 positional parameters. In that case, we discard the expansion. */
4739 /* Because of how the code that handles "" and '' in partially
4740 quoted strings works, we need to make ISTRING into a QUOTED_NULL
4741 if we saw quoting characters, but the expansion was empty.
4742 "" and '' are tossed away before we get to this point when
4743 processing partially quoted strings. This makes "" and $xxx""
4744 equivalent when xxx is unset. We also look to see whether we
4745 saw a quoted null from a ${} expansion and add one back if we
4748 /* If we expand to nothing and there were no single or double quotes
4749 in the word, we throw it away. Otherwise, we return a NULL word.
4750 The single exception is for $@ surrounded by double quotes when
4751 there are no positional parameters. In that case, we also throw
4754 if (*istring == '\0')
4756 if (quoted_dollar_at == 0 && (had_quoted_null || quoted_state == PARTIALLY_QUOTED))
4758 istring[0] = CTLNUL;
4760 tword = make_bare_word (istring);
4761 list = make_word_list (tword, (WORD_LIST *)NULL);
4762 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
4763 tword->flags |= W_QUOTED;
4765 /* According to sh, ksh, and Posix.2, if a word expands into nothing
4766 and a double-quoted "$@" appears anywhere in it, then the entire
4768 else if (quoted_state == UNQUOTED || quoted_dollar_at)
4769 list = (WORD_LIST *)NULL;
4773 tword = make_bare_word (istring);
4774 list = make_word_list (tword, (WORD_LIST *)NULL);
4775 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
4776 tword->flags |= W_QUOTED;
4780 else if (word->flags & W_NOSPLIT)
4782 tword = make_bare_word (istring);
4783 list = make_word_list (tword, (WORD_LIST *)NULL);
4784 if (word->flags & W_ASSIGNMENT)
4785 tword->flags |= W_ASSIGNMENT; /* XXX */
4786 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
4787 tword->flags |= W_QUOTED;
4793 if (quoted_dollar_at)
4795 var = find_variable ("IFS");
4796 ifs_chars = var ? value_cell (var) : " \t\n";
4799 ifs_chars = (char *)NULL;
4801 /* According to Posix.2, "$@" expands to a single word if
4802 IFS="" and the positional parameters are not empty. */
4803 if (quoted_dollar_at && ifs_chars && *ifs_chars)
4805 list = list_string (istring, " ", 1);
4809 tword = make_bare_word (istring);
4810 list = make_word_list (tword, (WORD_LIST *)NULL);
4811 if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) || (quoted_state == WHOLLY_QUOTED))
4812 tword->flags |= W_QUOTED;
4813 if (word->flags & W_ASSIGNMENT)
4814 tword->flags |= W_ASSIGNMENT;
4822 /* **************************************************************** */
4824 /* Functions for Quote Removal */
4826 /* **************************************************************** */
4828 /* Perform quote removal on STRING. If QUOTED > 0, assume we are obeying the
4829 backslash quoting rules for within double quotes. */
4831 string_quote_removal (string, quoted)
4835 char *r, *result_string, *temp;
4836 int sindex, tindex, c, dquote;
4838 /* The result can be no longer than the original string. */
4839 r = result_string = xmalloc (strlen (string) + 1);
4841 for (dquote = sindex = 0; c = string[sindex];)
4846 c = string[++sindex];
4847 if (((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || dquote) && member (c, slashify_in_quotes) == 0)
4857 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || dquote)
4863 tindex = sindex + 1;
4864 temp = string_extract_single_quoted (string, &tindex);
4875 dquote = 1 - dquote;
4881 return (result_string);
4886 /* Perform quote removal on word WORD. This allocates and returns a new
4889 word_quote_removal (word, quoted)
4896 t = string_quote_removal (word->word, quoted);
4897 w = make_bare_word (t);
4901 /* Perform quote removal on all words in LIST. If QUOTED is non-zero,
4902 the members of the list are treated as if they are surrounded by
4903 double quotes. Return a new list, or NULL if LIST is NULL. */
4905 word_list_quote_removal (list, quoted)
4909 WORD_LIST *result, *t, *tresult;
4911 for (t = list, result = (WORD_LIST *)NULL; t; t = t->next)
4913 tresult = (WORD_LIST *)xmalloc (sizeof (WORD_LIST));
4914 tresult->word = word_quote_removal (t->word, quoted);
4915 tresult->next = (WORD_LIST *)NULL;
4916 result = (WORD_LIST *) list_append (result, tresult);
4922 /* Return 1 if CHARACTER appears in an unquoted portion of
4923 STRING. Return 0 otherwise. */
4925 unquoted_member (character, string)
4931 for (sindex = 0; c = string[sindex]; )
4949 sindex = skip_single_quoted (string, ++sindex);
4953 sindex = skip_double_quoted (string, ++sindex);
4960 /* Return 1 if SUBSTR appears in an unquoted portion of STRING. */
4962 unquoted_substring (substr, string)
4963 char *substr, *string;
4965 int sindex, c, sublen;
4967 if (substr == 0 || *substr == '\0')
4970 sublen = strlen (substr);
4971 for (sindex = 0; c = string[sindex]; )
4973 if (STREQN (string + sindex, substr, sublen))
4986 sindex = skip_single_quoted (string, ++sindex);
4990 sindex = skip_double_quoted (string, ++sindex);
5001 /*******************************************
5003 * Functions to perform word splitting *
5005 *******************************************/
5007 /* This splits a single word into a WORD LIST on $IFS, but only if the word
5008 is not quoted. list_string () performs quote removal for us, even if we
5009 don't do any splitting. */
5020 ifs = find_variable ("IFS");
5021 /* If IFS is unset, it defaults to " \t\n". */
5022 ifs_chars = ifs ? value_cell (ifs) : " \t\n";
5024 if ((w->flags & W_QUOTED) || !ifs_chars)
5027 result = list_string (w->word, ifs_chars, w->flags & W_QUOTED);
5030 result = (WORD_LIST *)NULL;
5035 /* Perform word splitting on LIST and return the RESULT. It is possible
5036 to return (WORD_LIST *)NULL. */
5038 word_list_split (list)
5041 WORD_LIST *result, *t, *tresult;
5043 for (t = list, result = (WORD_LIST *)NULL; t; t = t->next)
5045 tresult = word_split (t->word);
5046 result = (WORD_LIST *) list_append (result, tresult);
5051 /**************************************************
5053 * Functions to expand an entire WORD_LIST *
5055 **************************************************/
5057 static WORD_LIST *varlist = (WORD_LIST *)NULL;
5059 /* Separate out any initial variable assignments from TLIST. If set -k has
5060 been executed, remove all assignment statements from TLIST. Initial
5061 variable assignments and other environment assignments are placed
5064 separate_out_assignments (tlist)
5067 register WORD_LIST *vp, *lp;
5070 return ((WORD_LIST *)NULL);
5072 varlist = (WORD_LIST *)NULL;
5075 /* Separate out variable assignments at the start of the command.
5076 Loop invariant: vp->next == lp
5078 lp = list of words left after assignment statements skipped
5079 tlist = original list of words
5081 while (lp && (lp->word->flags & W_ASSIGNMENT))
5087 /* If lp != tlist, we have some initial assignment statements. */
5088 /* We make VARLIST point to the list of assignment words and
5089 TLIST point to the remaining words. */
5093 /* ASSERT(vp->next == lp); */
5094 vp->next = (WORD_LIST *)NULL; /* terminate variable list */
5095 tlist = lp; /* remainder of word list */
5098 /* vp == end of variable list */
5099 /* tlist == remainder of original word list without variable assignments */
5101 /* All the words in tlist were assignment statements */
5102 return ((WORD_LIST *)NULL);
5104 /* ASSERT(tlist != NULL); */
5105 /* ASSERT((tlist->word->flags & W_ASSIGNMENT) == 0); */
5107 /* If the -k option is in effect, we need to go through the remaining
5108 words, separate out the assignment words, and place them on VARLIST. */
5109 if (place_keywords_in_env)
5111 WORD_LIST *tp; /* tp == running pointer into tlist */
5116 /* Loop Invariant: tp->next == lp */
5117 /* Loop postcondition: tlist == word list without assignment statements */
5120 if (lp->word->flags & W_ASSIGNMENT)
5122 /* Found an assignment statement, add this word to end of
5132 /* Remove the word pointed to by LP from TLIST. */
5133 tp->next = lp->next;
5134 /* ASSERT(vp == lp); */
5135 lp->next = (WORD_LIST *)NULL;
5148 /* Take the list of words in LIST and do the various substitutions. Return
5149 a new list of words which is the expanded list, and without things like
5150 variable assignments. */
5156 return (expand_word_list_internal (list, 1));
5159 /* Same as expand_words (), but doesn't hack variable or environment
5162 expand_words_no_vars (list)
5165 return (expand_word_list_internal (list, 0));
5168 /* The workhorse for expand_words () and expand_words_no_vars ().
5169 First arg is LIST, a WORD_LIST of words.
5170 Second arg DO_VARS is non-zero if you want to do environment and
5171 variable assignments, else zero.
5173 This does all of the substitutions: brace expansion, tilde expansion,
5174 parameter expansion, command substitution, arithmetic expansion,
5175 process substitution, word splitting, and pathname expansion. Words
5176 with the W_QUOTED or W_NOSPLIT bits set, or for which no expansion
5177 is done, do not undergo word splitting. Words with the W_ASSIGNMENT
5178 bit set do not undergo pathname expansion. */
5180 expand_word_list_internal (list, do_vars)
5184 WORD_LIST *tlist, *new_list, *next, *temp_list, *orig_list, *disposables;
5189 return ((WORD_LIST *)NULL);
5191 tlist = copy_word_list (list);
5195 tlist = separate_out_assignments (tlist);
5200 /* All the words were variable assignments, so they are placed
5201 into the shell's environment. */
5202 for (new_list = varlist; new_list; new_list = new_list->next)
5204 this_command_name = (char *)NULL; /* no arithmetic errors */
5205 tint = do_assignment (new_list->word->word);
5206 /* Variable assignment errors in non-interactive shells
5207 running in Posix.2 mode cause the shell to exit. */
5208 if (tint == 0 && interactive_shell == 0 && posixly_correct)
5210 last_command_exit_value = EXECUTION_FAILURE;
5211 jump_to_top_level (FORCE_EOF);
5214 dispose_words (varlist);
5215 varlist = (WORD_LIST *)NULL;
5217 return ((WORD_LIST *)NULL);
5221 /* Begin expanding the words that remain. The expansions take place on
5222 things that aren't really variable assignments. */
5224 #if defined (BRACE_EXPANSION)
5225 /* Do brace expansion on this word if there are any brace characters
5227 if (brace_expansion && tlist)
5229 register char **expansions;
5233 for (braces = disposables = (WORD_LIST *)NULL; tlist; tlist = next)
5237 /* Only do brace expansion if the word has a brace character. If
5238 not, just add the word list element to BRACES and continue. In
5239 the common case, at least when running shell scripts, this will
5240 degenerate to a bunch of calls to `strchr', and then what is
5241 basically a reversal of TLIST into BRACES, which is corrected
5242 by a call to reverse_list () on BRACES when the end of TLIST
5244 if (strchr (tlist->word->word, '{'))
5246 expansions = brace_expand (tlist->word->word);
5248 for (eindex = 0; temp_string = expansions[eindex]; eindex++)
5250 braces = make_word_list (make_word (temp_string), braces);
5251 free (expansions[eindex]);
5255 /* Add TLIST to the list of words to be freed after brace
5256 expansion has been performed. */
5257 tlist->next = disposables;
5258 disposables = tlist;
5262 tlist->next = braces;
5267 dispose_words (disposables);
5268 tlist = REVERSE_LIST (braces, WORD_LIST *);
5270 #endif /* BRACE_EXPANSION */
5272 /* We do tilde expansion all the time. This is what 1003.2 says. */
5273 for (orig_list = tlist, new_list = (WORD_LIST *)NULL; tlist; tlist = next)
5275 WORD_LIST *expanded;
5276 int expanded_something, has_dollar_at;
5278 temp_string = tlist->word->word;
5282 /* Posix.2 section 3.6.1 says that tildes following `=' in words
5283 which are not assignment statements are not expanded. We do
5284 this only if POSIXLY_CORRECT is enabled. Essentially, we do
5285 tilde expansion on unquoted assignment statements (flags include
5286 W_ASSIGNMENT but not W_QUOTED). */
5287 if (temp_string[0] == '~' ||
5288 (((tlist->word->flags & (W_ASSIGNMENT|W_QUOTED)) == W_ASSIGNMENT) &&
5289 posixly_correct == 0 &&
5290 strchr (temp_string, '~') &&
5291 (unquoted_substring ("=~", temp_string) || unquoted_substring (":~", temp_string))))
5293 tlist->word->word = bash_tilde_expand (temp_string);
5297 expanded_something = 0;
5298 expanded = expand_word_internal
5299 (tlist->word, 0, &has_dollar_at, &expanded_something);
5301 if (expanded == &expand_word_error || expanded == &expand_word_fatal)
5303 /* By convention, each time this error is returned,
5304 tlist->word->word has already been freed. */
5305 tlist->word->word = (char *)NULL;
5307 /* Dispose our copy of the original list. */
5308 dispose_words (orig_list);
5309 /* Dispose the new list we're building. */
5310 dispose_words (new_list);
5312 if (expanded == &expand_word_error)
5313 jump_to_top_level (DISCARD);
5315 jump_to_top_level (FORCE_EOF);
5318 /* Don't split words marked W_NOSPLIT. */
5319 if (expanded_something && (tlist->word->flags & W_NOSPLIT) == 0)
5321 temp_list = word_list_split (expanded);
5322 dispose_words (expanded);
5326 /* If no parameter expansion, command substitution, process
5327 substitution, or arithmetic substitution took place, then
5328 do not do word splitting. We still have to remove quoted
5329 null characters from the result. */
5330 word_list_remove_quoted_nulls (expanded);
5331 temp_list = expanded;
5334 /* In the most common cases, t will be a list containing only one
5335 element, so the call to reverse_list would be wasted. */
5336 expanded = REVERSE_LIST (temp_list, WORD_LIST *);
5337 new_list = (WORD_LIST *)list_append (expanded, new_list);
5340 new_list = REVERSE_LIST (new_list, WORD_LIST *);
5342 dispose_words (orig_list);
5344 /* Okay, we're almost done. Now let's just do some filename
5349 register int glob_index;
5350 WORD_LIST *glob_list;
5353 orig_list = disposables = (WORD_LIST *)NULL;
5356 /* orig_list == output list, despite the name. */
5357 if (disallow_filename_globbing == 0)
5359 glob_array = (char **)NULL;
5362 /* For each word, either globbing is attempted or the word is
5363 added to orig_list. If globbing succeeds, the results are
5364 added to orig_list and the word (tlist) is added to the list
5365 of disposable words. If globbing fails and failed glob
5366 expansions are left unchanged (the shell default), the
5367 original word is added to orig_list. If globbing fails and
5368 failed glob expansions are removed, the original word is
5369 added to the list of disposable words. orig_list ends up
5370 in reverse order and requires a call to reverse_list to
5371 be set right. After all words are examined, the disposable
5375 /* If the word isn't quoted and there is an unquoted pattern
5376 matching character in the word, then glob it. */
5377 if ((tlist->word->flags & (W_QUOTED|W_ASSIGNMENT)) == 0 &&
5378 unquoted_glob_pattern_p (tlist->word->word))
5380 glob_array = shell_glob_filename (tlist->word->word);
5382 /* Handle error cases.
5383 I don't think we should report errors like "No such file
5384 or directory". However, I would like to report errors
5385 like "Read failed". */
5387 if (GLOB_FAILED (glob_array))
5389 glob_array = (char **) xmalloc (sizeof (char *));
5390 glob_array[0] = (char *)NULL;
5393 /* Dequote the current word in case we have to use it. */
5394 if (glob_array[0] == NULL)
5396 temp_string = dequote_string (tlist->word->word);
5397 free (tlist->word->word);
5398 tlist->word->word = temp_string;
5401 /* Make the array into a word list. */
5402 glob_list = (WORD_LIST *)NULL;
5403 for (glob_index = 0; glob_array[glob_index]; glob_index++)
5405 tword = make_bare_word (glob_array[glob_index]);
5406 tword->flags |= W_GLOBEXP; /* XXX */
5407 glob_list = make_word_list (tword, glob_list);
5412 orig_list = (WORD_LIST *)list_append (glob_list, orig_list);
5413 tlist->next = disposables;
5414 disposables = tlist;
5416 else if (allow_null_glob_expansion == 0)
5418 /* Failed glob expressions are left unchanged. */
5419 tlist->next = orig_list;
5424 /* Failed glob expressions are removed. */
5425 tlist->next = disposables;
5426 disposables = tlist;
5431 /* Dequote the string. */
5432 temp_string = dequote_string (tlist->word->word);
5433 free (tlist->word->word);
5434 tlist->word->word = temp_string;
5435 tlist->next = orig_list;
5439 free_array (glob_array);
5440 glob_array = (char **)NULL;
5446 dispose_words (disposables);
5448 new_list = REVERSE_LIST (orig_list, WORD_LIST *);
5452 /* Dequote the words, because we're not performing globbing. */
5453 for (temp_list = new_list; temp_list; temp_list = temp_list->next)
5455 temp_string = dequote_string (temp_list->word->word);
5456 free (temp_list->word->word);
5457 temp_list->word->word = temp_string;
5464 Function *assign_func;
5466 /* If the remainder of the words expand to nothing, Posix.2 requires
5467 that the variable and environment assignments affect the shell's
5469 assign_func = new_list ? assign_in_env : do_assignment;
5471 for (temp_list = varlist; temp_list; temp_list = temp_list->next)
5473 this_command_name = (char *)NULL;
5474 tint = (*assign_func) (temp_list->word->word);
5475 /* Variable assignment errors in non-interactive shells running
5476 in Posix.2 mode cause the shell to exit. */
5477 if (tint == 0 && assign_func == do_assignment &&
5478 interactive_shell == 0 && posixly_correct)
5480 last_command_exit_value = EXECUTION_FAILURE;
5481 jump_to_top_level (FORCE_EOF);
5485 dispose_words (varlist);
5486 varlist = (WORD_LIST *)NULL;
5489 tint = list_length (new_list) + 1;
5490 RESIZE_MALLOCED_BUFFER (glob_argv_flags, 0, tint, glob_argv_flags_size, 16);
5491 for (tint = 0, tlist = new_list; tlist; tlist = tlist->next)
5492 glob_argv_flags[tint++] = (tlist->word->flags & W_GLOBEXP) ? '1' : '0';
5493 glob_argv_flags[tint] = '\0';
5498 /*************************************************
5500 * Functions to manage special variables *
5502 *************************************************/
5504 /* An alist of name.function for each special variable. Most of the
5505 functions don't do much, and in fact, this would be faster with a
5506 switch statement, but by the end of this file, I am sick of switch
5509 #define SET_INT_VAR(name, intvar) intvar = find_variable (name) != 0
5511 struct name_and_function {
5513 VFunction *function;
5514 } special_vars[] = {
5515 { "PATH", sv_path },
5516 { "MAIL", sv_mail },
5517 { "MAILPATH", sv_mail },
5518 { "MAILCHECK", sv_mail },
5520 { "POSIXLY_CORRECT", sv_strict_posix },
5521 { "GLOBIGNORE", sv_globignore },
5523 /* Variables which only do something special when READLINE is defined. */
5524 #if defined (READLINE)
5525 { "TERM", sv_terminal },
5526 { "TERMCAP", sv_terminal },
5527 { "TERMINFO", sv_terminal },
5528 { "HOSTFILE", sv_hostfile },
5529 #endif /* READLINE */
5531 /* Variables which only do something special when HISTORY is defined. */
5532 #if defined (HISTORY)
5533 { "HISTIGNORE", sv_histignore },
5534 { "HISTSIZE", sv_histsize },
5535 { "HISTFILESIZE", sv_histsize },
5536 { "HISTCONTROL", sv_history_control },
5537 # if defined (BANG_HISTORY)
5538 { "histchars", sv_histchars },
5539 # endif /* BANG_HISTORY */
5540 #endif /* HISTORY */
5542 { "IGNOREEOF", sv_ignoreeof },
5543 { "ignoreeof", sv_ignoreeof },
5545 { "OPTIND", sv_optind },
5546 { "OPTERR", sv_opterr },
5548 { "TEXTDOMAIN", sv_locale },
5549 { "TEXTDOMAINDIR", sv_locale },
5550 { "LC_ALL", sv_locale },
5551 { "LC_COLLATE", sv_locale },
5552 { "LC_CTYPE", sv_locale },
5553 { "LC_MESSAGES", sv_locale },
5554 { "LANG", sv_locale },
5556 #if defined (HAVE_TZSET) && defined (PROMPT_STRING_DECODE)
5560 { (char *)0, (VFunction *)0 }
5563 /* The variable in NAME has just had its state changed. Check to see if it
5564 is one of the special ones where something special happens. */
5566 stupidly_hack_special_variables (name)
5571 for (i = 0; special_vars[i].name; i++)
5573 if (STREQ (special_vars[i].name, name))
5575 (*(special_vars[i].function)) (name);
5581 /* What to do just after the PATH variable has changed. */
5587 flush_hashed_filenames ();
5590 /* What to do just after one of the MAILxxxx variables has changed. NAME
5591 is the name of the variable. This is called with NAME set to one of
5592 MAIL, MAILCHECK, or MAILPATH. */
5597 /* If the time interval for checking the files has changed, then
5598 reset the mail timer. Otherwise, one of the pathname vars
5599 to the users mailbox has changed, so rebuild the array of
5601 if (name[4] == 'C') /* if (strcmp (name, "MAILCHECK") == 0) */
5602 reset_mail_timer ();
5606 remember_mail_dates ();
5610 /* What to do when GLOBIGNORE changes. */
5612 sv_globignore (name)
5615 setup_glob_ignore (name);
5618 #if defined (READLINE)
5619 /* What to do just after one of the TERMxxx variables has changed.
5620 If we are an interactive shell, then try to reset the terminal
5621 information in readline. */
5626 if (interactive_shell && no_line_editing == 0)
5627 rl_reset_terminal (get_string_value ("TERM"));
5634 hostname_list_initialized = 0;
5636 #endif /* READLINE */
5638 #if defined (HISTORY)
5639 /* What to do after the HISTSIZE or HISTFILESIZE variables change.
5640 If there is a value for this HISTSIZE (and it is numeric), then stifle
5641 the history. Otherwise, if there is NO value for this variable,
5642 unstifle the history. If name is HISTFILESIZE, and its value is
5643 numeric, truncate the history file to hold no more than that many
5652 temp = get_string_value (name);
5656 if (legal_number (temp, &num))
5660 stifle_history (num);
5661 num = where_history ();
5662 if (history_lines_this_session > num)
5663 history_lines_this_session = num;
5667 history_truncate_file (get_string_value ("HISTFILE"), (int)num);
5668 if (num <= history_lines_in_file)
5669 history_lines_in_file = num;
5673 else if (name[4] == 'S')
5674 unstifle_history ();
5677 /* What to do after the HISTIGNORE variable changes. */
5679 sv_histignore (name)
5682 setup_history_ignore (name);
5685 /* What to do after the HISTCONTROL variable changes. */
5687 sv_history_control (name)
5692 history_control = 0;
5693 temp = get_string_value (name);
5695 if (temp && *temp && STREQN (temp, "ignore", 6))
5697 if (temp[6] == 's') /* ignorespace */
5698 history_control = 1;
5699 else if (temp[6] == 'd') /* ignoredups */
5700 history_control = 2;
5701 else if (temp[6] == 'b') /* ignoreboth */
5702 history_control = 3;
5706 #if defined (BANG_HISTORY)
5707 /* Setting/unsetting of the history expansion character. */
5714 temp = get_string_value (name);
5717 history_expansion_char = *temp;
5718 if (temp[0] && temp[1])
5720 history_subst_char = temp[1];
5722 history_comment_char = temp[2];
5727 history_expansion_char = '!';
5728 history_subst_char = '^';
5729 history_comment_char = '#';
5732 #endif /* BANG_HISTORY */
5733 #endif /* HISTORY */
5735 #if defined (HAVE_TZSET) && defined (PROMPT_STRING_DECODE)
5744 /* If the variable exists, then the value of it can be the number
5745 of times we actually ignore the EOF. The default is small,
5746 (smaller than csh, anyway). */
5754 eof_encountered = 0;
5756 tmp_var = find_variable (name);
5757 ignoreeof = tmp_var != 0;
5758 temp = tmp_var ? value_cell (tmp_var) : (char *)NULL;
5760 eof_encountered_limit = (*temp && all_digits (temp)) ? atoi (temp) : 10;
5770 tt = get_string_value ("OPTIND");
5775 /* According to POSIX, setting OPTIND=1 resets the internal state
5777 if (s < 0 || s == 1)
5791 tt = get_string_value ("OPTERR");
5792 sh_opterr = (tt && *tt) ? atoi (tt) : 1;
5796 sv_strict_posix (name)
5799 SET_INT_VAR (name, posixly_correct);
5800 posix_initialize (posixly_correct);
5801 #if defined (READLINE)
5802 posix_readline_initialize (posixly_correct);
5803 #endif /* READLINE */
5812 v = get_string_value (name);
5813 if (name[0] == 'L' && name[1] == 'A') /* LANG */
5816 set_locale_var (name, v); /* LC_*, TEXTDOMAIN* */