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 #if !defined (HAVE_RESTARTABLE_SYSCALLS) /* for getc_with_restart */
50 #include "builtins/getopt.h"
51 #include "builtins/common.h"
53 #if defined (READLINE)
54 # include "bashline.h"
55 # include <readline/readline.h>
57 # include <tilde/tilde.h>
61 # include "bashhist.h"
62 # include <readline/history.h>
65 #include <glob/fnmatch.h>
71 /* The size that strings change by. */
72 #define DEFAULT_INITIAL_ARRAY_SIZE 112
73 #define DEFAULT_ARRAY_SIZE 128
79 #define VT_ARRAYMEMBER 3
81 /* Flags for quoted_strchr */
82 #define ST_BACKSL 0x01
83 #define ST_CTLESC 0x02
85 /* How to quote character C. */
86 static char *make_quoted_char ();
88 /* Process ID of the last command executed within command substitution. */
89 pid_t last_command_subst_pid = NO_PID;
91 /* Extern functions and variables from different files. */
92 extern int last_command_exit_value, interactive, interactive_shell;
93 extern int subshell_environment, startup_state;
94 extern int dollar_dollar_pid;
95 extern int posixly_correct;
96 extern int eof_encountered, eof_encountered_limit, ignoreeof;
97 extern char *this_command_name;
98 extern struct fd_bitmap *current_fds_to_close;
99 #if defined (READLINE)
100 extern int no_line_editing;
101 extern int hostname_list_initialized;
104 extern void getopts_reset ();
106 /* Non-zero means to allow unmatched globbed filenames to expand to
108 int allow_null_glob_expansion;
110 /* Variables to keep track of which words in an expanded word list (the
111 output of expand_word_list_internal) are the result of globbing
112 expansions. GLOB_ARGV_FLAGS is used by execute_cmd.c. */
113 char *glob_argv_flags;
114 static int glob_argv_flags_size;
116 static WORD_LIST expand_word_error, expand_word_fatal;
117 static char expand_param_error, expand_param_fatal;
119 static WORD_LIST *expand_string_internal ();
120 static WORD_LIST *expand_word_internal (), *expand_word_list_internal ();
121 static WORD_LIST *expand_string_leave_quoted ();
122 static WORD_LIST *expand_string_for_rhs ();
123 static WORD_LIST *word_list_split ();
124 static WORD_LIST *quote_list (), *dequote_list ();
125 static int unquoted_substring (), unquoted_member ();
126 static int do_assignment_internal ();
127 static char *string_extract_verbatim (), *string_extract ();
128 static char *string_extract_double_quoted (), *string_extract_single_quoted ();
129 static int skip_single_quoted (), skip_double_quoted ();
130 static char *extract_delimited_string ();
131 static char *extract_dollar_brace_string ();
133 /* **************************************************************** */
135 /* Utility Functions */
137 /* **************************************************************** */
139 /* Cons a new string from STRING starting at START and ending at END,
140 not including END. */
142 substring (string, start, end)
147 register char *result;
150 result = xmalloc (len + 1);
151 strncpy (result, string + start, len);
157 quoted_substring (string, start, end)
162 register char *result, *s, *r;
166 /* Move to string[start], skipping quoted characters. */
167 for (s = string, l = 0; *s && l < start; )
179 r = result = xmalloc (2*len + 1); /* save room for quotes */
181 /* Copy LEN characters, including quote characters. */
183 for (l = 0; l < len; s++)
196 /* Find the first occurrence of character C in string S, obeying shell
197 quoting rules. If (FLAGS & ST_BACKSL) is non-zero, backslash-escaped
198 characters are skipped. If (FLAGS & ST_CTLESC) is non-zero, characters
199 escaped with CTLESC are skipped. */
201 quoted_strchr (s, c, flags)
209 if (((flags & ST_BACKSL) && *p == '\\')
210 || ((flags & ST_CTLESC) && *p == CTLESC))
214 return ((char *)NULL);
220 return ((char *)NULL);
225 A string with s[0] == CTLNUL && s[1] == 0 is a quoted null string.
226 The parser passes CTLNUL as CTLESC CTLNUL. */
228 /* The parser passes us CTLESC as CTLESC CTLESC and CTLNUL as CTLESC CTLNUL.
229 This is necessary to make unquoted CTLESC and CTLNUL characters in the
230 data stream pass through properly.
231 Here we remove doubled CTLESC characters inside quoted strings before
232 quoting the entire string, so we do not double the number of CTLESC
235 remove_quoted_escapes (string)
245 t1 = t = xmalloc (strlen (string) + 1);
246 for (docopy = 0, s = string; *s; s++, t1++)
248 if (*s == CTLESC && (s[1] == CTLESC || s[1] == CTLNUL))
262 /* Quote escape characters in string s, but no other characters. This is
263 used to protect CTLESC and CTLNUL in variable values from the rest of
264 the word expansion process after the variable is expanded. */
266 quote_escapes (string)
269 register char *s, *t;
272 result = xmalloc ((strlen (string) * 2) + 1);
273 for (s = string, t = result; *s; )
275 if (*s == CTLESC || *s == CTLNUL)
283 #ifdef INCLUDE_UNUSED
285 dequote_escapes (string)
288 register char *s, *t;
291 result = xmalloc (strlen (string) + 1);
292 for (s = string, t = result; *s; )
294 if (*s == CTLESC && (s[1] == CTLESC || s[1] == CTLNUL))
307 /* Extract a substring from STRING, starting at SINDEX and ending with
308 one of the characters in CHARLIST. Don't make the ending character
309 part of the string. Leave SINDEX pointing at the ending character.
310 Understand about backslashes in the string. If VARNAME is non-zero,
311 and array variables have been compiled into the shell, everything
312 between a `[' and a corresponding `]' is skipped over. */
314 string_extract (string, sindex, charlist, varname)
315 char *string, *charlist;
316 int *sindex, varname;
321 for (i = *sindex; c = string[i]; i++)
328 #if defined (ARRAY_VARS)
329 else if (varname && c == '[')
332 /* If this is an array subscript, skip over it and continue. */
333 ni = skipsubscript (string, i);
334 if (string[ni] == ']')
338 else if (MEMBER (c, charlist))
342 temp = xmalloc (1 + c);
343 strncpy (temp, string + *sindex, c);
349 /* Extract the contents of STRING as if it is enclosed in double quotes.
350 SINDEX, when passed in, is the offset of the character immediately
351 following the opening double quote; on exit, SINDEX is left pointing after
352 the closing double quote. If STRIPDQ is non-zero, unquoted double
353 quotes are stripped and the string is terminated by a null byte.
354 Backslashes between the embedded double quotes are processed. If STRIPDQ
355 is zero, an unquoted `"' terminates the string. */
357 string_extract_double_quoted (string, sindex, stripdq)
359 int *sindex, stripdq;
362 char *temp, *ret; /* The new string we return. */
363 int pass_next, backquote, si; /* State variables for the machine. */
366 pass_next = backquote = dquote = 0;
367 temp = xmalloc (1 + strlen (string) - *sindex);
369 for (j = 0, i = *sindex; c = string[i]; i++)
371 /* Process a character that was quoted by a backslash. */
376 ``The backslash shall retain its special meaning as an escape
377 character only when followed by one of the characters:
380 If STRIPDQ is zero, we handle the double quotes here and let
381 expand_word_internal handle the rest. If STRIPDQ is non-zero,
382 we have already been through one round of backslash stripping,
383 and want to strip these backslashes only if DQUOTE is non-zero,
384 indicating that we are inside an embedded double-quoted string. */
386 /* If we are in an embedded quoted string, then don't strip
387 backslashes before characters for which the backslash
388 retains its special meaning, but remove backslashes in
389 front of other characters. If we are not in an
390 embedded quoted string, don't strip backslashes at all.
391 This mess is necessary because the string was already
392 surrounded by double quotes (and sh has some really weird
394 The returned string will be run through expansion as if
395 it were double-quoted. */
396 if ((stripdq == 0 && c != '"') ||
397 (stripdq && ((dquote && strchr (slashify_in_quotes, c)) || dquote == 0)))
404 /* A backslash protects the next character. The code just above
405 handles preserving the backslash in front of any character but
413 /* Inside backquotes, ``the portion of the quoted string from the
414 initial backquote and the characters up to the next backquote
415 that is not preceded by a backslash, having escape characters
416 removed, defines that command''. */
432 /* Pass everything between `$(' and the matching `)' or a quoted
433 ${ ... } pair through according to the Posix.2 specification. */
434 if (c == '$' && ((string[i + 1] == '(') || (string[i + 1] == '{')))
437 if (string[i + 1] == '(')
438 ret = extract_delimited_string (string, &si, "$(", "(", ")");
440 ret = extract_dollar_brace_string (string, &si, 1);
443 temp[j++] = string[i + 1];
445 for (t = 0; ret[t]; t++, j++)
447 temp[j++] = string[si];
454 /* Add any character but a double quote to the quoted string we're
473 /* Point to after the closing quote. */
481 /* This should really be another option to string_extract_double_quoted. */
483 skip_double_quoted (string, sind)
489 int pass_next, backquote, si;
491 pass_next = backquote = 0;
493 for (j = 0, i = sind; c = string[i]; i++)
516 else if (c == '$' && ((string[i + 1] == '(') || (string[i + 1] == '{')))
519 if (string[i + 1] == '(')
520 ret = extract_delimited_string (string, &si, "$(", "(", ")");
522 ret = extract_dollar_brace_string (string, &si, 0);
540 /* Extract the contents of STRING as if it is enclosed in single quotes.
541 SINDEX, when passed in, is the offset of the character immediately
542 following the opening single quote; on exit, SINDEX is left pointing after
543 the closing single quote. */
545 string_extract_single_quoted (string, sindex)
552 for (i = *sindex; string[i] && string[i] != '\''; i++)
557 strncpy (t, string + *sindex, j);
568 skip_single_quoted (string, sind)
574 for (i = sind; string[i] && string[i] != '\''; i++)
581 /* Just like string_extract, but doesn't hack backslashes or any of
582 that other stuff. Obeys quoting. Used to do splitting on $IFS. */
584 string_extract_verbatim (string, sindex, charlist)
585 char *string, *charlist;
588 register int i = *sindex;
592 if (charlist[0] == '\'' && charlist[1] == '\0')
594 temp = string_extract_single_quoted (string, sindex);
595 --*sindex; /* leave *sindex at separator character */
599 for (i = *sindex; c = string[i]; i++)
607 if (MEMBER (c, charlist))
612 temp = xmalloc (1 + c);
613 strncpy (temp, string + *sindex, c);
620 /* Extract the $( construct in STRING, and return a new string.
621 Start extracting at (SINDEX) as if we had just seen "$(".
622 Make (SINDEX) get the position of the matching ")". */
624 extract_command_subst (string, sindex)
628 return (extract_delimited_string (string, sindex, "$(", "(", ")"));
631 /* Extract the $[ construct in STRING, and return a new string.
632 Start extracting at (SINDEX) as if we had just seen "$[".
633 Make (SINDEX) get the position of the matching "]". */
635 extract_arithmetic_subst (string, sindex)
639 return (extract_delimited_string (string, sindex, "$[", "[", "]"));
642 #if defined (PROCESS_SUBSTITUTION)
643 /* Extract the <( or >( construct in STRING, and return a new string.
644 Start extracting at (SINDEX) as if we had just seen "<(".
645 Make (SINDEX) get the position of the matching ")". */
647 extract_process_subst (string, starter, sindex)
652 return (extract_delimited_string (string, sindex, starter, "(", ")"));
654 #endif /* PROCESS_SUBSTITUTION */
656 #if defined (ARRAY_VARS)
658 extract_array_assignment_list (string, sindex)
662 return (extract_delimited_string (string, sindex, "(", (char *)NULL, ")"));
666 /* Extract and create a new string from the contents of STRING, a
667 character string delimited with OPENER and CLOSER. SINDEX is
668 the address of an int describing the current offset in STRING;
669 it should point to just after the first OPENER found. On exit,
670 SINDEX gets the position of the last character of the matching CLOSER.
671 If OPENER is more than a single character, ALT_OPENER, if non-null,
672 contains a character string that can also match CLOSER and thus
673 needs to be skipped. */
675 extract_delimited_string (string, sindex, opener, alt_opener, closer)
678 char *opener, *alt_opener, *closer;
682 int pass_character, nesting_level;
683 int len_closer, len_opener, len_alt_opener;
685 len_opener = STRLEN (opener);
686 len_alt_opener = STRLEN (alt_opener);
687 len_closer = STRLEN (closer);
694 while (nesting_level)
701 if (pass_character) /* previous char was backslash */
716 if (c == '\\' && delimiter == '"' &&
717 (member (string[i], slashify_in_quotes)))
727 /* Process a nested OPENER. */
728 if (STREQN (string + i, opener, len_opener))
731 t = extract_delimited_string (string, &si, opener, alt_opener, closer);
737 /* Process a nested ALT_OPENER */
738 if (len_alt_opener && STREQN (string + i, alt_opener, len_alt_opener))
740 si = i + len_alt_opener;
741 t = extract_delimited_string (string, &si, alt_opener, alt_opener, closer);
747 /* If the current substring terminates the delimited string, decrement
748 the nesting level. */
749 if (STREQN (string + i, closer, len_closer))
751 i += len_closer - 1; /* move to last char of the closer */
753 if (nesting_level == 0)
757 /* Pass old-style command substitution through verbatim. */
761 t = string_extract (string, &si, "`", 0);
767 /* Pass single-quoted strings through verbatim. */
771 i = skip_single_quoted (string, si);
775 /* Pass embedded double-quoted strings through verbatim as well. */
779 i = skip_double_quoted (string, si);
783 i++; /* move past this character, which was not special. */
786 si = i - *sindex - len_closer + 1;
787 result = xmalloc (1 + si);
788 strncpy (result, string + *sindex, si);
792 if (c == 0 && nesting_level)
794 report_error ("bad substitution: no `%s' in %s", closer, string);
796 jump_to_top_level (DISCARD);
802 /* Extract a parameter expansion expression within ${ and } from STRING.
803 Obey the Posix.2 rules for finding the ending `}': count braces while
804 skipping over enclosed quoted strings and command substitutions.
805 SINDEX is the address of an int describing the current offset in STRING;
806 it should point to just after the first `{' found. On exit, SINDEX
807 gets the position of the matching `}'. QUOTED is non-zero if this
808 occurs inside double quotes. */
809 /* XXX -- this is very similar to extract_delimited_string -- XXX */
811 extract_dollar_brace_string (string, sindex, quoted)
815 register int i, c, l;
816 int pass_character, nesting_level, si;
823 for (i = *sindex; (c = string[i]); i++)
837 /* Backslashes quote the next character. */
844 if (string[i] == '$' && string[i+1] == '{')
854 if (nesting_level == 0)
859 /* Pass the contents of old-style command substitutions through
864 t = string_extract (string, &si, "`", 0);
870 /* Pass the contents of new-style command substitutions through
872 if (string[i] == '$' && string[i+1] == '(')
875 t = extract_delimited_string (string, &si, "$(", "(", ")");
881 /* Pass the contents of single-quoted strings through verbatim. */
885 i = skip_single_quoted (string, si);
886 /* skip_single_quoted leaves index one past close quote */
891 /* Pass embedded double-quoted strings through verbatim as well. */
895 /* skip_double_quoted leaves index one past close quote */
896 i = skip_double_quoted (string, si);
903 result = xmalloc (1 + l);
904 strncpy (result, string + *sindex, l);
908 if (c == 0 && nesting_level)
910 report_error ("bad substitution: no ending `}' in %s", string);
912 jump_to_top_level (DISCARD);
918 /* Remove backslashes which are quoting backquotes from STRING. Modifies
919 STRING, and returns a pointer to it. */
921 de_backslash (string)
926 for (i = 0, l = strlen (string); i < l; i++)
927 if (string[i] == '\\' && (string[i + 1] == '`' || string[i + 1] == '\\' ||
928 string[i + 1] == '$'))
929 strcpy (string + i, string + i + 1); /* XXX - should be memmove */
934 /* Replace instances of \! in a string with !. */
936 unquote_bang (string)
942 temp = xmalloc (1 + strlen (string));
944 for (i = 0, j = 0; (temp[j] = string[i]); i++, j++)
946 if (string[i] == '\\' && string[i + 1] == '!')
952 strcpy (string, temp);
957 #if defined (READLINE)
958 /* Return 1 if the portion of STRING ending at EINDEX is quoted (there is
959 an unclosed quoted string), or if the character at EINDEX is quoted
962 char_is_quoted (string, eindex)
966 int i, pass_next, quoted;
968 for (i = pass_next = quoted = 0; i <= eindex; i++)
973 if (i >= eindex) /* XXX was if (i >= eindex - 1) */
977 else if (string[i] == '\'' || string[i] == '"')
979 i = (string[i] == '\'') ? skip_single_quoted (string, ++i)
980 : skip_double_quoted (string, ++i);
983 i--; /* the skip functions increment past the closing quote. */
985 else if (string[i] == '\\')
995 unclosed_pair (string, eindex, openstr)
1000 int i, pass_next, openc, olen;
1002 olen = strlen (openstr);
1003 for (i = pass_next = openc = 0; i <= eindex; i++)
1008 if (i >= eindex) /* XXX was if (i >= eindex - 1) */
1012 else if (STREQN (string + i, openstr, olen))
1017 else if (string[i] == '\'' || string[i] == '"')
1019 i = (string[i] == '\'') ? skip_single_quoted (string, i)
1020 : skip_double_quoted (string, i);
1024 else if (string[i] == '\\')
1032 #endif /* READLINE */
1036 /* Extract the name of the variable to bind to from the assignment string. */
1038 assignment_name (string)
1044 offset = assignment (string);
1046 return (char *)NULL;
1047 temp = xmalloc (offset + 1);
1048 strncpy (temp, string, offset);
1049 temp[offset] = '\0';
1054 /* Return a single string of all the words in LIST. SEP is the separator
1055 to put between individual elements of LIST in the output string. */
1057 string_list_internal (list, sep)
1061 register WORD_LIST *t;
1063 int word_len, sep_len, result_size;
1066 return ((char *)NULL);
1068 /* This is nearly always called with either sep[0] == 0 or sep[1] == 0. */
1069 sep_len = STRLEN (sep);
1072 for (t = list; t; t = t->next)
1075 result_size += sep_len;
1076 result_size += strlen (t->word->word);
1079 r = result = xmalloc (result_size + 1);
1081 for (t = list; t; t = t->next)
1083 if (t != list && sep_len)
1087 FASTCOPY (sep, r, sep_len);
1094 word_len = strlen (t->word->word);
1095 FASTCOPY (t->word->word, r, word_len);
1103 /* Return a single string of all the words present in LIST, separating
1104 each word with a space. */
1109 return (string_list_internal (list, " "));
1112 /* Return a single string of all the words present in LIST, obeying the
1113 quoting rules for "$*", to wit: (P1003.2, draft 11, 3.5.2) "If the
1114 expansion [of $*] appears within a double quoted string, it expands
1115 to a single field with the value of each parameter separated by the
1116 first character of the IFS variable, or by a <space> if IFS is unset." */
1118 string_list_dollar_star (list)
1123 ifs = get_string_value ("IFS");
1126 else if (*ifs == '\0')
1133 return (string_list_internal (list, sep));
1136 /* Return the list of words present in STRING. Separate the string into
1137 words at any of the characters found in SEPARATORS. If QUOTED is
1138 non-zero then word in the list will have its quoted flag set, otherwise
1139 the quoted flag is left as make_word () deemed fit.
1141 This obeys the P1003.2 word splitting semantics. If `separators' is
1142 exactly <space><tab><newline>, then the splitting algorithm is that of
1143 the Bourne shell, which treats any sequence of characters from `separators'
1144 as a delimiter. If IFS is unset, which results in `separators' being set
1145 to "", no splitting occurs. If separators has some other value, the
1146 following rules are applied (`IFS white space' means zero or more
1147 occurrences of <space>, <tab>, or <newline>, as long as those characters
1148 are in `separators'):
1150 1) IFS white space is ignored at the start and the end of the
1152 2) Each occurrence of a character in `separators' that is not
1153 IFS white space, along with any adjacent occurrences of
1154 IFS white space delimits a field.
1155 3) Any nonzero-length sequence of IFS white space delimits a field.
1158 /* BEWARE! list_string strips null arguments. Don't call it twice and
1159 expect to have "" preserved! */
1161 /* Perform quoted null character removal on STRING. We don't allow any
1162 quoted null characters in the middle or at the ends of strings because
1163 of how expand_word_internal works. remove_quoted_nulls () turns
1164 STRING into an empty string iff it only consists of a quoted null,
1165 and removes all unquoted CTLNUL characters. */
1167 #define remove_quoted_nulls(string) \
1168 do { if (QUOTED_NULL (string)) string[0] ='\0'; } while (0)
1171 remove_quoted_nulls (string)
1176 nstr = savestring (string);
1178 for (p = nstr, s = string; *s; s++)
1182 *p++ = *s++; /* CTLESC */
1185 *p++ = *s; /* quoted char */
1193 strcpy (string, nstr);
1197 /* Perform quoted null character removal on each element of LIST.
1198 This modifies LIST. */
1200 word_list_remove_quoted_nulls (list)
1203 register WORD_LIST *t;
1205 for (t = list; t; t = t->next)
1206 remove_quoted_nulls (t->word->word);
1209 /* This performs word splitting and quoted null character removal on
1211 #define issep(c) (member ((c), separators))
1214 list_string (string, separators, quoted)
1215 register char *string, *separators;
1220 char *current_word, *s;
1221 int sindex, sh_style_split;
1223 if (!string || !*string)
1224 return ((WORD_LIST *)NULL);
1227 separators && *separators && (STREQ (separators, " \t\n"));
1229 /* Remove sequences of whitespace at the beginning of STRING, as
1230 long as those characters appear in IFS. Do not do this if
1231 STRING is quoted or if there are no separator characters. */
1232 if (!quoted || !separators || !*separators)
1234 for (s = string; *s && spctabnl (*s) && issep (*s); s++);
1237 return ((WORD_LIST *)NULL);
1242 /* OK, now STRING points to a word that does not begin with white space.
1243 The splitting algorithm is:
1244 extract a word, stopping at a separator
1245 skip sequences of spc, tab, or nl as long as they are separators
1246 This obeys the field splitting rules in Posix.2. */
1247 for (result = (WORD_LIST *)NULL, sindex = 0; string[sindex]; )
1249 current_word = string_extract_verbatim (string, &sindex, separators);
1250 if (current_word == 0)
1253 /* If we have a quoted empty string, add a quoted null argument. We
1254 want to preserve the quoted null character iff this is a quoted
1255 empty string; otherwise the quoted null characters are removed
1257 if (QUOTED_NULL (current_word))
1259 t = make_bare_word ("");
1260 t->flags |= W_QUOTED;
1262 t->word = make_quoted_char ('\0');
1263 result = make_word_list (t, result);
1265 else if (current_word[0] != '\0')
1267 /* If we have something, then add it regardless. However,
1268 perform quoted null character removal on the current word. */
1269 remove_quoted_nulls (current_word);
1270 result = make_word_list (make_word (current_word), result);
1271 if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
1272 result->word->flags |= W_QUOTED;
1275 /* If we're not doing sequences of separators in the traditional
1276 Bourne shell style, then add a quoted null argument. */
1277 else if (!sh_style_split && !spctabnl (string[sindex]))
1279 t = make_bare_word ("");
1280 t->flags |= W_QUOTED;
1282 t->word = make_quoted_char ('\0');
1283 result = make_word_list (t, result);
1286 free (current_word);
1288 /* Move past the current separator character. */
1292 /* Now skip sequences of space, tab, or newline characters if they are
1293 in the list of separators. */
1294 while (string[sindex] && spctabnl (string[sindex]) && issep (string[sindex]))
1297 return (REVERSE_LIST (result, WORD_LIST *));
1300 /* Parse a single word from STRING, using SEPARATORS to separate fields.
1301 ENDPTR is set to the first character after the word. This is used by
1303 XXX - this function is very similar to list_string; they should be
1306 get_word_from_string (stringp, separators, endptr)
1307 char **stringp, *separators, **endptr;
1311 int sindex, sh_style_split;
1313 if (!stringp || !*stringp || !**stringp)
1314 return ((char *)NULL);
1319 separators && *separators && (STREQ (separators, " \t\n"));
1321 /* Remove sequences of whitespace at the beginning of STRING, as
1322 long as those characters appear in IFS. */
1323 if (sh_style_split || !separators || !*separators)
1325 for (; *s && spctabnl (*s) && issep (*s); s++);
1327 /* If the string is nothing but whitespace, update it and return. */
1333 return ((char *)NULL);
1337 /* OK, S points to a word that does not begin with white space.
1338 Now extract a word, stopping at a separator, save a pointer to
1339 the first character after the word, then skip sequences of spc,
1340 tab, or nl as long as they are separators.
1342 This obeys the field splitting rules in Posix.2. */
1344 current_word = string_extract_verbatim (s, &sindex, separators);
1346 /* Set ENDPTR to the first character after the end of the word. */
1348 *endptr = s + sindex;
1350 /* Move past the current separator character. */
1354 /* Now skip sequences of space, tab, or newline characters if they are
1355 in the list of separators. */
1356 while (s[sindex] && spctabnl (s[sindex]) && issep (s[sindex]))
1359 /* Update STRING to point to the next field. */
1360 *stringp = s + sindex;
1361 return (current_word);
1364 /* Remove IFS white space at the end of STRING. Start at the end
1365 of the string and walk backwards until the beginning of the string
1366 or we find a character that's not IFS white space and not CTLESC.
1367 Only let CTLESC escape a white space character if SAW_ESCAPE is
1370 strip_trailing_ifs_whitespace (string, separators, saw_escape)
1371 char *string, *separators;
1376 s = string + STRLEN (string) - 1;
1377 while (s > string && ((spctabnl (*s) && issep (*s)) ||
1378 (saw_escape && *s == CTLESC && spctabnl (s[1]))))
1385 #if defined (ARRAY_VARS)
1387 list_string_with_quotes (string)
1392 int c, i, tokstart, len;
1394 for (s = string; s && *s && spctabnl (*s); s++)
1396 if (s == 0 || *s == 0)
1397 return ((WORD_LIST *)NULL);
1400 list = (WORD_LIST *)NULL;
1411 i = skip_single_quoted (s, ++i);
1413 i = skip_double_quoted (s, ++i);
1414 else if (c == 0 || spctabnl (c))
1416 /* We have found the end of a token. Make a word out of it and
1417 add it to the word list. */
1419 token = xmalloc (len + 1);
1420 strncpy (token, s + tokstart, len);
1422 list = make_word_list (make_word (token), list);
1424 while (spctabnl (s[i]))
1432 i++; /* normal character */
1434 return (REVERSE_LIST (list, WORD_LIST *));
1436 #endif /* ARRAY_VARS */
1439 #if defined (PROCESS_SUBSTITUTION)
1440 #define EXP_CHAR(s) (s == '$' || s == '`' || s == '<' || s == '>' || s == CTLESC)
1442 #define EXP_CHAR(s) (s == '$' || s == '`' || s == CTLESC)
1445 /* If there are any characters in STRING that require full expansion,
1446 then call FUNC to expand STRING; otherwise just perform quote
1447 removal if necessary. This returns a new string. */
1449 maybe_expand_string (string, quoted, func)
1452 WORD_LIST *(*func)();
1458 for (i = saw_quote = 0; string[i]; i++)
1460 if (EXP_CHAR (string[i]))
1462 else if (string[i] == '\'' || string[i] == '\\' || string[i] == '"')
1468 list = (*func) (string, quoted);
1471 ret = string_list (list);
1472 dispose_words (list);
1477 else if (saw_quote && ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) == 0))
1478 ret = string_quote_removal (string, quoted);
1480 ret = savestring (string);
1484 static inline char *
1485 expand_string_to_string (string, quoted, func)
1488 WORD_LIST *(*func)();
1493 if (string == 0 || *string == '\0')
1494 return ((char *)NULL);
1496 list = (*func) (string, quoted);
1499 ret = string_list (list);
1500 dispose_words (list);
1508 #if defined (ARRAY_VARS)
1510 do_array_element_assignment (name, value)
1517 t = strchr (name, '[');
1519 return ((SHELL_VAR *)NULL);
1521 ni = skipsubscript (name, ind);
1522 if ((ALL_ELEMENT_SUB (t[1]) && t[2] == ']') || (ni <= ind + 1))
1524 report_error ("%s: bad array subscript", name);
1525 return ((SHELL_VAR *)NULL);
1528 ind = array_expand_index (t, ni - ind);
1531 t[-1] = '['; /* restore original name */
1532 report_error ("%s: bad array subscript", name);
1533 return ((SHELL_VAR *)NULL);
1535 entry = bind_array_variable (name, ind, value);
1536 t[-1] = '['; /* restore original name */
1539 #endif /* ARRAY_VARS */
1541 /* Given STRING, an assignment string, get the value of the right side
1542 of the `=', and bind it to the left side. If EXPAND is true, then
1543 perform parameter expansion, command substitution, and arithmetic
1544 expansion on the right-hand side. Perform tilde expansion in any
1545 case. Do not perform word splitting on the result of expansion. */
1547 do_assignment_internal (string, expand)
1554 #if defined (ARRAY_VARS)
1556 int ni, assign_list = 0;
1559 offset = assignment (string);
1560 name = savestring (string);
1561 value = (char *)NULL;
1563 if (name[offset] == '=')
1568 temp = name + offset + 1;
1570 #if defined (ARRAY_VARS)
1571 if (expand && temp[0] == '(' && strchr (temp, ')'))
1573 assign_list = ni = 1;
1574 value = extract_delimited_string (temp, &ni, "(", (char *)NULL, ")");
1579 /* Perform tilde expansion. */
1580 if (expand && temp[0])
1582 temp = (strchr (temp, '~') && unquoted_member ('~', temp))
1583 ? bash_tilde_expand (temp)
1584 : savestring (temp);
1586 value = maybe_expand_string (temp, 0, expand_string_unsplit);
1590 value = savestring (temp);
1595 value = xmalloc (1);
1599 if (echo_command_at_execute)
1600 #if defined (ARRAY_VARS)
1602 fprintf (stderr, "%s%s=(%s)\n", indirection_level_string (), name, value);
1605 fprintf (stderr, "%s%s=%s\n", indirection_level_string (), name, value);
1607 #define ASSIGN_RETURN(r) do { FREE (value); free (name); return (r); } while (0)
1609 #if defined (ARRAY_VARS)
1610 if (t = strchr (name, '['))
1614 report_error ("%s: cannot assign list to array member", name);
1617 entry = do_array_element_assignment (name, value);
1621 else if (assign_list)
1622 entry = assign_array_from_string (name, value);
1624 #endif /* ARRAY_VARS */
1625 entry = bind_variable (name, value);
1627 stupidly_hack_special_variables (name);
1630 entry->attributes &= ~att_invisible;
1632 /* Return 1 if the assignment seems to have been performed correctly. */
1633 ASSIGN_RETURN (entry ? ((entry->attributes & att_readonly) == 0) : 0);
1636 /* Perform the assignment statement in STRING, and expand the
1637 right side by doing command and parameter expansion. */
1639 do_assignment (string)
1642 return do_assignment_internal (string, 1);
1645 /* Given STRING, an assignment string, get the value of the right side
1646 of the `=', and bind it to the left side. Do not do command and
1647 parameter substitution on the right hand side. */
1649 do_assignment_no_expand (string)
1652 return do_assignment_internal (string, 0);
1655 /* Most of the substitutions must be done in parallel. In order
1656 to avoid using tons of unclear goto's, I have some functions
1657 for manipulating malloc'ed strings. They all take INDX, a
1658 pointer to an integer which is the offset into the string
1659 where manipulation is taking place. They also take SIZE, a
1660 pointer to an integer which is the current length of the
1661 character array for this string. */
1663 /* Append SOURCE to TARGET at INDEX. SIZE is the current amount
1664 of space allocated to TARGET. SOURCE can be NULL, in which
1665 case nothing happens. Gets rid of SOURCE by freeing it.
1666 Returns TARGET in case the location has changed. */
1668 sub_append_string (source, target, indx, size)
1669 char *source, *target;
1676 srclen = STRLEN (source);
1677 if (srclen >= (int)(*size - *indx))
1680 n = (n + DEFAULT_ARRAY_SIZE) - (n % DEFAULT_ARRAY_SIZE);
1681 target = xrealloc (target, (*size = n));
1684 FASTCOPY (source, target + *indx, srclen);
1686 target[*indx] = '\0';
1695 /* Append the textual representation of NUMBER to TARGET.
1696 INDX and SIZE are as in SUB_APPEND_STRING. */
1698 sub_append_number (number, target, indx, size)
1699 int number, *indx, *size;
1704 temp = itos (number);
1705 return (sub_append_string (temp, target, indx, size));
1709 /* Return the word list that corresponds to `$*'. */
1711 list_rest_of_args ()
1713 register WORD_LIST *list, *args;
1716 /* Break out of the loop as soon as one of the dollar variables is null. */
1717 for (i = 1, list = (WORD_LIST *)NULL; i < 10 && dollar_vars[i]; i++)
1718 list = make_word_list (make_bare_word (dollar_vars[i]), list);
1720 for (args = rest_of_args; args; args = args->next)
1721 list = make_word_list (make_bare_word (args->word->word), list);
1723 return (REVERSE_LIST (list, WORD_LIST *));
1729 register WORD_LIST *list;
1732 for (n = 0; n < 9 && dollar_vars[n+1]; n++)
1734 for (list = rest_of_args; list; list = list->next)
1739 /* Make a single large string out of the dollar digit variables,
1740 and the rest_of_args. If DOLLAR_STAR is 1, then obey the special
1741 case of "$*" with respect to IFS. */
1743 string_rest_of_args (dollar_star)
1746 register WORD_LIST *list;
1749 list = list_rest_of_args ();
1750 string = dollar_star ? string_list_dollar_star (list) : string_list (list);
1751 dispose_words (list);
1755 /***************************************************
1757 * Functions to Expand a String *
1759 ***************************************************/
1760 /* Call expand_word_internal to expand W and handle error returns.
1761 A convenience function for functions that don't want to handle
1762 any errors or free any memory before aborting. */
1764 call_expand_word_internal (w, q, c, e)
1770 result = expand_word_internal (w, q, c, e);
1771 if (result == &expand_word_error)
1773 /* By convention, each time this error is returned, w->word has
1774 already been freed. */
1775 w->word = (char *)NULL;
1776 jump_to_top_level (DISCARD);
1779 else if (result == &expand_word_fatal)
1780 jump_to_top_level (FORCE_EOF);
1786 /* Perform parameter expansion, command substitution, and arithmetic
1787 expansion on STRING, as if it were a word. Leave the result quoted. */
1789 expand_string_internal (string, quoted)
1796 if (string == 0 || *string == 0)
1797 return ((WORD_LIST *)NULL);
1799 bzero ((char *)&td, sizeof (td));
1801 tresult = call_expand_word_internal (&td, quoted, (int *)NULL, (int *)NULL);
1805 /* Expand STRING by performing parameter expansion, command substitution,
1806 and arithmetic expansion. Dequote the resulting WORD_LIST before
1807 returning it, but do not perform word splitting. The call to
1808 remove_quoted_nulls () is in here because word splitting normally
1809 takes care of quote removal. */
1811 expand_string_unsplit (string, quoted)
1817 if (!string || !*string)
1818 return ((WORD_LIST *)NULL);
1820 value = expand_string_internal (string, quoted);
1824 remove_quoted_nulls (value->word->word);
1825 dequote_list (value);
1830 /* Expand STRING just as if you were expanding a word, but do not dequote
1831 the resultant WORD_LIST. This is called only from within this file,
1832 and is used to correctly preserve quoted characters when expanding
1833 things like ${1+"$@"}. This does parameter expansion, command
1834 subsitution, arithmetic expansion, and word splitting. */
1836 expand_string_leave_quoted (string, quoted)
1843 if (string == 0 || *string == '\0')
1844 return ((WORD_LIST *)NULL);
1846 tlist = expand_string_internal (string, quoted);
1850 tresult = word_list_split (tlist);
1851 dispose_words (tlist);
1854 return ((WORD_LIST *)NULL);
1857 /* This does not perform word splitting or dequote the WORD_LIST
1860 expand_string_for_rhs (string, quoted, dollar_at_p, has_dollar_at)
1862 int quoted, *dollar_at_p, *has_dollar_at;
1867 if (string == 0 || *string == '\0')
1868 return (WORD_LIST *)NULL;
1870 bzero ((char *)&td, sizeof (td));
1872 tresult = call_expand_word_internal (&td, quoted, dollar_at_p, has_dollar_at);
1876 /* Expand STRING just as if you were expanding a word. This also returns
1877 a list of words. Note that filename globbing is *NOT* done for word
1878 or string expansion, just when the shell is expanding a command. This
1879 does parameter expansion, command substitution, arithmetic expansion,
1880 and word splitting. Dequote the resultant WORD_LIST before returning. */
1882 expand_string (string, quoted)
1888 if (!string || !*string)
1889 return ((WORD_LIST *)NULL);
1891 result = expand_string_leave_quoted (string, quoted);
1892 return (result ? dequote_list (result) : result);
1895 /***************************************************
1897 * Functions to handle quoting chars *
1899 ***************************************************/
1906 register WORD_LIST *tlist;
1908 for (tlist = list; tlist; tlist = tlist->next)
1910 s = dequote_string (tlist->word->word);
1911 free (tlist->word->word);
1912 tlist->word->word = s;
1918 make_quoted_char (c)
1938 /* Quote STRING. Return a new string. */
1940 quote_string (string)
1948 result = xmalloc (2);
1954 result = xmalloc ((strlen (string) * 2) + 1);
1956 for (t = result; *string; )
1966 /* De-quoted quoted characters in STRING. */
1968 dequote_string (string)
1974 result = xmalloc (strlen (string) + 1);
1976 if (QUOTED_NULL (string))
1982 /* If no character in the string can be quoted, don't bother examining
1983 each character. Just return a copy of the string passed to us. */
1984 if (strchr (string, CTLESC) == NULL) /* XXX */
1986 strcpy (result, string); /* XXX */
1987 return (result); /* XXX */
1990 for (t = result; *string; string++, t++)
1992 if (*string == CTLESC)
2007 /* Quote the entire WORD_LIST list. */
2012 register WORD_LIST *w;
2015 for (w = list; w; w = w->next)
2018 w->word->word = quote_string (t);
2020 w->word->flags |= W_QUOTED;
2025 /* **************************************************************** */
2027 /* Functions for Removing Patterns */
2029 /* **************************************************************** */
2031 /* Remove the portion of PARAM matched by PATTERN according to OP, where OP
2032 can have one of 4 values:
2033 RP_LONG_LEFT remove longest matching portion at start of PARAM
2034 RP_SHORT_LEFT remove shortest matching portion at start of PARAM
2035 RP_LONG_RIGHT remove longest matching portion at end of PARAM
2036 RP_SHORT_RIGHT remove shortest matching portion at end of PARAM
2039 #define RP_LONG_LEFT 1
2040 #define RP_SHORT_LEFT 2
2041 #define RP_LONG_RIGHT 3
2042 #define RP_SHORT_RIGHT 4
2045 remove_pattern (param, pattern, op)
2046 char *param, *pattern;
2051 register char *p, *ret, c;
2053 if (param == NULL || *param == '\0')
2055 if (pattern == NULL || *pattern == '\0') /* minor optimization */
2056 return (savestring (param));
2058 len = STRLEN (param);
2063 case RP_LONG_LEFT: /* remove longest match at start */
2064 for (p = end; p >= param; p--)
2067 if (fnmatch (pattern, param, 0) != FNM_NOMATCH)
2070 return (savestring (p));
2076 case RP_SHORT_LEFT: /* remove shortest match at start */
2077 for (p = param; p <= end; p++)
2080 if (fnmatch (pattern, param, 0) != FNM_NOMATCH)
2083 return (savestring (p));
2089 case RP_LONG_RIGHT: /* remove longest match at end */
2090 for (p = param; p <= end; p++)
2092 if (fnmatch (pattern, p, 0) != FNM_NOMATCH)
2095 ret = savestring (param);
2102 case RP_SHORT_RIGHT: /* remove shortest match at end */
2103 for (p = end; p >= param; p--)
2105 if (fnmatch (pattern, p, 0) != FNM_NOMATCH)
2108 ret = savestring (param);
2115 return (savestring (param)); /* no match, return original string */
2118 /* Return 1 of the first character of STRING could match the first
2119 character of pattern PAT. Used to avoid n2 calls to fnmatch(). */
2121 match_pattern_char (pat, string)
2137 return (*string == c);
2139 return (*string == *pat);
2141 return (*string != '\0');
2146 for (np = pat; *np != ']'; np++);
2148 return (*string == '[');
2149 if (neg = (*pat == '!' || *pat == '^'))
2151 for ( ; (c1 = *pat++) != ']'; )
2157 if (*pat != '-' || pat[1] == '\0' || pat[1] == ']')
2158 return (neg ? *string != c1 : *string == c1);
2159 if (c1 <= *string && *string <= pat[1])
2164 return (*string != '\0');
2169 /* Match PAT anywhere in STRING and return the match boundaries.
2170 This returns 1 in case of a successful match, 0 otherwise. SP
2171 and EP are pointers into the string where the match begins and
2172 ends, respectively. MTYPE controls what kind of match is attempted.
2173 MATCH_BEG and MATCH_END anchor the match at the beginning and end
2174 of the string, respectively. The longest match is returned. */
2176 match_pattern (string, pat, mtype, sp, ep)
2182 register char *p, *p1;
2185 if (string == 0 || *string == 0 || pat == 0 || *pat == 0)
2188 end = string + STRLEN (string);
2193 for (p = string; p <= end; p++)
2195 if (match_pattern_char (pat, p))
2197 for (p1 = end; p1 >= p; p1--)
2199 c = *p1; *p1 = '\0';
2200 if (fnmatch (pat, p, 0) == 0)
2214 if (match_pattern_char (pat, string) == 0)
2216 for (p = end; p >= string; p--)
2219 if (fnmatch (pat, string, 0) == 0)
2231 for (p = string; p <= end; p++)
2232 if (fnmatch (pat, p, 0) == 0)
2244 /*******************************************
2246 * Functions to expand WORD_DESCs *
2248 *******************************************/
2250 /* Expand WORD, performing word splitting on the result. This does
2251 parameter expansion, command substitution, arithmetic expansion,
2252 word splitting, and quote removal. */
2255 expand_word (word, quoted)
2259 WORD_LIST *result, *tresult;
2261 tresult = call_expand_word_internal (word, quoted, (int *)NULL, (int *)NULL);
2262 result = word_list_split (tresult);
2263 dispose_words (tresult);
2264 return (result ? dequote_list (result) : result);
2267 /* Expand WORD, but do not perform word splitting on the result. This
2268 does parameter expansion, command substitution, arithmetic expansion,
2269 and quote removal. */
2271 expand_word_no_split (word, quoted)
2277 result = call_expand_word_internal (word, quoted, (int *)NULL, (int *)NULL);
2278 return (result ? dequote_list (result) : result);
2281 /* Perform shell expansions on WORD, but do not perform word splitting or
2282 quote removal on the result. */
2284 expand_word_leave_quoted (word, quoted)
2288 return (call_expand_word_internal (word, quoted, (int *)NULL, (int *)NULL));
2291 /* Return the value of a positional parameter. This handles values > 10. */
2293 get_dollar_var_value (ind)
2300 temp = dollar_vars[ind] ? savestring (dollar_vars[ind]) : (char *)NULL;
2301 else /* We want something like ${11} */
2304 for (p = rest_of_args; p && ind--; p = p->next)
2306 temp = p ? savestring (p->word->word) : (char *)NULL;
2311 #if defined (PROCESS_SUBSTITUTION)
2313 /* **************************************************************** */
2315 /* Hacking Process Substitution */
2317 /* **************************************************************** */
2319 #if !defined (HAVE_DEV_FD)
2320 /* Named pipes must be removed explicitly with `unlink'. This keeps a list
2321 of FIFOs the shell has open. unlink_fifo_list will walk the list and
2322 unlink all of them. add_fifo_list adds the name of an open FIFO to the
2323 list. NFIFO is a count of the number of FIFOs in the list. */
2324 #define FIFO_INCR 20
2325 extern char *mktemp ();
2327 static char **fifo_list = (char **)NULL;
2329 static int fifo_list_size;
2332 add_fifo_list (pathname)
2335 if (nfifo >= fifo_list_size - 1)
2337 fifo_list_size += FIFO_INCR;
2338 fifo_list = (char **)xrealloc (fifo_list,
2339 fifo_list_size * sizeof (char *));
2342 fifo_list[nfifo++] = savestring (pathname);
2353 unlink (fifo_list[nfifo]);
2354 free (fifo_list[nfifo]);
2355 fifo_list[nfifo] = (char *)NULL;
2365 tname = mktemp (savestring ("/tmp/sh-np-XXXXXX"));
2366 if (mkfifo (tname, 0600) < 0)
2369 return ((char *)NULL);
2372 add_fifo_list (tname);
2376 #else /* HAVE_DEV_FD */
2378 /* DEV_FD_LIST is a bitmap of file descriptors attached to pipes the shell
2379 has open to children. NFDS is a count of the number of bits currently
2380 set in DEV_FD_LIST. TOTFDS is a count of the highest possible number
2382 static char *dev_fd_list = (char *)NULL;
2384 static int totfds; /* The highest possible number of open files. */
2390 if (!dev_fd_list || fd >= totfds)
2395 totfds = getdtablesize ();
2396 if (totfds < 0 || totfds > 256)
2401 dev_fd_list = xrealloc (dev_fd_list, totfds);
2402 bzero (dev_fd_list + ofds, totfds - ofds);
2405 dev_fd_list[fd] = 1;
2417 for (i = 0; nfds && i < totfds; i++)
2428 #if defined (NOTDEF)
2429 print_dev_fd_list ()
2433 fprintf (stderr, "pid %d: dev_fd_list:", getpid ());
2436 for (i = 0; i < totfds; i++)
2439 fprintf (stderr, " %d", i);
2441 fprintf (stderr, "\n");
2446 make_dev_fd_filename (fd)
2451 ret = xmalloc (sizeof (DEV_FD_PREFIX) + 4);
2452 sprintf (ret, "%s%d", DEV_FD_PREFIX, fd);
2457 #endif /* HAVE_DEV_FD */
2459 /* Return a filename that will open a connection to the process defined by
2460 executing STRING. HAVE_DEV_FD, if defined, means open a pipe and return
2461 a filename in /dev/fd corresponding to a descriptor that is one of the
2462 ends of the pipe. If not defined, we use named pipes on systems that have
2463 them. Systems without /dev/fd and named pipes are out of luck.
2465 OPEN_FOR_READ_IN_CHILD, if 1, means open the named pipe for reading or
2466 use the read end of the pipe and dup that file descriptor to fd 0 in
2467 the child. If OPEN_FOR_READ_IN_CHILD is 0, we open the named pipe for
2468 writing or use the write end of the pipe in the child, and dup that
2469 file descriptor to fd 1 in the child. The parent does the opposite. */
2472 process_substitute (string, open_for_read_in_child)
2474 int open_for_read_in_child;
2479 #if defined (HAVE_DEV_FD)
2480 int parent_pipe_fd, child_pipe_fd;
2482 #endif /* HAVE_DEV_FD */
2483 #if defined (JOB_CONTROL)
2484 pid_t old_pipeline_pgrp;
2487 if (!string || !*string)
2488 return ((char *)NULL);
2490 #if !defined (HAVE_DEV_FD)
2491 pathname = make_named_pipe ();
2492 #else /* HAVE_DEV_FD */
2493 if (pipe (fildes) < 0)
2495 sys_error ("cannot make pipe for process substitution");
2496 return ((char *)NULL);
2498 /* If OPEN_FOR_READ_IN_CHILD == 1, we want to use the write end of
2499 the pipe in the parent, otherwise the read end. */
2500 parent_pipe_fd = fildes[open_for_read_in_child];
2501 child_pipe_fd = fildes[1 - open_for_read_in_child];
2502 /* Move the parent end of the pipe to some high file descriptor, to
2503 avoid clashes with FDs used by the script. */
2504 parent_pipe_fd = move_to_high_fd (parent_pipe_fd, 1, 64);
2506 pathname = make_dev_fd_filename (parent_pipe_fd);
2507 #endif /* HAVE_DEV_FD */
2511 sys_error ("cannot make pipe for process substitution");
2512 return ((char *)NULL);
2515 old_pid = last_made_pid;
2517 #if defined (JOB_CONTROL)
2518 old_pipeline_pgrp = pipeline_pgrp;
2519 pipeline_pgrp = shell_pgrp;
2521 cleanup_the_pipeline ();
2525 #endif /* JOB_CONTROL */
2527 pid = make_child ((char *)NULL, 1);
2530 reset_terminating_signals (); /* XXX */
2531 /* Cancel traps, in trap.c. */
2532 restore_original_signals ();
2533 setup_async_signals ();
2534 subshell_environment = SUBSHELL_COMSUB;
2537 #if defined (JOB_CONTROL)
2538 set_sigchld_handler ();
2539 stop_making_children ();
2540 pipeline_pgrp = old_pipeline_pgrp;
2541 #endif /* JOB_CONTROL */
2545 sys_error ("cannot make child for process substitution");
2547 #if defined (HAVE_DEV_FD)
2548 close (parent_pipe_fd);
2549 close (child_pipe_fd);
2550 #endif /* HAVE_DEV_FD */
2551 return ((char *)NULL);
2556 #if defined (JOB_CONTROL)
2557 restore_pipeline (1);
2560 last_made_pid = old_pid;
2562 #if defined (JOB_CONTROL) && defined (PGRP_PIPE)
2564 #endif /* JOB_CONTROL && PGRP_PIPE */
2566 #if defined (HAVE_DEV_FD)
2567 close (child_pipe_fd);
2568 #endif /* HAVE_DEV_FD */
2573 set_sigint_handler ();
2575 #if defined (JOB_CONTROL)
2576 set_job_control (0);
2577 #endif /* JOB_CONTROL */
2579 #if !defined (HAVE_DEV_FD)
2580 /* Open the named pipe in the child. */
2581 fd = open (pathname, open_for_read_in_child ? O_RDONLY|O_NONBLOCK : O_WRONLY);
2584 sys_error ("cannot open named pipe %s for %s", pathname,
2585 open_for_read_in_child ? "reading" : "writing");
2588 #else /* HAVE_DEV_FD */
2590 #endif /* HAVE_DEV_FD */
2592 if (dup2 (fd, open_for_read_in_child ? 0 : 1) < 0)
2594 sys_error ("cannot duplicate named pipe %s as fd %d", pathname,
2595 open_for_read_in_child ? 0 : 1);
2601 /* Need to close any files that this process has open to pipes inherited
2603 if (current_fds_to_close)
2605 close_fd_bitmap (current_fds_to_close);
2606 current_fds_to_close = (struct fd_bitmap *)NULL;
2609 #if defined (HAVE_DEV_FD)
2610 /* Make sure we close the parent's end of the pipe and clear the slot
2611 in the fd list so it is not closed later, if reallocated by, for
2612 instance, pipe(2). */
2613 close (parent_pipe_fd);
2614 dev_fd_list[parent_pipe_fd] = 0;
2615 #endif /* HAVE_DEV_FD */
2617 result = parse_and_execute (string, "process substitution", (SEVAL_NONINT|SEVAL_NOHIST));
2619 #if !defined (HAVE_DEV_FD)
2620 /* Make sure we close the named pipe in the child before we exit. */
2621 close (open_for_read_in_child ? 0 : 1);
2622 #endif /* !HAVE_DEV_FD */
2627 #endif /* PROCESS_SUBSTITUTION */
2630 read_comsub (fd, quoted)
2633 char *istring, buf[128], *bufp;
2634 int bufn, istring_index, istring_size, c;
2636 istring = (char *)NULL;
2637 istring_index = istring_size = bufn = 0;
2639 /* Read the output of the command through the pipe. */
2646 while ((bufn = read (fd, buf, sizeof(buf))) < 0 && errno == EINTR)
2654 /* Add the character to ISTRING, possibly after resizing it. */
2655 RESIZE_MALLOCED_BUFFER (istring, istring_index, 2, istring_size, DEFAULT_ARRAY_SIZE);
2657 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || c == CTLESC || c == CTLNUL)
2658 istring[istring_index++] = CTLESC;
2660 istring[istring_index++] = c;
2664 istring[istring_index] = '\0';
2666 /* If we read no output, just return now and save ourselves some
2668 if (istring_index == 0)
2671 return (char *)NULL;
2674 /* Strip trailing newlines from the output of the command. */
2675 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
2677 while (istring_index > 0)
2679 if (istring[istring_index - 1] == '\n')
2683 /* If the newline was quoted, remove the quoting char. */
2684 if (istring[istring_index - 1] == CTLESC)
2690 istring[istring_index] = '\0';
2693 strip_trailing (istring, istring_index - 1, 1);
2698 /* Perform command substitution on STRING. This returns a string,
2701 command_substitute (string, quoted)
2705 pid_t pid, old_pid, old_pipeline_pgrp;
2707 int result, fildes[2];
2709 istring = (char *)NULL;
2711 /* Don't fork () if there is no need to. In the case of no command to
2712 run, just return NULL. */
2713 if (!string || !*string || (string[0] == '\n' && !string[1]))
2714 return ((char *)NULL);
2716 /* Pipe the output of executing STRING into the current shell. */
2717 if (pipe (fildes) < 0)
2719 sys_error ("cannot make pipes for command substitution");
2723 old_pid = last_made_pid;
2724 #if defined (JOB_CONTROL)
2725 old_pipeline_pgrp = pipeline_pgrp;
2726 pipeline_pgrp = shell_pgrp;
2727 cleanup_the_pipeline ();
2730 pid = make_child ((char *)NULL, 0);
2732 /* Reset the signal handlers in the child, but don't free the
2734 reset_signal_handlers ();
2736 #if defined (JOB_CONTROL)
2737 set_sigchld_handler ();
2738 stop_making_children ();
2739 pipeline_pgrp = old_pipeline_pgrp;
2740 #endif /* JOB_CONTROL */
2744 sys_error ("cannot make child for command substitution");
2750 return ((char *)NULL);
2755 set_sigint_handler (); /* XXX */
2756 #if defined (JOB_CONTROL)
2757 set_job_control (0);
2759 if (dup2 (fildes[1], 1) < 0)
2761 sys_error ("command_substitute: cannot duplicate pipe as fd 1");
2762 exit (EXECUTION_FAILURE);
2765 /* If standard output is closed in the parent shell
2766 (such as after `exec >&-'), file descriptor 1 will be
2767 the lowest available file descriptor, and end up in
2768 fildes[0]. This can happen for stdin and stderr as well,
2769 but stdout is more important -- it will cause no output
2770 to be generated from this command. */
2771 if ((fildes[1] != fileno (stdin)) &&
2772 (fildes[1] != fileno (stdout)) &&
2773 (fildes[1] != fileno (stderr)))
2776 if ((fildes[0] != fileno (stdin)) &&
2777 (fildes[0] != fileno (stdout)) &&
2778 (fildes[0] != fileno (stderr)))
2781 /* The currently executing shell is not interactive. */
2784 /* This is a subshell environment. */
2785 subshell_environment = SUBSHELL_COMSUB;
2787 /* Command substitution does not inherit the -e flag. */
2788 exit_immediately_on_error = 0;
2790 remove_quoted_escapes (string);
2792 startup_state = 2; /* see if we can avoid a fork */
2793 /* Give command substitution a place to jump back to on failure,
2794 so we don't go back up to main (). */
2795 result = setjmp (top_level);
2797 if (result == EXITPROG)
2798 exit (last_command_exit_value);
2800 exit (EXECUTION_FAILURE);
2802 exit (parse_and_execute (string, "command substitution", SEVAL_NOHIST));
2806 #if defined (JOB_CONTROL) && defined (PGRP_PIPE)
2808 #endif /* JOB_CONTROL && PGRP_PIPE */
2812 istring = read_comsub (fildes[0], quoted);
2816 last_command_exit_value = wait_for (pid);
2817 last_command_subst_pid = pid;
2818 last_made_pid = old_pid;
2820 #if defined (JOB_CONTROL)
2821 /* If last_command_exit_value > 128, then the substituted command
2822 was terminated by a signal. If that signal was SIGINT, then send
2823 SIGINT to ourselves. This will break out of loops, for instance. */
2824 if (last_command_exit_value == (128 + SIGINT))
2825 kill (getpid (), SIGINT);
2827 /* wait_for gives the terminal back to shell_pgrp. If some other
2828 process group should have it, give it away to that group here. */
2829 if (interactive && pipeline_pgrp != (pid_t)0)
2830 give_terminal_to (pipeline_pgrp);
2831 #endif /* JOB_CONTROL */
2837 /********************************************************
2839 * Utility functions for parameter expansion *
2841 ********************************************************/
2844 getpatspec (c, value)
2849 return ((*value == '#') ? RP_LONG_LEFT : RP_SHORT_LEFT);
2851 return ((*value == '%') ? RP_LONG_RIGHT : RP_SHORT_RIGHT);
2854 /* Posix.2 says that the WORD should be run through tilde expansion,
2855 parameter expansion, command substitution and arithmetic expansion.
2856 This leaves the result quoted, so quote_string_for_globbing () has
2857 to be called to fix it up for fnmatch (). If QUOTED is non-zero,
2858 it means that the entire expression was enclosed in double quotes.
2859 This means that quoting characters in the pattern do not make any
2860 special pattern characters quoted. For example, the `*' in the
2861 following retains its special meaning: "${foo#'*'}". */
2863 getpattern (value, quoted, expandpat)
2865 int quoted, expandpat;
2871 tword = strchr (value, '~') ? bash_tilde_expand (value) : savestring (value);
2873 /* expand_string_internal () leaves WORD quoted and does not perform
2875 if (expandpat && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && *tword)
2878 pat = string_extract_double_quoted (tword, &i, 1);
2883 /* There is a problem here: how to handle single or double quotes in the
2884 pattern string when the whole expression is between double quotes? */
2886 l = *tword ? expand_string_for_rhs (tword, quoted, (int *)NULL, (int *)NULL)
2888 l = *tword ? expand_string_for_rhs (tword,
2889 (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? Q_NOQUOTE : quoted,
2890 (int *)NULL, (int *)NULL)
2894 pat = string_list (l);
2898 tword = quote_string_for_globbing (pat, 1);
2905 /* Handle removing a pattern from a string as a result of ${name%[%]value}
2906 or ${name#[#]value}. */
2908 parameter_brace_remove_pattern (value, temp, c, quoted)
2913 char *pattern, *tword;
2915 patspec = getpatspec (c, value);
2916 if (patspec == RP_LONG_LEFT || patspec == RP_LONG_RIGHT)
2919 pattern = getpattern (value, quoted, 1);
2921 tword = remove_pattern (temp, pattern, patspec);
2928 list_remove_pattern (list, pattern, patspec, type, quoted)
2931 int patspec, type, quoted;
2937 for (new = (WORD_LIST *)NULL, l = list; l; l = l->next)
2939 tword = remove_pattern (l->word->word, pattern, patspec);
2940 w = make_bare_word (tword);
2942 new = make_word_list (w, new);
2945 l = REVERSE_LIST (new, WORD_LIST *);
2947 tword = (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? string_list_dollar_star (l) : string_list (l);
2949 tword = string_list ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? quote_list (l) : l);
2956 parameter_list_remove_pattern (value, type, c, quoted)
2958 int type, c, quoted;
2961 char *pattern, *ret;
2964 patspec = getpatspec (c, value);
2965 if (patspec == RP_LONG_LEFT || patspec == RP_LONG_RIGHT)
2968 pattern = getpattern (value, quoted, 1);
2970 list = list_rest_of_args ();
2971 ret = list_remove_pattern (list, pattern, patspec, type, quoted);
2972 dispose_words (list);
2977 #if defined (ARRAY_VARS)
2979 array_remove_pattern (value, aspec, aval, c, quoted)
2980 char *value, *aspec, *aval; /* AVAL == evaluated ASPEC */
2988 char *ret, *t, *pattern;
2991 var = array_variable_part (aspec, &t, &len);
2993 return ((char *)NULL);
2995 patspec = getpatspec (c, value);
2996 if (patspec == RP_LONG_LEFT || patspec == RP_LONG_RIGHT)
2999 pattern = getpattern (value, quoted, 1);
3001 if (ALL_ELEMENT_SUB (t[0]) && t[1] == ']')
3003 if (array_p (var) == 0)
3005 report_error ("%s: bad array subscript", aspec);
3007 return ((char *)NULL);
3009 l = array_to_word_list (array_cell (var));
3011 return ((char *)NULL);
3012 ret = list_remove_pattern (l, pattern, patspec, t[0], quoted);
3018 ind = array_expand_index (t, len);
3021 report_error ("%s: bad array subscript", aspec);
3023 return ((char *)NULL);
3025 if (array_p (var) == 0 && ind != 0)
3026 return ((char *)NULL);
3028 t = array_p (var) ? array_reference (array_cell (var), ind) : value_cell (var);
3029 ret = remove_pattern (t, pattern, patspec);
3031 ret = remove_pattern (aval, pattern, patspec);
3035 t = quote_escapes (ret);
3046 valid_array_reference (name)
3052 t = strchr (name, '[');
3056 r = legal_identifier (name);
3060 /* Check for a properly-terminated non-blank subscript. */
3061 len = skipsubscript (t, 0);
3062 if (t[len] != ']' || len == 1)
3064 for (r = 1; r < len; r++)
3065 if (whitespace (t[r]) == 0)
3072 /* Expand the array index beginning at S and extending LEN characters. */
3074 array_expand_index (s, len)
3081 exp = xmalloc (len);
3082 strncpy (exp, s, len - 1);
3083 exp[len - 1] = '\0';
3084 t = maybe_expand_string (exp, 0, expand_string);
3085 this_command_name = (char *)NULL;
3086 val = evalexp (t, &expok);
3090 jump_to_top_level (DISCARD);
3094 /* Return the variable specified by S without any subscript. If non-null,
3095 return the index of the start of the subscript in *SUBP. If non-null,
3096 the length of the subscript is returned in *LENP. */
3098 array_variable_part (s, subp, lenp)
3106 t = strchr (s, '[');
3108 ni = skipsubscript (s, ind);
3109 if (ni <= ind + 1 || s[ni] != ']')
3111 report_error ("%s: bad array subscript", s);
3112 return ((SHELL_VAR *)NULL);
3116 var = find_variable (s);
3127 array_value_internal (s, quoted, allow_all)
3129 int quoted, allow_all;
3136 var = array_variable_part (s, &t, &len);
3139 return (char *)NULL;
3141 if (ALL_ELEMENT_SUB (t[0]) && t[1] == ']')
3143 if (array_p (var) == 0 || allow_all == 0)
3145 report_error ("%s: bad array subscript", s);
3146 return ((char *)NULL);
3148 l = array_to_word_list (array_cell (var));
3149 if (l == (WORD_LIST *)NULL)
3150 return ((char *) NULL);
3152 if (t[0] == '*') /* ${name[*]} */
3153 retval = (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? string_list_dollar_star (l) : string_list (l);
3154 else /* ${name[@]} */
3155 retval = string_list ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? quote_list (l) : l);
3161 ind = array_expand_index (t, len);
3164 report_error ("%s: bad array subscript", var->name);
3165 return ((char *)NULL);
3167 if (array_p (var) == 0)
3168 return (ind == 0 ? savestring (value_cell (var)) : (char *)NULL);
3169 retval = array_reference (array_cell (var), ind);
3171 retval = quote_escapes (retval);
3178 array_value (s, quoted)
3182 return (array_value_internal (s, quoted, 1));
3185 /* Return the value of the array indexing expression S as a single string.
3186 If ALLOW_ALL is 0, do not allow `@' and `*' subscripts. This is used
3187 by other parts of the shell such as the arithmetic expression evaluator
3190 get_array_value (s, allow_all)
3194 return (array_value_internal (s, 0, allow_all));
3198 array_length_reference (s)
3206 var = array_variable_part (s, &t, &len);
3208 /* If unbound variables should generate an error, report one and return
3210 if ((var == 0 || array_p (var) == 0) && unbound_vars_is_error)
3214 report_error ("%s: unbound variable", s);
3220 else if (array_p (var) == 0)
3223 array = array_cell (var);
3225 if (ALL_ELEMENT_SUB (t[0]) && t[1] == ']')
3226 return (array_num_elements (array));
3228 ind = array_expand_index (t, len);
3231 report_error ("%s: bad array subscript", t);
3234 t = array_reference (array, ind);
3239 #endif /* ARRAY_VARS */
3242 valid_brace_expansion_word (name, var_is_special)
3246 if (digit (*name) && all_digits (name))
3248 else if (var_is_special)
3250 #if defined (ARRAY_VARS)
3251 else if (valid_array_reference (name))
3253 #endif /* ARRAY_VARS */
3254 else if (legal_identifier (name))
3260 /* Parameter expand NAME, and return a new string which is the expansion,
3261 or NULL if there was no expansion.
3262 VAR_IS_SPECIAL is non-zero if NAME is one of the special variables in
3263 the shell, e.g., "@", "$", "*", etc. QUOTED, if non-zero, means that
3264 NAME was found inside of a double-quoted expression. */
3266 parameter_brace_expand_word (name, var_is_special, quoted)
3268 int var_is_special, quoted;
3275 /* Handle multiple digit arguments, as in ${11}. */
3278 arg_index = atoi (name);
3279 temp = get_dollar_var_value (arg_index);
3281 else if (var_is_special) /* ${@} */
3283 tt = xmalloc (2 + strlen (name));
3285 strcpy (tt + 1, name);
3286 l = expand_string_leave_quoted (tt, quoted);
3288 temp = string_list (l);
3291 #if defined (ARRAY_VARS)
3292 else if (valid_array_reference (name))
3294 temp = array_value (name, quoted);
3297 else if (var = find_variable (name))
3299 if (var && invisible_p (var) == 0)
3301 #if defined (ARRAY_VARS)
3302 temp = array_p (var) ? array_reference (array_cell (var), 0) : value_cell (var);
3304 temp = value_cell (var);
3308 temp = quote_escapes (temp);
3311 temp = (char *)NULL;
3314 temp = (char *)NULL;
3319 /* Expand an indirect reference to a variable: ${!NAME} expands to the
3320 value of the variable whose name is the value of NAME. */
3322 parameter_brace_expand_indir (name, var_is_special, quoted)
3324 int var_is_special, quoted;
3328 t = parameter_brace_expand_word (name, var_is_special, quoted);
3331 temp = parameter_brace_expand_word (t, t[0] == '@' && t[1] == '\0', quoted);
3336 /* Expand the right side of a parameter expansion of the form ${NAMEcVALUE},
3337 depending on the value of C, the separating character. C can be one of
3338 "-", "+", or "=". QUOTED is true if the entire brace expression occurs
3339 between double quotes. */
3341 parameter_brace_expand_rhs (name, value, c, quoted, qdollaratp, hasdollarat)
3343 int c, quoted, *qdollaratp, *hasdollarat;
3346 char *t, *t1, *temp;
3349 temp = (*value == '~' || (strchr (value, '~') && unquoted_substring ("=~", value)))
3350 ? bash_tilde_expand (value)
3351 : savestring (value);
3353 /* If the entire expression is between double quotes, we want to treat
3354 the value as a double-quoted string, with the exception that we strip
3355 embedded unescaped double quotes. */
3356 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && *temp)
3359 t = string_extract_double_quoted (temp, &hasdol, 1);
3365 /* XXX was 0 not quoted */
3366 l = *temp ? expand_string_for_rhs (temp, quoted, &hasdol, (int *)NULL)
3369 *hasdollarat = hasdol || (l && l->next);
3373 /* The expansion of TEMP returned something. We need to treat things
3374 slightly differently if HASDOL is non-zero. */
3375 temp = string_list (l);
3376 /* If l->next is not null, we know that TEMP contained "$@", since that
3377 is the only expansion that creates more than one word. */
3378 if ((hasdol && quoted) || l->next)
3382 else if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && hasdol)
3384 /* The brace expansion occurred between double quotes and there was
3385 a $@ in TEMP. It does not matter if the $@ is quoted, as long as
3386 it does not expand to anything. In this case, we want to return
3387 a quoted empty string. */
3393 temp = (char *)NULL;
3395 if (c == '-' || c == '+')
3399 t = temp ? savestring (temp) : savestring ("");
3400 t1 = dequote_string (t);
3402 bind_variable (name, t1);
3407 /* Deal with the right hand side of a ${name:?value} expansion in the case
3408 that NAME is null or not set. If VALUE is non-null it is expanded and
3409 used as the error message to print, otherwise a standard message is
3412 parameter_brace_expand_error (name, value)
3418 if (value && *value)
3420 l = expand_string (value, 0);
3421 temp = string_list (l);
3422 report_error ("%s: %s", name, temp ? temp : ""); /* XXX was value not "" */
3427 report_error ("%s: parameter null or not set", name);
3429 /* Free the data we have allocated during this expansion, since we
3430 are about to longjmp out. */
3435 /* Return 1 if NAME is something for which parameter_brace_expand_length is
3438 valid_length_expression (name)
3441 return (!name[1] || /* ${#} */
3442 ((name[1] == '@' || name[1] == '*') && !name[2]) || /* ${#@}, ${#*} */
3443 (digit (name[1]) && all_digits (name + 1)) || /* ${#11} */
3444 #if defined (ARRAY_VARS)
3445 valid_array_reference (name + 1) || /* ${#a[7]} */
3447 legal_identifier (name + 1)); /* ${#PS1} */
3450 /* Handle the parameter brace expansion that requires us to return the
3451 length of a parameter. */
3453 parameter_brace_expand_length (name)
3459 #if defined (ARRAY_VARS)
3463 if (name[1] == '\0') /* ${#} */
3464 number = number_of_args ();
3465 #if defined (ARRAY_VARS)
3466 else if (valid_array_reference (name + 1))
3467 number = array_length_reference (name + 1);
3468 #endif /* ARRAY_VARS */
3469 else if (name[1] != '*' && name[1] != '@')
3473 if (digit (name[1])) /* ${#1} */
3475 t = get_dollar_var_value (atoi (name + 1));
3476 number = STRLEN (t);
3479 #if defined (ARRAY_VARS)
3480 else if ((var = find_variable (name + 1)) && array_p (var))
3482 t = array_reference (array_cell (var), 0);
3483 number = STRLEN (t);
3488 newname = savestring (name);
3490 list = expand_string (newname, Q_DOUBLE_QUOTES);
3491 t = list ? string_list (list) : (char *)NULL;
3494 dispose_words (list);
3496 number = STRLEN (t);
3500 else /* ${#@} and ${#*} */
3501 number = number_of_args ();
3506 /* Verify and limit the start and end of the desired substring. If
3507 VTYPE == 0, a regular shell variable is being used; if it is 1,
3508 then the positional paramters are being used; if it is 2, then
3509 VALUE is really a pointer to an array variable that should be used. */
3511 verify_substring_values (value, substr, vtype, e1p, e2p)
3512 char *value, *substr;
3513 int vtype, *e1p, *e2p;
3517 #if defined (ARRAY_VARS)
3521 t = strchr (substr, ':');
3524 temp1 = maybe_expand_string (substr, Q_DOUBLE_QUOTES, expand_string);
3525 *e1p = evalexp (temp1, &expok);
3533 case VT_ARRAYMEMBER:
3534 len = strlen (value);
3537 len = number_of_args () + 1;
3539 #if defined (ARRAY_VARS)
3542 len = array_num_elements (a) + 1;
3547 if (*e1p < 0) /* negative offsets count from end */
3550 if (*e1p >= len || *e1p < 0)
3556 temp1 = maybe_expand_string (t, Q_DOUBLE_QUOTES, expand_string);
3558 *e2p = evalexp (temp1, &expok);
3564 internal_error ("%s: substring expression < 0", t);
3567 *e2p += *e1p; /* want E2 chars starting at E1 */
3577 /* Return a string containing the positional parameters from START to
3578 END, inclusive. If STRING[0] == '*', we obey the rules for $*,
3579 which only makes a difference if QUOTED is non-zero. */
3581 pos_params (string, start, end, quoted)
3583 int start, end, quoted;
3585 WORD_LIST *save, *params, *h, *t;
3589 save = params = list_rest_of_args ();
3591 return ((char *)NULL);
3593 for (i = 1; params && i < start; i++)
3594 params = params->next;
3596 return ((char *)NULL);
3597 for (h = t = params; params && i < end; i++)
3600 params = params->next;
3603 t->next = (WORD_LIST *)NULL;
3604 if (string[0] == '*')
3605 ret = (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? string_list_dollar_star (h) : string_list (h);
3607 ret = string_list ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? quote_list (h) : h);
3610 dispose_words (save);
3614 /* Return the type of variable specified by VARNAME (simple variable,
3615 positional param, or array variable. Also return the value specified
3616 by VARNAME (value of a variable or a reference to an array element). */
3618 get_var_and_type (varname, value, varp, valp)
3619 char *varname, *value;
3625 #if defined (ARRAY_VARS)
3629 vtype = (varname[0] == '@' || varname[0] == '*') && varname[1] == '\0'; /* VT_POSPARMS */
3630 *varp = (SHELL_VAR *)NULL;
3632 #if defined (ARRAY_VARS)
3633 if (valid_array_reference (varname))
3635 v = array_variable_part (varname, &temp, (int *)0);
3636 if (v && array_p (v))
3638 if ((temp[0] == '@' || temp[0] == '*') && temp[1] == ']')
3640 vtype = VT_ARRAYVAR;
3641 *valp = (char *)array_cell (v);
3645 vtype = VT_ARRAYMEMBER;
3646 *valp = array_value (varname, 1);
3653 else if ((v = find_variable (varname)) && array_p (v))
3655 vtype = VT_VARIABLE;
3657 *valp = array_reference (array_cell (v), 0);
3666 /* Process a variable substring expansion: ${name:e1[:e2]}. If VARNAME
3667 is `@', use the positional parameters; otherwise, use the value of
3668 VARNAME. If VARNAME is an array variable, use the array elements. */
3671 parameter_brace_substring (varname, value, substr, quoted)
3672 char *varname, *value, *substr;
3680 return ((char *)NULL);
3682 this_command_name = varname;
3684 vtype = get_var_and_type (varname, value, &v, &val);
3686 return ((char *)NULL);
3688 if (verify_substring_values (val, substr, vtype, &e1, &e2) == 0)
3690 if (val && vtype == VT_ARRAYMEMBER)
3692 return (&expand_param_error);
3698 case VT_ARRAYMEMBER:
3699 temp = quoted ? quoted_substring (value, e1, e2) : substring (value, e1, e2);
3702 temp = pos_params (varname, e1, e2, quoted);
3704 #if defined (ARRAY_VARS)
3706 temp = array_subrange (array_cell (v), e1, e2, quoted);
3715 pat_subst (string, pat, rep, mflags)
3716 char *string, *pat, *rep;
3719 char *ret, *s, *e, *str;
3720 int rsize, rptr, l, replen, mtype;
3722 ret = xmalloc (rsize = 64);
3725 mtype = mflags & MATCH_TYPEMASK;
3727 for (replen = STRLEN (rep), rptr = 0, str = string;;)
3729 if (match_pattern (str, pat, mtype, &s, &e) == 0)
3732 RESIZE_MALLOCED_BUFFER (ret, rptr, (l + replen), rsize, 64);
3734 /* OK, now copy the leading unmatched portion of the string (from
3735 str to s) to ret starting at rptr (the current offset). Then copy
3736 the replacement string at ret + rptr + (s - str). Increment
3737 rptr (if necessary) and str and go on. */
3740 strncpy (ret + rptr, str, l);
3745 strncpy (ret + rptr, rep, replen);
3748 str = e; /* e == end of match */
3749 if (((mflags & MATCH_GLOBREP) == 0) || mtype != MATCH_ANY)
3753 /* Now copy the unmatched portion of the input string */
3756 RESIZE_MALLOCED_BUFFER (ret, rptr, STRLEN(str) + 1, rsize, 64);
3757 strcpy (ret + rptr, str);
3765 /* Do pattern match and replacement on the positional parameters. */
3767 pos_params_pat_subst (string, pat, rep, mflags)
3768 char *string, *pat, *rep;
3771 WORD_LIST *save, *params;
3775 save = params = list_rest_of_args ();
3777 return ((char *)NULL);
3779 for ( ; params; params = params->next)
3781 ret = pat_subst (params->word->word, pat, rep, mflags);
3782 w = make_bare_word (ret);
3783 dispose_word (params->word);
3788 ret = string_list ((mflags & MATCH_QUOTED) ? quote_list (save) : save);
3789 dispose_words (save);
3795 parameter_brace_patsub (varname, value, patsub, quoted)
3796 char *varname, *value, *patsub;
3800 char *val, *temp, *pat, *rep, *p;
3804 return ((char *)NULL);
3806 this_command_name = varname;
3808 vtype = get_var_and_type (varname, value, &v, &val);
3810 return ((char *)NULL);
3815 mflags |= MATCH_GLOBREP;
3819 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
3820 mflags |= MATCH_QUOTED;
3822 if (rep = quoted_strchr (patsub, '/', ST_BACKSL))
3827 if (rep && *rep == '\0')
3830 /* Expand PAT and REP for command, variable and parameter, arithmetic,
3831 and process substitution. Also perform quote removal. Do not
3832 perform word splitting or filename generation. */
3833 pat = maybe_expand_string (patsub, quoted, expand_string_unsplit);
3836 if ((mflags & MATCH_QUOTED) == 0)
3837 rep = maybe_expand_string (rep, quoted, expand_string_unsplit);
3839 rep = expand_string_to_string (rep, quoted, expand_string_unsplit);
3843 if (pat && pat[0] == '#')
3845 mflags |= MATCH_BEG;
3848 else if (pat && pat[0] == '%')
3850 mflags |= MATCH_END;
3854 mflags |= MATCH_ANY;
3856 /* OK, we now want to substitute REP for PAT in VAL. If GLOBAL is 1,
3857 the substitution is done everywhere, otherwise only the first
3858 occurrence of PAT is replaced. */
3862 case VT_ARRAYMEMBER:
3863 temp = pat_subst (val, p, rep, mflags);
3866 temp = pos_params_pat_subst (val, p, rep, mflags);
3868 #if defined (ARRAY_VARS)
3870 temp = array_pat_subst (array_cell (v), p, rep, mflags);
3875 if (val && v && array_p (v) && vtype == VT_ARRAYMEMBER)
3884 /* ${[#][!]name[[:]#[#]%[%]-=?+[word][:e1[:e2]]]} */
3886 parameter_brace_expand (string, indexp, quoted, quoted_dollar_atp, contains_dollar_at)
3888 int *indexp, quoted, *quoted_dollar_atp, *contains_dollar_at;
3890 int check_nullness, var_is_set, var_is_null, var_is_special;
3891 int want_substring, want_indir, want_patsub;
3892 char *name, *value, *temp, *temp1;
3893 int t_index, sindex, c, number;
3897 name = string_extract (string, &t_index, "#%:-=?+/}", 1);
3898 value = (char *)NULL;
3899 var_is_set = var_is_null = var_is_special = check_nullness = 0;
3900 want_substring = want_indir = want_patsub = 0;
3902 /* If the name really consists of a special variable, then
3903 make sure that we have the entire name. Handle indirect
3904 references to special variables here, too. */
3905 if ((sindex == t_index ||
3906 ((sindex == t_index - 1) && string[sindex] == '!')) &&
3907 (string[t_index] == '-' ||
3908 string[t_index] == '?' ||
3909 string[t_index] == '#'))
3913 temp1 = string_extract (string, &t_index, "#%:-=?+/}", 0);
3914 name = xmalloc (3 + (strlen (temp1)));
3915 *name = string[sindex];
3916 if (string[sindex] == '!')
3918 /* indirect ref. of special variable */
3919 name[1] = string[sindex + 1];
3920 strcpy (name + 2, temp1);
3923 strcpy (name + 1, temp1);
3928 /* Find out what character ended the variable name. Then
3929 do the appropriate thing. */
3930 if (c = string[sindex])
3933 /* If c is followed by one of the valid parameter expansion
3934 characters, move past it as normal. If not, assume that
3935 a substring specification is being given, and do not move
3937 if (c == ':' && member (string[sindex], "-=?+"))
3940 if (c = string[sindex])
3948 want_indir = *name == '!';
3950 /* Determine the value of this variable. */
3952 /* Check for special variables, directly and indirectly
3954 if ((digit (*name) && all_digits (name)) ||
3955 (name[1] == '\0' && member (*name, "#-?$!@*")) ||
3956 (want_indir && name[2] == '\0' && member (name[1], "#-?$!@*")))
3959 /* Check for special expansion things. */
3960 if (*name == '#') /* length of a parameter */
3962 /* Take the lengths of some of the shell's special
3964 if (string[sindex] == '}' && name[1] == '\0' &&
3965 check_nullness == 0 && member (c, "-?$!#"))
3971 temp1 = which_set_flags ();
3974 temp1 = itos (last_command_exit_value);
3977 temp1 = itos (dollar_dollar_pid);
3980 if (last_asynchronous_pid == NO_PID)
3981 temp1 = (char *)NULL;
3983 temp1 = itos ((int)last_asynchronous_pid);
3986 temp1 = itos (number_of_args ());
3989 number = STRLEN (temp1);
3991 *indexp = ++sindex; /* { string[sindex] == '}' */
3992 return (itos (number));
3995 /* Don't allow things like ${#:-foo} to go by; they are
3996 errors. If we are not pointing at the character just
3997 after the closing brace, then we haven't gotten all of
3998 the name. Since it begins with a special character,
3999 this is a bad substitution. Explicitly check for ${#:},
4000 which the rules do not catch. Also check NAME for
4001 validity before trying to go on. */
4002 if (string[sindex - 1] != '}' ||
4003 member (c, "?-=+") ||
4004 (name[1] == '\0' && c == '}' && check_nullness) ||
4005 (valid_length_expression (name) == 0))
4007 temp = (char *)NULL;
4008 goto bad_substitution;
4011 number = parameter_brace_expand_length (name);
4015 return ((number < 0) ? &expand_param_error : itos (number));
4018 /* ${@} is identical to $@. */
4019 if (name[0] == '@' && name[1] == '\0')
4021 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
4022 *quoted_dollar_atp = 1;
4024 if (contains_dollar_at)
4025 *contains_dollar_at = 1;
4028 /* Make sure that NAME is valid before trying to go on. */
4029 if (valid_brace_expansion_word (want_indir ? name + 1 : name,
4030 var_is_special) == 0)
4032 temp = (char *)NULL;
4033 goto bad_substitution;
4037 temp = parameter_brace_expand_indir (name + 1, var_is_special, quoted);
4039 temp = parameter_brace_expand_word (name, var_is_special, quoted);
4041 #if defined (ARRAY_VARS)
4042 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && valid_array_reference (name))
4044 temp1 = strchr (name, '[');
4045 if (temp1 && temp1[1] == '@' && temp1[2] == ']')
4047 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
4048 *quoted_dollar_atp = 1;
4049 if (contains_dollar_at)
4050 *contains_dollar_at = 1;
4055 var_is_set = temp != (char *)0;
4056 var_is_null = check_nullness && (var_is_set == 0 || *temp == 0);
4058 /* Get the rest of the stuff inside the braces. */
4061 /* Extract the contents of the ${ ... } expansion
4062 according to the Posix.2 rules. */
4063 value = extract_dollar_brace_string (string, &sindex, quoted);
4065 if (string[sindex] == '}')
4068 goto bad_substitution;
4071 value = (char *)NULL;
4075 /* If this is a substring spec, process it and add the result. */
4078 temp1 = parameter_brace_substring (name, temp, value, quoted);
4084 else if (want_patsub)
4086 temp1 = parameter_brace_patsub (name, temp, value, quoted);
4093 /* Do the right thing based on which character ended the variable name. */
4099 report_error ("%s: bad substitution", string ? string : "??");
4103 return &expand_param_error;
4107 if (var_is_set == 0 && unbound_vars_is_error)
4109 report_error ("%s: unbound variable", name);
4113 last_command_exit_value = EXECUTION_FAILURE;
4114 return (interactive_shell ? &expand_param_error : &expand_param_fatal);
4118 case '#': /* ${param#[#]pattern} */
4119 case '%': /* ${param%[%]pattern} */
4120 if (value == 0 || *value == '\0' || temp == 0 || *temp == '\0')
4125 if ((name[0] == '@' || name[0] == '*') && name[1] == '\0')
4126 temp1 = parameter_list_remove_pattern (value, name[0], c, quoted);
4127 #if defined (ARRAY_VARS)
4128 else if (valid_array_reference (name))
4129 temp1 = array_remove_pattern (value, name, temp, c, quoted);
4132 temp1 = parameter_brace_remove_pattern (value, temp, c, quoted);
4142 if (var_is_set && var_is_null == 0)
4144 /* We don't want the value of the named variable for
4145 anything, just the value of the right hand side. */
4151 temp = parameter_brace_expand_rhs (name, value, c,
4154 contains_dollar_at);
4158 temp = (char *)NULL;
4164 /* Otherwise do nothing; just use the value in TEMP. */
4166 else /* VAR not set or VAR is NULL. */
4169 temp = (char *)NULL;
4170 if (c == '=' && var_is_special)
4172 report_error ("$%s: cannot assign in this way", name);
4175 return &expand_param_error;
4179 parameter_brace_expand_error (name, value);
4180 return (interactive ? &expand_param_error : &expand_param_fatal);
4183 temp = parameter_brace_expand_rhs (name, value, c, quoted,
4185 contains_dollar_at);
4194 /* Make a word list which is the parameter and variable expansion,
4195 command substitution, arithmetic substitution, and quote removed
4196 expansion of WORD. Return a pointer to a WORD_LIST which is the
4197 result of the expansion. If WORD contains a null word, the word
4198 list returned is also null.
4200 QUOTED contains flag values defined in shell.h.
4202 CONTAINS_DOLLAR_AT and EXPANDED_SOMETHING are return values; when non-null
4203 they point to an integer value which receives information about expansion.
4204 CONTAINS_DOLLAR_AT gets non-zero if WORD contained "$@", else zero.
4205 EXPANDED_SOMETHING get non-zero if WORD contained any parameter expansions,
4208 This only does word splitting in the case of $@ expansion. In that
4209 case, we split on ' '. */
4211 /* Values for the local variable quoted_state. */
4213 #define PARTIALLY_QUOTED 1
4214 #define WHOLLY_QUOTED 2
4217 expand_word_internal (word, quoted, contains_dollar_at, expanded_something)
4220 int *contains_dollar_at;
4221 int *expanded_something;
4227 /* The intermediate string that we build while expanding. */
4230 /* The current size of the above object. */
4233 /* Index into ISTRING. */
4236 /* Temporary string storage. */
4239 /* The text of WORD. */
4240 register char *string;
4242 /* The index into STRING. */
4245 /* This gets 1 if we see a $@ while quoted. */
4246 int quoted_dollar_at;
4248 /* One of UNQUOTED, PARTIALLY_QUOTED, or WHOLLY_QUOTED, depending on
4249 whether WORD contains no quoting characters, a partially quoted
4250 string (e.g., "xx"ab), or is fully quoted (e.g., "xxab"). */
4253 int had_quoted_null;
4257 register int c; /* Current character. */
4258 int number; /* Temporary number value. */
4259 int t_index; /* For calls to string_extract_xxx. */
4261 istring = xmalloc (istring_size = DEFAULT_INITIAL_ARRAY_SIZE);
4262 istring[istring_index = 0] = '\0';
4264 quoted_dollar_at = had_quoted_null = 0;
4265 quoted_state = UNQUOTED;
4267 string = word->word;
4269 goto finished_with_string;
4271 if (contains_dollar_at)
4272 *contains_dollar_at = 0;
4274 /* Begin the expansion. */
4280 /* Case on toplevel character. */
4284 goto finished_with_string;
4289 temp[1] = c = string[++sindex];
4297 #if defined (PROCESS_SUBSTITUTION)
4298 /* Process substitution. */
4302 if (string[++sindex] != '(' || (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || posixly_correct)
4308 t_index = sindex + 1; /* skip past both '<' and '(' */
4310 temp1 = extract_process_subst (string, (c == '<') ? "<(" : ">(", &t_index);
4313 /* If the process substitution specification is `<()', we want to
4314 open the pipe for writing in the child and produce output; if
4315 it is `>()', we want to open the pipe for reading in the child
4316 and consume input. */
4317 temp = temp1 ? process_substitute (temp1, (c == '>')) : (char *)0;
4321 goto dollar_add_string;
4323 #endif /* PROCESS_SUBSTITUTION */
4325 /* See about breaking this into a separate function:
4327 param_expand (string, sindex, quoted, expanded_something,
4328 contains_dollar_at, quoted_dollar_at)
4330 int *sindex, quoted, *expanded_something, *contains_dollar_at;
4331 int *quoted_dollar_at;
4335 if (expanded_something)
4336 *expanded_something = 1;
4338 c = string[++sindex];
4340 /* Do simple cases first. Switch on what follows '$'. */
4354 temp1 = dollar_vars[digit_value (c)];
4355 if (unbound_vars_is_error && temp1 == (char *)NULL)
4357 report_error ("$%c: unbound variable", c);
4360 last_command_exit_value = EXECUTION_FAILURE;
4361 return (interactive_shell ? &expand_word_error : &expand_word_fatal);
4363 temp = temp1 ? savestring (temp1) : (char *)NULL;
4364 goto dollar_add_string;
4366 /* $$ -- pid of the invoking shell. */
4368 number = dollar_dollar_pid;
4371 temp = itos (number);
4373 if (string[sindex]) sindex++;
4375 /* Add TEMP to ISTRING. */
4379 istring = sub_append_string
4380 (temp, istring, &istring_index, &istring_size);
4386 /* $# -- number of positional parameters. */
4388 number = number_of_args ();
4391 /* $? -- return value of the last synchronous command. */
4393 number = last_command_exit_value;
4396 /* $- -- flags supplied to the shell on invocation or
4399 temp = which_set_flags ();
4400 goto dollar_add_string;
4402 /* $! -- Pid of the last asynchronous command. */
4404 number = (int)last_asynchronous_pid;
4406 /* If no asynchronous pids have been created, expand
4408 if (number == (int)NO_PID)
4412 if (expanded_something)
4413 *expanded_something = 0;
4418 /* The only difference between this and $@ is when the
4420 case '*': /* `$*' */
4421 temp = string_rest_of_args (quoted);
4423 /* If there are no command-line arguments, this should just
4424 disappear if there are other characters in the expansion,
4425 even if it's quoted. */
4426 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && temp && *temp == '\0')
4429 temp = (char *)NULL;
4431 /* In the case of a quoted string, quote the entire arg-list.
4432 "$1 $2 $3". Otherwise quote the special escape characters. */
4436 temp = (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
4437 ? quote_string (temp)
4438 : quote_escapes (temp);
4441 goto dollar_add_string;
4443 /* When we have "$@" what we want is "$1" "$2" "$3" ... This
4444 means that we have to turn quoting off after we split into
4445 the individually quoted arguments so that the final split
4446 on the first character of $IFS is still done. */
4447 case '@': /* `$@' */
4448 list = list_rest_of_args ();
4450 /* We want to flag the fact that we saw this. We can't turn
4451 off quoting entirely, because other characters in the
4452 string might need it (consider "\"$@\""), but we need some
4453 way to signal that the final split on the first character
4454 of $IFS should be done, even though QUOTED is 1. */
4455 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
4456 quoted_dollar_at = 1;
4457 if (contains_dollar_at)
4458 *contains_dollar_at = 1;
4459 temp = string_list (((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && list) ? quote_list (list) : list);
4460 /* If the expansion is not quoted, protect any special escape
4461 characters in the expansion by quoting them. */
4462 if (temp && quoted == 0)
4465 temp = quote_escapes (temp);
4468 dispose_words (list);
4469 goto dollar_add_string;
4472 temp = parameter_brace_expand (string, &sindex, quoted,
4474 contains_dollar_at);
4475 if (temp == &expand_param_error || temp == &expand_param_fatal)
4479 return (temp == &expand_param_error) ? &expand_word_error
4480 : &expand_word_fatal;
4483 /* quoted nulls should be removed if there is anything else
4485 /* Note that we saw the quoted null so we can add one back at
4486 the end of this function if there are no other characters
4487 in the string, discard TEMP, and go on. */
4488 if (temp && QUOTED_NULL (temp))
4490 had_quoted_null = 1;
4498 /* Do command or arithmetic substitution. */
4500 /* We have to extract the contents of this paren substitution. */
4501 t_index = sindex + 1;
4502 temp = extract_command_subst (string, &t_index);
4505 /* For Posix.2-style `$(( ))' arithmetic substitution,
4506 extract the expression and pass it to the evaluator. */
4507 if (temp && *temp == '(')
4510 t_index = strlen (temp1) - 1;
4512 if (temp1[t_index] != ')')
4515 report_error ("%s: bad arithmetic substitution", temp);
4519 return (&expand_word_error);
4525 /* Cut off ending `)' */
4526 temp1[t_index] = '\0';
4528 /* Expand variables found inside the expression. */
4529 temp1 = maybe_expand_string (temp1, Q_DOUBLE_QUOTES, expand_string);
4531 /* No error messages. */
4532 this_command_name = (char *)NULL;
4533 number = evalexp (temp1, &expok);
4540 return (&expand_word_error);
4546 temp1 = command_substitute (temp, quoted);
4549 goto dollar_add_string;
4551 /* Do straight arithmetic substitution. */
4553 /* We have to extract the contents of this
4554 arithmetic substitution. */
4555 t_index = sindex + 1;
4556 temp = extract_arithmetic_subst (string, &t_index);
4559 /* Do initial variable expansion. */
4560 temp1 = maybe_expand_string (temp, Q_DOUBLE_QUOTES, expand_string);
4562 /* No error messages. */
4563 this_command_name = (char *)NULL;
4564 number = evalexp (temp1, &expok);
4571 return (&expand_word_error);
4576 /* Find the variable in VARIABLE_LIST. */
4577 temp = (char *)NULL;
4579 for (t_index = sindex;
4580 (c = string[sindex]) && legal_variable_char (c);
4582 temp1 = substring (string, t_index, sindex);
4584 /* If this isn't a variable name, then just output the `$'. */
4585 if (temp1 == 0 || *temp1 == '\0')
4591 if (expanded_something)
4592 *expanded_something = 0;
4596 /* If the variable exists, return its value cell. */
4597 var = find_variable (temp1);
4599 if (var && invisible_p (var) == 0 && value_cell (var))
4601 #if defined (ARRAY_VARS)
4604 temp = array_reference (array_cell (var), 0);
4606 temp = quote_escapes (temp);
4610 temp = quote_escapes (value_cell (var));
4615 temp = (char *)NULL;
4617 if (unbound_vars_is_error)
4618 report_error ("%s: unbound variable", temp1);
4627 last_command_exit_value = EXECUTION_FAILURE;
4629 return ((unbound_vars_is_error && interactive_shell == 0)
4630 ? &expand_word_fatal
4631 : &expand_word_error);
4633 break; /* End case '$': */
4635 case '`': /* Backquoted command substitution. */
4639 if (expanded_something)
4640 *expanded_something = 1;
4642 temp = string_extract (string, &sindex, "`", 0);
4643 de_backslash (temp);
4644 temp1 = command_substitute (temp, quoted);
4647 goto dollar_add_string;
4651 if (string[sindex + 1] == '\n')
4657 c = string[++sindex];
4659 if (quoted & Q_HERE_DOCUMENT)
4660 temp1 = slashify_in_here_document;
4661 else if (quoted & Q_DOUBLE_QUOTES)
4662 temp1 = slashify_in_quotes;
4666 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && member (c, temp1) == 0)
4669 temp[0] = '\\'; temp[1] = c; temp[2] = '\0';
4672 /* This character is quoted, so add it in quoted mode. */
4673 temp = make_quoted_char (c);
4680 if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT|Q_NOQUOTE))
4684 temp = string_extract_double_quoted (string, &sindex, 0);
4686 /* If the quotes surrounded the entire string, then the
4687 whole word was quoted. */
4688 quoted_state = (t_index == 1 && string[sindex] == '\0')
4696 tword = make_word (temp); /* XXX */
4698 temp = (char *)NULL;
4700 list = expand_word_internal (tword, Q_DOUBLE_QUOTES, &dollar_at_flag, (int *)NULL);
4702 if (list == &expand_word_error || list == &expand_word_fatal)
4706 /* expand_word_internal has already freed temp_word->word
4707 for us because of the way it prints error messages. */
4708 tword->word = (char *)NULL;
4709 dispose_word (tword);
4713 dispose_word (tword);
4715 /* "$@" (a double-quoted dollar-at) expands into nothing,
4716 not even a NULL word, when there are no positional
4718 if (list == 0 && dollar_at_flag)
4724 /* If we get "$@", we know we have expanded something, so we
4725 need to remember it for the final split on $IFS. This is
4726 a special case; it's the only case where a quoted string
4727 can expand into more than one word. It's going to come back
4728 from the above call to expand_word_internal as a list with
4729 a single word, in which all characters are quoted and
4730 separated by blanks. What we want to do is to turn it back
4731 into a list for the next piece of code. */
4733 dequote_list (list);
4738 if (contains_dollar_at)
4739 *contains_dollar_at = 1;
4740 if (expanded_something)
4741 *expanded_something = 1;
4746 /* What we have is "". This is a minor optimization. */
4748 list = (WORD_LIST *)NULL;
4751 /* The code above *might* return a list (consider the case of "$@",
4752 where it returns "$1", "$2", etc.). We can't throw away the
4753 rest of the list, and we have to make sure each word gets added
4754 as quoted. We test on tresult->next: if it is non-NULL, we
4755 quote the whole list, save it to a string with string_list, and
4756 add that string. We don't need to quote the results of this
4757 (and it would be wrong, since that would quote the separators
4758 as well), so we go directly to add_string. */
4763 temp = string_list (quote_list (list));
4764 dispose_words (list);
4769 temp = savestring (list->word->word);
4770 dispose_words (list);
4774 temp = (char *)NULL;
4776 /* We do not want to add quoted nulls to strings that are only
4777 partially quoted; we can throw them away. */
4778 if (temp == 0 && quoted_state == PARTIALLY_QUOTED)
4789 temp = quote_string (temp);
4803 if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT|Q_NOQUOTE))
4807 temp = string_extract_single_quoted (string, &sindex);
4809 /* If the entire STRING was surrounded by single quotes,
4810 then the string is wholly quoted. */
4811 quoted_state = (t_index == 1 && string[sindex] == '\0')
4815 /* If all we had was '', it is a null expansion. */
4819 temp = (char *)NULL;
4822 remove_quoted_escapes (temp);
4824 /* We do not want to add quoted nulls to strings that are only
4825 partially quoted; such nulls are discarded. */
4826 if (temp == 0 && (quoted_state == PARTIALLY_QUOTED))
4829 goto add_quoted_string;
4833 /* This is the fix for " $@ " */
4834 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
4836 temp = make_quoted_char (c);
4837 goto dollar_add_string;
4841 RESIZE_MALLOCED_BUFFER (istring, istring_index, 1, istring_size,
4842 DEFAULT_ARRAY_SIZE);
4843 istring[istring_index++] = c;
4844 istring[istring_index] = '\0';
4846 /* Next character. */
4851 finished_with_string:
4852 /* OK, we're ready to return. If we have a quoted string, and
4853 quoted_dollar_at is not set, we do no splitting at all; otherwise
4854 we split on ' '. The routines that call this will handle what to
4855 do if nothing has been expanded. */
4857 /* Partially and wholly quoted strings which expand to the empty
4858 string are retained as an empty arguments. Unquoted strings
4859 which expand to the empty string are discarded. The single
4860 exception is the case of expanding "$@" when there are no
4861 positional parameters. In that case, we discard the expansion. */
4863 /* Because of how the code that handles "" and '' in partially
4864 quoted strings works, we need to make ISTRING into a QUOTED_NULL
4865 if we saw quoting characters, but the expansion was empty.
4866 "" and '' are tossed away before we get to this point when
4867 processing partially quoted strings. This makes "" and $xxx""
4868 equivalent when xxx is unset. We also look to see whether we
4869 saw a quoted null from a ${} expansion and add one back if we
4872 /* If we expand to nothing and there were no single or double quotes
4873 in the word, we throw it away. Otherwise, we return a NULL word.
4874 The single exception is for $@ surrounded by double quotes when
4875 there are no positional parameters. In that case, we also throw
4878 if (*istring == '\0')
4880 if (quoted_dollar_at == 0 && (had_quoted_null || quoted_state == PARTIALLY_QUOTED))
4882 istring[0] = CTLNUL;
4884 tword = make_bare_word (istring);
4885 list = make_word_list (tword, (WORD_LIST *)NULL);
4886 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
4887 tword->flags |= W_QUOTED;
4889 /* According to sh, ksh, and Posix.2, if a word expands into nothing
4890 and a double-quoted "$@" appears anywhere in it, then the entire
4892 else if (quoted_state == UNQUOTED || quoted_dollar_at)
4893 list = (WORD_LIST *)NULL;
4897 tword = make_bare_word (istring);
4898 list = make_word_list (tword, (WORD_LIST *)NULL);
4899 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
4900 tword->flags |= W_QUOTED;
4904 else if (word->flags & W_NOSPLIT)
4906 tword = make_bare_word (istring);
4907 list = make_word_list (tword, (WORD_LIST *)NULL);
4908 if (word->flags & W_ASSIGNMENT)
4909 tword->flags |= W_ASSIGNMENT; /* XXX */
4910 if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
4911 tword->flags |= W_QUOTED;
4917 if (quoted_dollar_at)
4919 var = find_variable ("IFS");
4920 ifs_chars = var ? value_cell (var) : " \t\n";
4923 ifs_chars = (char *)NULL;
4925 /* According to Posix.2, "$@" expands to a single word if
4926 IFS="" and the positional parameters are not empty. */
4927 if (quoted_dollar_at && ifs_chars && *ifs_chars)
4929 list = list_string (istring, " ", 1);
4933 tword = make_bare_word (istring);
4934 list = make_word_list (tword, (WORD_LIST *)NULL);
4935 if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) || (quoted_state == WHOLLY_QUOTED))
4936 tword->flags |= W_QUOTED;
4937 if (word->flags & W_ASSIGNMENT)
4938 tword->flags |= W_ASSIGNMENT;
4946 /* **************************************************************** */
4948 /* Functions for Quote Removal */
4950 /* **************************************************************** */
4952 /* Perform quote removal on STRING. If QUOTED > 0, assume we are obeying the
4953 backslash quoting rules for within double quotes. */
4955 string_quote_removal (string, quoted)
4959 char *r, *result_string, *temp;
4960 int sindex, tindex, c, dquote;
4962 /* The result can be no longer than the original string. */
4963 r = result_string = xmalloc (strlen (string) + 1);
4965 for (dquote = sindex = 0; c = string[sindex];)
4970 c = string[++sindex];
4971 if (((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || dquote) && member (c, slashify_in_quotes) == 0)
4981 if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || dquote)
4987 tindex = sindex + 1;
4988 temp = string_extract_single_quoted (string, &tindex);
4999 dquote = 1 - dquote;
5005 return (result_string);
5010 /* Perform quote removal on word WORD. This allocates and returns a new
5013 word_quote_removal (word, quoted)
5020 t = string_quote_removal (word->word, quoted);
5021 w = make_bare_word (t);
5026 /* Perform quote removal on all words in LIST. If QUOTED is non-zero,
5027 the members of the list are treated as if they are surrounded by
5028 double quotes. Return a new list, or NULL if LIST is NULL. */
5030 word_list_quote_removal (list, quoted)
5034 WORD_LIST *result, *t, *tresult;
5036 for (t = list, result = (WORD_LIST *)NULL; t; t = t->next)
5038 tresult = (WORD_LIST *)xmalloc (sizeof (WORD_LIST));
5039 tresult->word = word_quote_removal (t->word, quoted);
5040 tresult->next = (WORD_LIST *)NULL;
5041 result = (WORD_LIST *) list_append (result, tresult);
5047 /* Return 1 if CHARACTER appears in an unquoted portion of
5048 STRING. Return 0 otherwise. */
5050 unquoted_member (character, string)
5056 for (sindex = 0; c = string[sindex]; )
5074 sindex = skip_single_quoted (string, ++sindex);
5078 sindex = skip_double_quoted (string, ++sindex);
5085 /* Return 1 if SUBSTR appears in an unquoted portion of STRING. */
5087 unquoted_substring (substr, string)
5088 char *substr, *string;
5090 int sindex, c, sublen;
5092 if (substr == 0 || *substr == '\0')
5095 sublen = strlen (substr);
5096 for (sindex = 0; c = string[sindex]; )
5098 if (STREQN (string + sindex, substr, sublen))
5111 sindex = skip_single_quoted (string, ++sindex);
5115 sindex = skip_double_quoted (string, ++sindex);
5126 /*******************************************
5128 * Functions to perform word splitting *
5130 *******************************************/
5132 /* This splits a single word into a WORD LIST on $IFS, but only if the word
5133 is not quoted. list_string () performs quote removal for us, even if we
5134 don't do any splitting. */
5145 ifs = find_variable ("IFS");
5146 /* If IFS is unset, it defaults to " \t\n". */
5147 ifs_chars = ifs ? value_cell (ifs) : " \t\n";
5149 if ((w->flags & W_QUOTED) || !ifs_chars)
5152 result = list_string (w->word, ifs_chars, w->flags & W_QUOTED);
5155 result = (WORD_LIST *)NULL;
5160 /* Perform word splitting on LIST and return the RESULT. It is possible
5161 to return (WORD_LIST *)NULL. */
5163 word_list_split (list)
5166 WORD_LIST *result, *t, *tresult;
5168 for (t = list, result = (WORD_LIST *)NULL; t; t = t->next)
5170 tresult = word_split (t->word);
5171 result = (WORD_LIST *) list_append (result, tresult);
5176 /**************************************************
5178 * Functions to expand an entire WORD_LIST *
5180 **************************************************/
5182 static WORD_LIST *varlist = (WORD_LIST *)NULL;
5184 /* Separate out any initial variable assignments from TLIST. If set -k has
5185 been executed, remove all assignment statements from TLIST. Initial
5186 variable assignments and other environment assignments are placed
5189 separate_out_assignments (tlist)
5192 register WORD_LIST *vp, *lp;
5195 return ((WORD_LIST *)NULL);
5197 varlist = (WORD_LIST *)NULL;
5200 /* Separate out variable assignments at the start of the command.
5201 Loop invariant: vp->next == lp
5203 lp = list of words left after assignment statements skipped
5204 tlist = original list of words
5206 while (lp && (lp->word->flags & W_ASSIGNMENT))
5212 /* If lp != tlist, we have some initial assignment statements. */
5213 /* We make VARLIST point to the list of assignment words and
5214 TLIST point to the remaining words. */
5218 /* ASSERT(vp->next == lp); */
5219 vp->next = (WORD_LIST *)NULL; /* terminate variable list */
5220 tlist = lp; /* remainder of word list */
5223 /* vp == end of variable list */
5224 /* tlist == remainder of original word list without variable assignments */
5226 /* All the words in tlist were assignment statements */
5227 return ((WORD_LIST *)NULL);
5229 /* ASSERT(tlist != NULL); */
5230 /* ASSERT((tlist->word->flags & W_ASSIGNMENT) == 0); */
5232 /* If the -k option is in effect, we need to go through the remaining
5233 words, separate out the assignment words, and place them on VARLIST. */
5234 if (place_keywords_in_env)
5236 WORD_LIST *tp; /* tp == running pointer into tlist */
5241 /* Loop Invariant: tp->next == lp */
5242 /* Loop postcondition: tlist == word list without assignment statements */
5245 if (lp->word->flags & W_ASSIGNMENT)
5247 /* Found an assignment statement, add this word to end of
5257 /* Remove the word pointed to by LP from TLIST. */
5258 tp->next = lp->next;
5259 /* ASSERT(vp == lp); */
5260 lp->next = (WORD_LIST *)NULL;
5273 /* Take the list of words in LIST and do the various substitutions. Return
5274 a new list of words which is the expanded list, and without things like
5275 variable assignments. */
5281 return (expand_word_list_internal (list, 1));
5284 /* Same as expand_words (), but doesn't hack variable or environment
5287 expand_words_no_vars (list)
5290 return (expand_word_list_internal (list, 0));
5293 /* The workhorse for expand_words () and expand_words_no_vars ().
5294 First arg is LIST, a WORD_LIST of words.
5295 Second arg DO_VARS is non-zero if you want to do environment and
5296 variable assignments, else zero.
5298 This does all of the substitutions: brace expansion, tilde expansion,
5299 parameter expansion, command substitution, arithmetic expansion,
5300 process substitution, word splitting, and pathname expansion. Words
5301 with the W_QUOTED or W_NOSPLIT bits set, or for which no expansion
5302 is done, do not undergo word splitting. Words with the W_ASSIGNMENT
5303 bit set do not undergo pathname expansion. */
5305 expand_word_list_internal (list, do_vars)
5309 WORD_LIST *tlist, *new_list, *next, *temp_list, *orig_list, *disposables;
5314 return ((WORD_LIST *)NULL);
5316 tlist = copy_word_list (list);
5320 tlist = separate_out_assignments (tlist);
5325 /* All the words were variable assignments, so they are placed
5326 into the shell's environment. */
5327 for (new_list = varlist; new_list; new_list = new_list->next)
5329 this_command_name = (char *)NULL; /* no arithmetic errors */
5330 tint = do_assignment (new_list->word->word);
5331 /* Variable assignment errors in non-interactive shells
5332 running in Posix.2 mode cause the shell to exit. */
5333 if (tint == 0 && interactive_shell == 0 && posixly_correct)
5335 last_command_exit_value = EXECUTION_FAILURE;
5336 jump_to_top_level (FORCE_EOF);
5339 dispose_words (varlist);
5340 varlist = (WORD_LIST *)NULL;
5342 return ((WORD_LIST *)NULL);
5346 /* Begin expanding the words that remain. The expansions take place on
5347 things that aren't really variable assignments. */
5349 #if defined (BRACE_EXPANSION)
5350 /* Do brace expansion on this word if there are any brace characters
5352 if (brace_expansion && tlist)
5354 register char **expansions;
5359 for (braces = disposables = (WORD_LIST *)NULL; tlist; tlist = next)
5363 /* Only do brace expansion if the word has a brace character. If
5364 not, just add the word list element to BRACES and continue. In
5365 the common case, at least when running shell scripts, this will
5366 degenerate to a bunch of calls to `strchr', and then what is
5367 basically a reversal of TLIST into BRACES, which is corrected
5368 by a call to reverse_list () on BRACES when the end of TLIST
5370 if (strchr (tlist->word->word, '{'))
5372 expansions = brace_expand (tlist->word->word);
5374 for (eindex = 0; temp_string = expansions[eindex]; eindex++)
5376 w = make_word (temp_string);
5377 /* If brace expansion didn't change the word, preserve
5378 the flags. We may want to preserve the flags
5379 unconditionally someday -- XXX */
5380 if (STREQ (temp_string, tlist->word->word))
5381 w->flags = tlist->word->flags;
5382 braces = make_word_list (w, braces);
5383 free (expansions[eindex]);
5387 /* Add TLIST to the list of words to be freed after brace
5388 expansion has been performed. */
5389 tlist->next = disposables;
5390 disposables = tlist;
5394 tlist->next = braces;
5399 dispose_words (disposables);
5400 tlist = REVERSE_LIST (braces, WORD_LIST *);
5402 #endif /* BRACE_EXPANSION */
5404 /* We do tilde expansion all the time. This is what 1003.2 says. */
5405 for (orig_list = tlist, new_list = (WORD_LIST *)NULL; tlist; tlist = next)
5407 WORD_LIST *expanded;
5408 int expanded_something, has_dollar_at;
5410 temp_string = tlist->word->word;
5414 /* Posix.2 section 3.6.1 says that tildes following `=' in words
5415 which are not assignment statements are not expanded. We do
5416 this only if POSIXLY_CORRECT is enabled. Essentially, we do
5417 tilde expansion on unquoted assignment statements (flags include
5418 W_ASSIGNMENT but not W_QUOTED). */
5419 if (temp_string[0] == '~' ||
5420 (((tlist->word->flags & (W_ASSIGNMENT|W_QUOTED)) == W_ASSIGNMENT) &&
5421 posixly_correct == 0 &&
5422 strchr (temp_string, '~') &&
5423 (unquoted_substring ("=~", temp_string) || unquoted_substring (":~", temp_string))))
5425 tlist->word->word = bash_tilde_expand (temp_string);
5429 expanded_something = 0;
5430 expanded = expand_word_internal
5431 (tlist->word, 0, &has_dollar_at, &expanded_something);
5433 if (expanded == &expand_word_error || expanded == &expand_word_fatal)
5435 /* By convention, each time this error is returned,
5436 tlist->word->word has already been freed. */
5437 tlist->word->word = (char *)NULL;
5439 /* Dispose our copy of the original list. */
5440 dispose_words (orig_list);
5441 /* Dispose the new list we're building. */
5442 dispose_words (new_list);
5444 if (expanded == &expand_word_error)
5445 jump_to_top_level (DISCARD);
5447 jump_to_top_level (FORCE_EOF);
5450 /* Don't split words marked W_NOSPLIT. */
5451 if (expanded_something && (tlist->word->flags & W_NOSPLIT) == 0)
5453 temp_list = word_list_split (expanded);
5454 dispose_words (expanded);
5458 /* If no parameter expansion, command substitution, process
5459 substitution, or arithmetic substitution took place, then
5460 do not do word splitting. We still have to remove quoted
5461 null characters from the result. */
5462 word_list_remove_quoted_nulls (expanded);
5463 temp_list = expanded;
5466 /* In the most common cases, t will be a list containing only one
5467 element, so the call to reverse_list would be wasted. */
5468 expanded = REVERSE_LIST (temp_list, WORD_LIST *);
5469 new_list = (WORD_LIST *)list_append (expanded, new_list);
5472 new_list = REVERSE_LIST (new_list, WORD_LIST *);
5474 dispose_words (orig_list);
5476 /* Okay, we're almost done. Now let's just do some filename
5481 register int glob_index;
5482 WORD_LIST *glob_list;
5485 orig_list = disposables = (WORD_LIST *)NULL;
5488 /* orig_list == output list, despite the name. */
5489 if (disallow_filename_globbing == 0)
5491 glob_array = (char **)NULL;
5494 /* For each word, either globbing is attempted or the word is
5495 added to orig_list. If globbing succeeds, the results are
5496 added to orig_list and the word (tlist) is added to the list
5497 of disposable words. If globbing fails and failed glob
5498 expansions are left unchanged (the shell default), the
5499 original word is added to orig_list. If globbing fails and
5500 failed glob expansions are removed, the original word is
5501 added to the list of disposable words. orig_list ends up
5502 in reverse order and requires a call to reverse_list to
5503 be set right. After all words are examined, the disposable
5507 /* If the word isn't an assignment and contains an unquoted
5508 pattern matching character, then glob it. */
5510 if ((tlist->word->flags & (W_QUOTED|W_ASSIGNMENT)) == 0 &&
5512 if ((tlist->word->flags & W_ASSIGNMENT) == 0 &&
5514 unquoted_glob_pattern_p (tlist->word->word))
5516 glob_array = shell_glob_filename (tlist->word->word);
5518 /* Handle error cases.
5519 I don't think we should report errors like "No such file
5520 or directory". However, I would like to report errors
5521 like "Read failed". */
5523 if (GLOB_FAILED (glob_array))
5525 glob_array = (char **) xmalloc (sizeof (char *));
5526 glob_array[0] = (char *)NULL;
5529 /* Dequote the current word in case we have to use it. */
5530 if (glob_array[0] == NULL)
5532 temp_string = dequote_string (tlist->word->word);
5533 free (tlist->word->word);
5534 tlist->word->word = temp_string;
5537 /* Make the array into a word list. */
5538 glob_list = (WORD_LIST *)NULL;
5539 for (glob_index = 0; glob_array[glob_index]; glob_index++)
5541 tword = make_bare_word (glob_array[glob_index]);
5542 tword->flags |= W_GLOBEXP; /* XXX */
5543 glob_list = make_word_list (tword, glob_list);
5548 orig_list = (WORD_LIST *)list_append (glob_list, orig_list);
5549 tlist->next = disposables;
5550 disposables = tlist;
5552 else if (allow_null_glob_expansion == 0)
5554 /* Failed glob expressions are left unchanged. */
5555 tlist->next = orig_list;
5560 /* Failed glob expressions are removed. */
5561 tlist->next = disposables;
5562 disposables = tlist;
5567 /* Dequote the string. */
5568 temp_string = dequote_string (tlist->word->word);
5569 free (tlist->word->word);
5570 tlist->word->word = temp_string;
5571 tlist->next = orig_list;
5575 free_array (glob_array);
5576 glob_array = (char **)NULL;
5582 dispose_words (disposables);
5584 new_list = REVERSE_LIST (orig_list, WORD_LIST *);
5588 /* Dequote the words, because we're not performing globbing. */
5589 for (temp_list = new_list; temp_list; temp_list = temp_list->next)
5591 temp_string = dequote_string (temp_list->word->word);
5592 free (temp_list->word->word);
5593 temp_list->word->word = temp_string;
5600 Function *assign_func;
5602 /* If the remainder of the words expand to nothing, Posix.2 requires
5603 that the variable and environment assignments affect the shell's
5605 assign_func = new_list ? assign_in_env : do_assignment;
5607 for (temp_list = varlist; temp_list; temp_list = temp_list->next)
5609 this_command_name = (char *)NULL;
5610 tint = (*assign_func) (temp_list->word->word);
5611 /* Variable assignment errors in non-interactive shells running
5612 in Posix.2 mode cause the shell to exit. */
5613 if (tint == 0 && assign_func == do_assignment &&
5614 interactive_shell == 0 && posixly_correct)
5616 last_command_exit_value = EXECUTION_FAILURE;
5617 jump_to_top_level (FORCE_EOF);
5621 dispose_words (varlist);
5622 varlist = (WORD_LIST *)NULL;
5625 tint = list_length (new_list) + 1;
5626 RESIZE_MALLOCED_BUFFER (glob_argv_flags, 0, tint, glob_argv_flags_size, 16);
5627 for (tint = 0, tlist = new_list; tlist; tlist = tlist->next)
5628 glob_argv_flags[tint++] = (tlist->word->flags & W_GLOBEXP) ? '1' : '0';
5629 glob_argv_flags[tint] = '\0';
5634 /*************************************************
5636 * Functions to manage special variables *
5638 *************************************************/
5640 /* An alist of name.function for each special variable. Most of the
5641 functions don't do much, and in fact, this would be faster with a
5642 switch statement, but by the end of this file, I am sick of switch
5645 #define SET_INT_VAR(name, intvar) intvar = find_variable (name) != 0
5647 struct name_and_function {
5649 VFunction *function;
5650 } special_vars[] = {
5651 { "PATH", sv_path },
5652 { "MAIL", sv_mail },
5653 { "MAILPATH", sv_mail },
5654 { "MAILCHECK", sv_mail },
5656 { "POSIXLY_CORRECT", sv_strict_posix },
5657 { "GLOBIGNORE", sv_globignore },
5659 /* Variables which only do something special when READLINE is defined. */
5660 #if defined (READLINE)
5661 { "TERM", sv_terminal },
5662 { "TERMCAP", sv_terminal },
5663 { "TERMINFO", sv_terminal },
5664 { "HOSTFILE", sv_hostfile },
5665 #endif /* READLINE */
5667 /* Variables which only do something special when HISTORY is defined. */
5668 #if defined (HISTORY)
5669 { "HISTIGNORE", sv_histignore },
5670 { "HISTSIZE", sv_histsize },
5671 { "HISTFILESIZE", sv_histsize },
5672 { "HISTCONTROL", sv_history_control },
5673 # if defined (BANG_HISTORY)
5674 { "histchars", sv_histchars },
5675 # endif /* BANG_HISTORY */
5676 #endif /* HISTORY */
5678 { "IGNOREEOF", sv_ignoreeof },
5679 { "ignoreeof", sv_ignoreeof },
5681 { "OPTIND", sv_optind },
5682 { "OPTERR", sv_opterr },
5684 { "TEXTDOMAIN", sv_locale },
5685 { "TEXTDOMAINDIR", sv_locale },
5686 { "LC_ALL", sv_locale },
5687 { "LC_COLLATE", sv_locale },
5688 { "LC_CTYPE", sv_locale },
5689 { "LC_MESSAGES", sv_locale },
5690 { "LANG", sv_locale },
5692 #if defined (HAVE_TZSET) && defined (PROMPT_STRING_DECODE)
5696 { (char *)0, (VFunction *)0 }
5699 /* The variable in NAME has just had its state changed. Check to see if it
5700 is one of the special ones where something special happens. */
5702 stupidly_hack_special_variables (name)
5707 for (i = 0; special_vars[i].name; i++)
5709 if (STREQ (special_vars[i].name, name))
5711 (*(special_vars[i].function)) (name);
5717 /* What to do just after the PATH variable has changed. */
5723 flush_hashed_filenames ();
5726 /* What to do just after one of the MAILxxxx variables has changed. NAME
5727 is the name of the variable. This is called with NAME set to one of
5728 MAIL, MAILCHECK, or MAILPATH. */
5733 /* If the time interval for checking the files has changed, then
5734 reset the mail timer. Otherwise, one of the pathname vars
5735 to the users mailbox has changed, so rebuild the array of
5737 if (name[4] == 'C') /* if (strcmp (name, "MAILCHECK") == 0) */
5738 reset_mail_timer ();
5742 remember_mail_dates ();
5746 /* What to do when GLOBIGNORE changes. */
5748 sv_globignore (name)
5751 setup_glob_ignore (name);
5754 #if defined (READLINE)
5755 /* What to do just after one of the TERMxxx variables has changed.
5756 If we are an interactive shell, then try to reset the terminal
5757 information in readline. */
5762 if (interactive_shell && no_line_editing == 0)
5763 rl_reset_terminal (get_string_value ("TERM"));
5770 hostname_list_initialized = 0;
5772 #endif /* READLINE */
5774 #if defined (HISTORY)
5775 /* What to do after the HISTSIZE or HISTFILESIZE variables change.
5776 If there is a value for this HISTSIZE (and it is numeric), then stifle
5777 the history. Otherwise, if there is NO value for this variable,
5778 unstifle the history. If name is HISTFILESIZE, and its value is
5779 numeric, truncate the history file to hold no more than that many
5788 temp = get_string_value (name);
5792 if (legal_number (temp, &num))
5796 stifle_history (num);
5797 num = where_history ();
5798 if (history_lines_this_session > num)
5799 history_lines_this_session = num;
5803 history_truncate_file (get_string_value ("HISTFILE"), (int)num);
5804 if (num <= history_lines_in_file)
5805 history_lines_in_file = num;
5809 else if (name[4] == 'S')
5810 unstifle_history ();
5813 /* What to do after the HISTIGNORE variable changes. */
5815 sv_histignore (name)
5818 setup_history_ignore (name);
5821 /* What to do after the HISTCONTROL variable changes. */
5823 sv_history_control (name)
5828 history_control = 0;
5829 temp = get_string_value (name);
5831 if (temp && *temp && STREQN (temp, "ignore", 6))
5833 if (temp[6] == 's') /* ignorespace */
5834 history_control = 1;
5835 else if (temp[6] == 'd') /* ignoredups */
5836 history_control = 2;
5837 else if (temp[6] == 'b') /* ignoreboth */
5838 history_control = 3;
5842 #if defined (BANG_HISTORY)
5843 /* Setting/unsetting of the history expansion character. */
5850 temp = get_string_value (name);
5853 history_expansion_char = *temp;
5854 if (temp[0] && temp[1])
5856 history_subst_char = temp[1];
5858 history_comment_char = temp[2];
5863 history_expansion_char = '!';
5864 history_subst_char = '^';
5865 history_comment_char = '#';
5868 #endif /* BANG_HISTORY */
5869 #endif /* HISTORY */
5871 #if defined (HAVE_TZSET) && defined (PROMPT_STRING_DECODE)
5880 /* If the variable exists, then the value of it can be the number
5881 of times we actually ignore the EOF. The default is small,
5882 (smaller than csh, anyway). */
5890 eof_encountered = 0;
5892 tmp_var = find_variable (name);
5893 ignoreeof = tmp_var != 0;
5894 temp = tmp_var ? value_cell (tmp_var) : (char *)NULL;
5896 eof_encountered_limit = (*temp && all_digits (temp)) ? atoi (temp) : 10;
5897 set_shellopts (); /* make sure `ignoreeof' is/is not in $SHELLOPTS */
5907 tt = get_string_value ("OPTIND");
5912 /* According to POSIX, setting OPTIND=1 resets the internal state
5914 if (s < 0 || s == 1)
5928 tt = get_string_value ("OPTERR");
5929 sh_opterr = (tt && *tt) ? atoi (tt) : 1;
5933 sv_strict_posix (name)
5936 SET_INT_VAR (name, posixly_correct);
5937 posix_initialize (posixly_correct);
5938 #if defined (READLINE)
5939 if (interactive_shell)
5940 posix_readline_initialize (posixly_correct);
5941 #endif /* READLINE */
5942 set_shellopts (); /* make sure `posix' is/is not in $SHELLOPTS */
5951 v = get_string_value (name);
5952 if (name[0] == 'L' && name[1] == 'A') /* LANG */
5955 set_locale_var (name, v); /* LC_*, TEXTDOMAIN* */