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. */
22 #include "bashtypes.h"
27 /* Not all systems declare ERRNO in errno.h... and some systems #define it! */
33 #include "posixstat.h"
38 #include "execute_cmd.h"
41 #if defined (READLINE)
42 # include <readline/readline.h>
44 # include <tilde/tilde.h>
48 # include "bashhist.h"
49 # include <readline/history.h>
52 #include <glob/fnmatch.h>
53 #include "builtins/getopt.h"
55 /* The size that strings change by. */
56 #define DEFAULT_ARRAY_SIZE 512
58 /* How to quote and determine the quoted state of the character C. */
59 static char *make_quoted_char ();
60 #define QUOTED_CHAR(c) ((c) == CTLESC)
62 /* Process ID of the last command executed within command substitution. */
63 pid_t last_command_subst_pid = NO_PID;
65 /* Extern functions and variables from different files. */
66 extern int last_command_exit_value, interactive, interactive_shell;
67 extern int subshell_environment;
68 extern int dollar_dollar_pid, no_brace_expansion;
69 extern int posixly_correct;
70 extern int eof_encountered, eof_encountered_limit, ignoreeof;
71 extern char *this_command_name;
72 extern jmp_buf top_level;
73 #if defined (READLINE)
74 extern int no_line_editing;
75 extern int hostname_list_initialized;
78 #if !defined (USE_POSIX_GLOB_LIBRARY)
79 extern int glob_dot_filenames, noglob_dot_filenames;
80 extern char *glob_error_return;
83 static WORD_LIST expand_word_error, expand_word_fatal;
84 static char expand_param_error, expand_param_fatal;
86 static WORD_LIST *expand_string_internal ();
87 static WORD_LIST *expand_word_internal (), *expand_words_internal ();
88 static WORD_LIST *expand_string_leave_quoted ();
89 static WORD_LIST *word_list_split ();
90 static char *quote_string ();
91 static int unquoted_substring (), unquoted_member ();
92 static int unquoted_glob_pattern_p ();
93 static void quote_list (), dequote_list ();
94 static int do_assignment_internal ();
95 static char *string_extract_verbatim (), *string_extract ();
96 static char *string_extract_double_quoted (), *string_extract_single_quoted ();
97 static char *extract_delimited_string ();
98 static char *extract_dollar_brace_string ();
100 /* **************************************************************** */
102 /* Utility Functions */
104 /* **************************************************************** */
106 /* Cons a new string from STRING starting at START and ending at END,
107 not including END. */
109 substring (string, start, end)
113 register int len = end - start;
114 register char *result = xmalloc (len + 1);
116 strncpy (result, string + start, len);
123 A string with s[0] == CTLNUL && s[1] == 0 is a quoted null string.
124 The parser passes CTLNUL as CTLESC CTLNUL. */
126 /* The parser passes us CTLESC as CTLESC CTLESC and CTLNUL as CTLESC CTLNUL.
127 This is necessary to make unquoted CTLESC and CTLNUL characters in the
128 data stream pass through properly.
129 Here we remove doubled CTLESC characters inside quoted strings before
130 quoting the entire string, so we do not double the number of CTLESC
133 remove_quoted_escapes (string)
138 for (s = string; s && *s; s++)
140 if (*s == CTLESC && (s[1] == CTLESC || s[1] == CTLNUL))
141 strcpy (s, s + 1); /* XXX - should be memmove */
146 /* Quote escape characters in string s, but no other characters. This is
147 used to protect CTLESC and CTLNUL in variable values from the rest of
148 the word expansion process after the variable is expanded. */
150 quote_escapes (string)
153 register char *s, *t;
156 result = xmalloc ((strlen (string) * 2) + 1);
157 for (s = string, t = result; s && *s; )
159 if (*s == CTLESC || *s == CTLNUL)
167 /* Just like string_extract, but doesn't hack backslashes or any of
168 that other stuff. Obeys quoting. Used to do splitting on $IFS. */
170 string_extract_verbatim (string, sindex, charlist)
171 char *string, *charlist;
174 register int i = *sindex;
178 if (charlist[0] == '\'' && !charlist[1])
180 temp = string_extract_single_quoted (string, sindex);
186 for (i = *sindex; (c = string[i]); i++)
194 if (MEMBER (c, charlist))
198 temp = xmalloc (1 + (i - *sindex));
199 strncpy (temp, string + (*sindex), i - (*sindex));
200 temp[i - (*sindex)] = '\0';
206 /* Extract a substring from STRING, starting at SINDEX and ending with
207 one of the characters in CHARLIST. Don't make the ending character
208 part of the string. Leave SINDEX pointing at the ending character.
209 Understand about backslashes in the string. */
211 string_extract (string, sindex, charlist)
212 char *string, *charlist;
215 register int c, i = *sindex;
218 while (c = string[i])
226 if (MEMBER (c, charlist))
230 temp = xmalloc (1 + (i - *sindex));
231 strncpy (temp, string + (*sindex), i - (*sindex));
232 temp[i - (*sindex)] = '\0';
237 /* Remove backslashes which are quoting backquotes from STRING. Modifies
238 STRING, and returns a pointer to it. */
240 de_backslash (string)
243 register int i, l = strlen (string);
245 for (i = 0; i < l; i++)
246 if (string[i] == '\\' && (string[i + 1] == '`' || string[i + 1] == '\\' ||
247 string[i + 1] == '$'))
248 strcpy (string + i, string + i + 1); /* XXX - should be memmove */
253 /* Replace instances of \! in a string with !. */
255 unquote_bang (string)
261 temp = xmalloc (1 + strlen (string));
263 for (i = 0, j = 0; (temp[j] = string[i]); i++, j++)
265 if (string[i] == '\\' && string[i + 1] == '!')
271 strcpy (string, temp);
276 /* Extract the $( construct in STRING, and return a new string.
277 Start extracting at (SINDEX) as if we had just seen "$(".
278 Make (SINDEX) get the position just after the matching ")". */
280 extract_command_subst (string, sindex)
284 return (extract_delimited_string (string, sindex, "$(", "(", ")"));
287 /* Extract the $[ construct in STRING, and return a new string.
288 Start extracting at (SINDEX) as if we had just seen "$[".
289 Make (SINDEX) get the position just after the matching "]". */
291 extract_arithmetic_subst (string, sindex)
295 return (extract_delimited_string (string, sindex, "$[", "[", "]"));
298 #if defined (PROCESS_SUBSTITUTION)
299 /* Extract the <( or >( construct in STRING, and return a new string.
300 Start extracting at (SINDEX) as if we had just seen "<(".
301 Make (SINDEX) get the position just after the matching ")". */
303 extract_process_subst (string, starter, sindex)
308 return (extract_delimited_string (string, sindex, starter, "(", ")"));
310 #endif /* PROCESS_SUBSTITUTION */
312 /* Extract and create a new string from the contents of STRING, a
313 character string delimited with OPENER and CLOSER. SINDEX is
314 the address of an int describing the current offset in STRING;
315 it should point to just after the first OPENER found. On exit,
316 SINDEX gets the position just after the matching CLOSER. If
317 OPENER is more than a single character, ALT_OPENER, if non-null,
318 contains a character string that can also match CLOSER and thus
319 needs to be skipped. */
321 extract_delimited_string (string, sindex, opener, alt_opener, closer)
324 char *opener, *alt_opener, *closer;
326 register int i, c, l;
327 int pass_character, nesting_level;
328 int delimiter, delimited_nesting_level;
329 int len_closer, len_opener, len_alt_opener;
332 len_opener = STRLEN (opener);
333 len_alt_opener = STRLEN (alt_opener);
334 len_closer = STRLEN (closer);
336 pass_character = delimiter = delimited_nesting_level = 0;
340 for (i = *sindex; c = string[i]; i++)
356 if ((delimiter == '"') &&
357 (member (string[i + 1], slashify_in_quotes)))
364 if (!delimiter || delimiter == '"')
366 if (STREQN (string + i, opener, len_opener))
371 delimited_nesting_level++;
377 if (len_alt_opener && STREQN (string + i, alt_opener, len_alt_opener))
382 delimited_nesting_level++;
384 i += len_alt_opener - 1;
388 if (STREQN (string + i, closer, len_closer))
392 if (delimiter && delimited_nesting_level)
393 delimited_nesting_level--;
398 if (nesting_level == 0)
406 if (c == delimiter || delimiter == '\\')
412 if (c == '"' || c == '\'' || c == '\\')
418 result = xmalloc (1 + l);
419 strncpy (result, string + *sindex, l);
423 if (!c && (delimiter || nesting_level))
425 report_error ("bad substitution: no `%s' in %s", closer, string);
427 longjmp (top_level, DISCARD);
432 /* Extract a parameter expansion expression within ${ and } from STRING.
433 Obey the Posix.2 rules for finding the ending `}': count braces while
434 skipping over enclosed quoted strings and command substitutions.
435 SINDEX is the address of an int describing the current offset in STRING;
436 it should point to just after the first `{' found. On exit, SINDEX
437 gets the position just after the matching `}'. */
438 /* XXX -- this is very similar to extract_delimited_string -- XXX */
440 extract_dollar_brace_string (string, sindex)
444 register int i, c, l;
445 int pass_character, nesting_level;
446 int delimiter, delimited_nesting_level;
449 pass_character = delimiter = delimited_nesting_level = 0;
453 for (i = *sindex; c = string[i]; i++)
467 /* Backslashes quote the next character. */
470 if ((delimiter == '"') &&
471 (member (string[i + 1], slashify_in_quotes)))
478 if (!delimiter || delimiter == '"')
480 if (string[i] == '$' && string[i+1] == '{')
485 delimited_nesting_level++;
491 /* Pass the contents of old-style command substitutions through
493 if (string[i] == '`')
499 t = string_extract (string, &si, "`");
505 /* Pass the contents of new-style command substitutions through
507 if (string[i] == '$' && string[i+1] == '(')
513 t = extract_delimited_string (string, &si, "$(", "(", ")");
519 if (string[i] == '{')
524 delimited_nesting_level++;
529 if (string[i] == '}')
531 if (delimiter && delimited_nesting_level)
532 delimited_nesting_level--;
537 if (nesting_level == 0)
545 if (c == delimiter || delimiter == '\\')
551 if (c == '"' || c == '\'' || c == '\\')
557 result = xmalloc (1 + l);
558 strncpy (result, string + *sindex, l);
562 if (!c && (delimiter || nesting_level))
564 report_error ("bad substitution: no ending `}' in %s", string);
566 longjmp (top_level, DISCARD);
571 /* Extract the contents of STRING as if it is enclosed in double quotes.
572 SINDEX, when passed in, is the offset of the character immediately
573 following the opening double quote; on exit, SINDEX is left pointing after
574 the closing double quote. */
576 string_extract_double_quoted (string, sindex)
580 register int c, j, i;
581 char *temp; /* The new string we return. */
582 int pass_next, backquote; /* State variables for the machine. */
584 pass_next = backquote = 0;
585 temp = xmalloc (1 + strlen (string) - *sindex);
587 for (j = 0, i = *sindex; c = string[i]; i++)
589 /* Process a character that was quoted by a backslash. */
594 ``The backslash shall retain its special meaning as an escape
595 character only when followed by one of the characters:
598 We handle the double quotes here. expand_word_internal handles
607 /* A backslash protects the next character. The code just above
608 handles preserving the backslash in front of any character but
616 /* Inside backquotes, ``the portion of the quoted string from the
617 initial backquote and the characters up to the next backquote
618 that is not preceded by a backslash, having escape characters
619 removed, defines that command''. */
635 /* Pass everything between `$(' and the matching `)' or a quoted
636 ${ ... } pair through according to the Posix.2 specification. */
637 if (c == '$' && ((string[i + 1] == '(') || (string[i + 1] == '{')))
644 if (string[i + 1] == '(')
645 ret = extract_delimited_string (string, &si, "$(", "(", ")");
647 ret = extract_dollar_brace_string (string, &si);
650 temp[j++] = string[i + 1];
652 for (t = 0; ret[t]; t++)
656 temp[j++] = string[i];
661 /* An unescaped double quote serves to terminate the string. */
665 /* Add the character to the quoted string we're accumulating. */
670 /* Point to after the closing quote. */
678 /* Extract the contents of STRING as if it is enclosed in single quotes.
679 SINDEX, when passed in, is the offset of the character immediately
680 following the opening single quote; on exit, SINDEX is left pointing after
681 the closing single quote. */
683 string_extract_single_quoted (string, sindex)
687 register int i = *sindex;
690 while (string[i] && string[i] != '\'')
693 temp = xmalloc (1 + i - *sindex);
694 strncpy (temp, string + *sindex, i - *sindex);
695 temp[i - *sindex] = '\0';
704 /* Return 1 if the portion of STRING ending at EINDEX is quoted (there is
705 an unclosed quoted string), or if the character at EINDEX is quoted
708 char_is_quoted (string, eindex)
712 int i, pass_next, quoted;
715 for (i = pass_next = quoted = 0; i <= eindex; i++)
720 if (i >= eindex) /* XXX was if (i >= eindex - 1) */
724 else if (string[i] == '\'')
727 temp = string_extract_single_quoted (string, &i);
733 else if (string[i] == '"')
736 temp = string_extract_double_quoted (string, &i);
742 else if (string[i] == '\\')
751 #if defined (READLINE)
753 unclosed_pair (string, eindex, openstr)
758 int i, pass_next, openc, c, olen;
761 olen = strlen (openstr);
762 for (i = pass_next = openc = 0; i <= eindex; i++)
767 if (i >= eindex) /* XXX was if (i >= eindex - 1) */
771 else if (STREQN (string + i, openstr, olen))
776 else if (string[i] == '\'')
779 temp = string_extract_single_quoted (string, &i);
784 else if (string[i] == '"')
787 temp = string_extract_double_quoted (string, &i);
792 else if (string[i] == '\\')
800 #endif /* READLINE */
802 /* Extract the name of the variable to bind to from the assignment string. */
804 assignment_name (string)
807 int offset = assignment (string);
812 temp = xmalloc (offset + 1);
813 strncpy (temp, string, offset);
818 /* Return a single string of all the words in LIST. SEP is the separator
819 to put between individual elements of LIST in the output string. */
821 string_list_internal (list, sep)
825 register WORD_LIST *t;
827 int word_len, sep_len, result_size;
830 return ((char *)NULL);
832 /* This is nearly always called with either sep[0] == 0 or sep[1] == 0. */
833 sep_len = STRLEN (sep);
836 for (t = list; t; t = t->next)
839 result_size += sep_len;
840 result_size += strlen (t->word->word);
843 r = result = xmalloc (result_size + 1);
845 for (t = list; t; t = t->next)
847 if (t != list && sep_len)
849 FASTCOPY (sep, r, sep_len);
853 word_len = strlen (t->word->word);
854 FASTCOPY (t->word->word, r, word_len);
862 /* Return a single string of all the words present in LIST, separating
863 each word with a space. */
868 return (string_list_internal (list, " "));
871 /* Return a single string of all the words present in LIST, obeying the
872 quoting rules for "$*", to wit: (P1003.2, draft 11, 3.5.2) "If the
873 expansion [of $*] appears within a double quoted string, it expands
874 to a single field with the value of each parameter separated by the
875 first character of the IFS variable, or by a <space> if IFS is unset." */
877 string_list_dollar_star (list)
880 char *ifs = get_string_value ("IFS");
892 return (string_list_internal (list, sep));
895 /* Return the list of words present in STRING. Separate the string into
896 words at any of the characters found in SEPARATORS. If QUOTED is
897 non-zero then word in the list will have its quoted flag set, otherwise
898 the quoted flag is left as make_word () deemed fit.
900 This obeys the P1003.2 word splitting semantics. If `separators' is
901 exactly <space><tab><newline>, then the splitting algorithm is that of
902 the Bourne shell, which treats any sequence of characters from `separators'
903 as a delimiter. If IFS is unset, which results in `separators' being set
904 to "", no splitting occurs. If separators has some other value, the
905 following rules are applied (`IFS white space' means zero or more
906 occurrences of <space>, <tab>, or <newline>, as long as those characters
907 are in `separators'):
909 1) IFS white space is ignored at the start and the end of the
911 2) Each occurrence of a character in `separators' that is not
912 IFS white space, along with any adjacent occurrences of
913 IFS white space delimits a field.
914 3) Any nonzero-length sequence of IFS white space delimits a field.
917 /* BEWARE! list_string strips null arguments. Don't call it twice and
918 expect to have "" preserved! */
920 /* Is the first character of STRING a quoted NULL character? */
921 #define QUOTED_NULL(string) ((string)[0] == CTLNUL && (string)[1] == '\0')
923 /* Perform quoted null character removal on STRING. We don't allow any
924 quoted null characters in the middle or at the ends of strings because
925 of how expand_word_internal works. remove_quoted_nulls () simply
926 turns STRING into an empty string iff it only consists of a quoted null. */
928 #define remove_quoted_nulls(string) \
929 do { if (QUOTED_NULL (string)) string[0] ='\0'; } while (0)
932 remove_quoted_nulls (string)
937 nstr = savestring (string);
939 for (p = nstr, s = string; *s; s++)
943 *p++ = *s++; /* CTLESC */
946 *p++ = *s; /* quoted char */
954 strcpy (string, nstr);
958 /* Perform quoted null character removal on each element of LIST.
959 This modifies LIST. */
961 word_list_remove_quoted_nulls (list)
964 register WORD_LIST *t;
970 remove_quoted_nulls (t->word->word);
975 /* This performs word splitting and quoted null character removal on
978 #define issep(c) (member ((c), separators))
981 list_string (string, separators, quoted)
982 register char *string, *separators;
985 WORD_LIST *result = (WORD_LIST *)NULL;
986 char *current_word = (char *)NULL, *s;
990 if (!string || !*string)
991 return ((WORD_LIST *)NULL);
994 separators && *separators && (STREQ (separators, " \t\n"));
996 /* Remove sequences of whitespace at the beginning of STRING, as
997 long as those characters appear in IFS. Do not do this if
998 STRING is quoted or if there are no separator characters. */
999 if (!quoted || !separators || !*separators)
1001 for (s = string; *s && spctabnl (*s) && issep (*s); s++);
1004 return ((WORD_LIST *)NULL);
1009 /* OK, now STRING points to a word that does not begin with white space.
1010 The splitting algorithm is:
1011 extract a word, stopping at a separator
1012 skip sequences of spc, tab, or nl as long as they are separators
1013 This obeys the field splitting rules in Posix.2. */
1015 while (string[sindex])
1017 current_word = string_extract_verbatim (string, &sindex, separators);
1021 /* If we have a quoted empty string, add a quoted null argument. We
1022 want to preserve the quoted null character iff this is a quoted
1023 empty string; otherwise the quoted null characters are removed
1025 if (QUOTED_NULL (current_word))
1027 WORD_DESC *t = make_word (" ");
1030 t->word = make_quoted_char ('\0');
1031 result = make_word_list (t, result);
1033 else if (strlen (current_word))
1035 /* If we have something, then add it regardless. However,
1036 perform quoted null character removal on the current word. */
1037 remove_quoted_nulls (current_word);
1038 result = make_word_list (make_word (current_word), result);
1040 result->word->quoted = 1;
1043 /* If we're not doing sequences of separators in the traditional
1044 Bourne shell style, then add a quoted null argument. */
1046 else if (!sh_style_split && !spctabnl (string[sindex]))
1048 result = make_word_list (make_word (""), result);
1049 result->word->quoted = 1;
1052 free (current_word);
1054 /* Move past the current separator character. */
1058 /* Now skip sequences of space, tab, or newline characters if they are
1059 in the list of separators. */
1060 while (string[sindex] && spctabnl (string[sindex]) && issep (string[sindex]))
1064 return (REVERSE_LIST (result, WORD_LIST *));
1067 /* Parse a single word from STRING, using SEPARATORS to separate fields.
1068 ENDPTR is set to the first character after the word. This is used by
1070 XXX - this function is very similar to list_string; they should be
1073 get_word_from_string (stringp, separators, endptr)
1074 char **stringp, *separators, **endptr;
1078 int sindex, sh_style_split;
1080 if (!stringp || !*stringp || !**stringp)
1081 return ((char *)NULL);
1086 separators && *separators && (STREQ (separators, " \t\n"));
1088 /* Remove sequences of whitespace at the beginning of STRING, as
1089 long as those characters appear in IFS. */
1090 if (sh_style_split || !separators || !*separators)
1092 for (; *s && spctabnl (*s) && issep (*s); s++);
1094 /* If the string is nothing but whitespace, update it and return. */
1100 return ((char *)NULL);
1104 /* OK, S points to a word that does not begin with white space.
1105 Now extract a word, stopping at a separator, save a pointer to
1106 the first character after the word, then skip sequences of spc,
1107 tab, or nl as long as they are separators.
1109 This obeys the field splitting rules in Posix.2. */
1111 current_word = string_extract_verbatim (s, &sindex, separators);
1113 /* Set ENDPTR to the first character after the end of the word. */
1115 *endptr = s + sindex;
1117 /* Move past the current separator character. */
1121 /* Now skip sequences of space, tab, or newline characters if they are
1122 in the list of separators. */
1123 while (s[sindex] && spctabnl (s[sindex]) && issep (s[sindex]))
1126 /* Update STRING to point to the next field. */
1127 *stringp = s + sindex;
1128 return (current_word);
1131 /* Remove IFS white space at the end of STRING. Start at the end
1132 of the string and walk backwards until the beginning of the string
1133 or we find a character that's not IFS white space and not CTLESC.
1134 Only let CTLESC escape a white space character if SAW_ESCAPE is
1137 strip_trailing_ifs_whitespace (string, separators, saw_escape)
1138 char *string, *separators;
1143 s = string + STRLEN (string) - 1;
1144 while (s > string && ((spctabnl (*s) && issep (*s)) ||
1145 (saw_escape && *s == CTLESC && spctabnl (s[1]))))
1151 #if defined (PROCESS_SUBSTITUTION)
1152 #define EXP_CHAR(s) (s == '$' || s == '`' || s == '<' || s == '>' || s == CTLESC)
1154 #define EXP_CHAR(s) (s == '$' || s == '`' || s == CTLESC)
1157 /* If there are any characters in STRING that require full expansion,
1158 then call FUNC to expand STRING; otherwise just perform quote
1159 removal if necessary. This returns a new string. */
1161 maybe_expand_string (string, quoted, func)
1164 WORD_LIST *(*func)();
1170 for (i = saw_quote = 0; string[i]; i++)
1172 if (EXP_CHAR (string[i]))
1174 else if (string[i] == '\'' || string[i] == '\\' || string[i] == '"')
1180 list = (*func) (string, quoted);
1183 ret = string_list (list);
1184 dispose_words (list);
1189 else if (saw_quote && !quoted)
1190 ret = string_quote_removal (string, quoted);
1192 ret = savestring (string);
1196 /* Given STRING, an assignment string, get the value of the right side
1197 of the `=', and bind it to the left side. If EXPAND is true, then
1198 perform parameter expansion, command substitution, and arithmetic
1199 expansion on the right-hand side. Perform tilde expansion in any
1200 case. Do not perform word splitting on the result of expansion. */
1202 do_assignment_internal (string, expand)
1206 int offset = assignment (string);
1207 char *name = savestring (string);
1208 char *value = (char *)NULL;
1209 SHELL_VAR *entry = (SHELL_VAR *)NULL;
1211 if (name[offset] == '=')
1216 temp = name + offset + 1;
1218 if (expand && temp[0])
1220 if (strchr (temp, '~') && unquoted_member ('~', temp))
1221 temp = tilde_expand (temp);
1223 temp = savestring (temp);
1225 value = maybe_expand_string (temp, 0, expand_string_unsplit);
1229 value = savestring (temp);
1233 value = savestring ("");
1235 entry = bind_variable (name, value);
1237 if (echo_command_at_execute)
1238 fprintf (stderr, "%s%s=%s\n", indirection_level_string (), name, value);
1240 stupidly_hack_special_variables (name);
1243 entry->attributes &= ~att_invisible;
1248 /* Return 1 if the assignment seems to have been performed correctly. */
1249 return (entry ? ((entry->attributes & att_readonly) == 0) : 0);
1252 /* Perform the assignment statement in STRING, and expand the
1253 right side by doing command and parameter expansion. */
1254 do_assignment (string)
1257 return do_assignment_internal (string, 1);
1260 /* Given STRING, an assignment string, get the value of the right side
1261 of the `=', and bind it to the left side. Do not do command and
1262 parameter substitution on the right hand side. */
1263 do_assignment_no_expand (string)
1266 return do_assignment_internal (string, 0);
1269 /* Most of the substitutions must be done in parallel. In order
1270 to avoid using tons of unclear goto's, I have some functions
1271 for manipulating malloc'ed strings. They all take INDX, a
1272 pointer to an integer which is the offset into the string
1273 where manipulation is taking place. They also take SIZE, a
1274 pointer to an integer which is the current length of the
1275 character array for this string. */
1277 /* Append SOURCE to TARGET at INDEX. SIZE is the current amount
1278 of space allocated to TARGET. SOURCE can be NULL, in which
1279 case nothing happens. Gets rid of SOURCE by free ()ing it.
1280 Returns TARGET in case the location has changed. */
1282 sub_append_string (source, target, indx, size)
1283 char *source, *target;
1290 srclen = strlen (source);
1291 if (srclen >= (int)(*size - *indx))
1294 n = (n + DEFAULT_ARRAY_SIZE) - (n % DEFAULT_ARRAY_SIZE);
1295 target = xrealloc (target, (*size = n));
1298 FASTCOPY (source, target + *indx, srclen);
1300 target[*indx] = '\0';
1307 /* Append the textual representation of NUMBER to TARGET.
1308 INDX and SIZE are as in SUB_APPEND_STRING. */
1310 sub_append_number (number, target, indx, size)
1311 int number, *indx, *size;
1316 temp = itos (number);
1317 return (sub_append_string (temp, target, indx, size));
1320 /* Return the word list that corresponds to `$*'. */
1322 list_rest_of_args ()
1324 register WORD_LIST *list = (WORD_LIST *)NULL;
1325 register WORD_LIST *args = rest_of_args;
1328 /* Break out of the loop as soon as one of the dollar variables is null. */
1329 for (i = 1; i < 10 && dollar_vars[i]; i++)
1330 list = make_word_list (make_word (dollar_vars[i]), list);
1334 list = make_word_list (make_word (args->word->word), list);
1337 return (REVERSE_LIST (list, WORD_LIST *));
1340 /* Make a single large string out of the dollar digit variables,
1341 and the rest_of_args. If DOLLAR_STAR is 1, then obey the special
1342 case of "$*" with respect to IFS. */
1344 string_rest_of_args (dollar_star)
1347 register WORD_LIST *list = list_rest_of_args ();
1350 string = dollar_star ? string_list_dollar_star (list) : string_list (list);
1351 dispose_words (list);
1355 /***************************************************
1357 * Functions to Expand a String *
1359 ***************************************************/
1360 /* Call expand_word_internal to expand W and handle error returns.
1361 A convenience function for functions that don't want to handle
1362 any errors or free any memory before aborting. */
1364 call_expand_word_internal (w, q, c, e)
1370 result = expand_word_internal (w, q, c, e);
1371 if (result == &expand_word_error)
1372 longjmp (top_level, DISCARD);
1373 else if (result == &expand_word_fatal)
1374 longjmp (top_level, FORCE_EOF);
1379 /* Perform parameter expansion, command substitution, and arithmetic
1380 expansion on STRING, as if it were a word. Leave the result quoted. */
1382 expand_string_internal (string, quoted)
1389 if (!string || !*string)
1390 return ((WORD_LIST *)NULL);
1392 bzero (&td, sizeof (td));
1394 tresult = call_expand_word_internal (&td, quoted, (int *)NULL, (int *)NULL);
1398 /* Expand STRING by performing parameter expansion, command substitution,
1399 and arithmetic expansion. Dequote the resulting WORD_LIST before
1400 returning it, but do not perform word splitting. The call to
1401 remove_quoted_nulls () is in here because word splitting normally
1402 takes care of quote removal. */
1404 expand_string_unsplit (string, quoted)
1410 if (!string || !*string)
1411 return ((WORD_LIST *)NULL);
1413 value = expand_string_internal (string, quoted);
1417 remove_quoted_nulls (value->word->word);
1418 dequote_list (value);
1423 /* This does not perform word splitting or dequote the WORD_LIST
1426 expand_string_for_rhs (string, quoted, dollar_at_p, has_dollar_at)
1428 int quoted, *dollar_at_p, *has_dollar_at;
1433 if (string == 0 || *string == '\0')
1434 return (WORD_LIST *)NULL;
1436 bzero (&td, sizeof (td));
1438 tresult = call_expand_word_internal (&td, quoted, dollar_at_p, has_dollar_at);
1442 /* Expand STRING just as if you were expanding a word, but do not dequote
1443 the resultant WORD_LIST. This is called only from within this file,
1444 and is used to correctly preserve quoted characters when expanding
1445 things like ${1+"$@"}. This does parameter expansion, command
1446 subsitution, arithmetic expansion, and word splitting. */
1448 expand_string_leave_quoted (string, quoted)
1455 if (!string || !*string)
1456 return ((WORD_LIST *)NULL);
1458 tlist = expand_string_internal (string, quoted);
1462 tresult = word_list_split (tlist);
1463 dispose_words (tlist);
1466 return ((WORD_LIST *)NULL);
1469 /* Expand STRING just as if you were expanding a word. This also returns
1470 a list of words. Note that filename globbing is *NOT* done for word
1471 or string expansion, just when the shell is expanding a command. This
1472 does parameter expansion, command substitution, arithmetic expansion,
1473 and word splitting. Dequote the resultant WORD_LIST before returning. */
1475 expand_string (string, quoted)
1481 if (!string || !*string)
1482 return ((WORD_LIST *)NULL);
1484 result = expand_string_leave_quoted (string, quoted);
1487 dequote_list (result);
1491 /***************************************************
1493 * Functions to handle quoting chars *
1495 ***************************************************/
1497 /* I'm going to have to rewrite expansion because filename globbing is
1498 beginning to make the entire arrangement ugly. I'll do this soon. */
1501 register WORD_LIST *list;
1507 s = dequote_string (list->word->word);
1508 free (list->word->word);
1509 list->word->word = s;
1515 make_quoted_char (c)
1535 /* Quote STRING. Return a new string. */
1537 quote_string (string)
1544 result = xmalloc (2);
1552 result = xmalloc ((strlen (string) * 2) + 1);
1554 for (t = result; string && *string; )
1564 /* De-quoted quoted characters in STRING. */
1566 dequote_string (string)
1572 result = xmalloc (strlen (string) + 1);
1574 if (QUOTED_NULL (string))
1580 /* If no character in the string can be quoted, don't bother examining
1581 each character. Just return a copy of the string passed to us. */
1582 if (strchr (string, CTLESC) == NULL) /* XXX */
1584 strcpy (result, string); /* XXX */
1585 return (result); /* XXX */
1588 for (t = result; string && *string; string++)
1590 if (*string == CTLESC)
1605 /* Quote the entire WORD_LIST list. */
1610 register WORD_LIST *w;
1612 for (w = list; w; w = w->next)
1614 char *t = w->word->word;
1615 w->word->word = quote_string (t);
1617 w->word->quoted = 1;
1621 /* **************************************************************** */
1623 /* Functions for Removing Patterns */
1625 /* **************************************************************** */
1627 /* Remove the portion of PARAM matched by PATTERN according to OP, where OP
1628 can have one of 4 values:
1629 RP_LONG_LEFT remove longest matching portion at start of PARAM
1630 RP_SHORT_LEFT remove shortest matching portion at start of PARAM
1631 RP_LONG_RIGHT remove longest matching portion at end of PARAM
1632 RP_SHORT_RIGHT remove shortest matching portion at end of PARAM
1635 #define RP_LONG_LEFT 1
1636 #define RP_SHORT_LEFT 2
1637 #define RP_LONG_RIGHT 3
1638 #define RP_SHORT_RIGHT 4
1641 remove_pattern (param, pattern, op)
1642 char *param, *pattern;
1645 register int len = param ? strlen (param) : 0;
1646 register char *end = param + len;
1647 register char *p, *ret, c;
1649 if (pattern == NULL || *pattern == '\0') /* minor optimization */
1650 return (savestring (param));
1652 if (param == NULL || *param == '\0')
1657 case RP_LONG_LEFT: /* remove longest match at start */
1658 for (p = end; p >= param; p--)
1661 if (fnmatch (pattern, param, 0) != FNM_NOMATCH)
1664 return (savestring (p));
1670 case RP_SHORT_LEFT: /* remove shortest match at start */
1671 for (p = param; p <= end; p++)
1674 if (fnmatch (pattern, param, 0) != FNM_NOMATCH)
1677 return (savestring (p));
1683 case RP_LONG_RIGHT: /* remove longest match at end */
1684 for (p = param; p <= end; p++)
1686 if (fnmatch (pattern, p, 0) != FNM_NOMATCH)
1690 ret = savestring (param);
1697 case RP_SHORT_RIGHT: /* remove shortest match at end */
1698 for (p = end; p >= param; p--)
1700 if (fnmatch (pattern, p, 0) != FNM_NOMATCH)
1704 ret = savestring (param);
1711 return (savestring (param)); /* no match, return original string */
1714 /*******************************************
1716 * Functions to expand WORD_DESCs *
1718 *******************************************/
1720 /* Expand WORD, performing word splitting on the result. This does
1721 parameter expansion, command substitution, arithmetic expansion,
1722 word splitting, and quote removal. */
1725 expand_word (word, quoted)
1729 WORD_LIST *result, *tresult;
1731 tresult = call_expand_word_internal (word, quoted, (int *)NULL, (int *)NULL);
1732 result = word_list_split (tresult);
1733 dispose_words (tresult);
1735 dequote_list (result);
1739 /* Expand WORD, but do not perform word splitting on the result. This
1740 does parameter expansion, command substitution, arithmetic expansion,
1741 and quote removal. */
1743 expand_word_no_split (word, quoted)
1749 result = call_expand_word_internal (word, quoted, (int *)NULL, (int *)NULL);
1751 dequote_list (result);
1755 /* Perform shell expansions on WORD, but do not perform word splitting or
1756 quote removal on the result. */
1758 expand_word_leave_quoted (word, quoted)
1764 result = call_expand_word_internal (word, quoted, (int *)NULL, (int *)NULL);
1768 /* Return the value of a positional parameter. This handles values > 10. */
1770 get_dollar_var_value (ind)
1777 if (dollar_vars[ind])
1778 temp = savestring (dollar_vars[ind]);
1780 temp = (char *)NULL;
1782 else /* We want something like ${11} */
1784 WORD_LIST *p = rest_of_args;
1790 temp = savestring (p->word->word);
1792 temp = (char *)NULL;
1797 #if defined (PROCESS_SUBSTITUTION)
1799 /* **************************************************************** */
1801 /* Hacking Process Substitution */
1803 /* **************************************************************** */
1805 extern struct fd_bitmap *current_fds_to_close;
1806 extern char *mktemp ();
1808 #if !defined (HAVE_DEV_FD)
1809 /* Named pipes must be removed explicitly with `unlink'. This keeps a list
1810 of FIFOs the shell has open. unlink_fifo_list will walk the list and
1811 unlink all of them. add_fifo_list adds the name of an open FIFO to the
1812 list. NFIFO is a count of the number of FIFOs in the list. */
1813 #define FIFO_INCR 20
1815 static char **fifo_list = (char **)NULL;
1816 static int nfifo = 0;
1817 static int fifo_list_size = 0;
1820 add_fifo_list (pathname)
1823 if (nfifo >= fifo_list_size - 1)
1825 fifo_list_size += FIFO_INCR;
1826 fifo_list = (char **)xrealloc (fifo_list,
1827 fifo_list_size * sizeof (char *));
1830 fifo_list[nfifo++] = savestring (pathname);
1841 unlink (fifo_list[nfifo]);
1842 free (fifo_list[nfifo]);
1843 fifo_list[nfifo] = (char *)NULL;
1853 tname = mktemp (savestring ("/tmp/sh-np-XXXXXX"));
1854 if (mkfifo (tname, 0600) < 0)
1857 return ((char *)NULL);
1860 add_fifo_list (tname);
1864 #if !defined (_POSIX_VERSION)
1870 #if defined (S_IFIFO)
1871 return (mknod (path, (mode | S_IFIFO), 0));
1872 #else /* !S_IFIFO */
1874 #endif /* !S_IFIFO */
1876 #endif /* !_POSIX_VERSION */
1878 #else /* HAVE_DEV_FD */
1880 /* DEV_FD_LIST is a bitmap of file descriptors attached to pipes the shell
1881 has open to children. NFDS is a count of the number of bits currently
1882 set in DEV_FD_LIST. TOTFDS is a count of the highest possible number
1884 static char *dev_fd_list = (char *)NULL;
1885 static int nfds = 0;
1886 static int totfds; /* The highest possible number of open files. */
1892 if (!dev_fd_list || fd >= totfds)
1897 totfds = getdtablesize ();
1898 if (totfds < 0 || totfds > 256)
1903 dev_fd_list = xrealloc (dev_fd_list, totfds);
1904 bzero (dev_fd_list + ofds, totfds - ofds);
1907 dev_fd_list[fd] = 1;
1919 for (i = 0; nfds && i < totfds; i++)
1930 #if defined (NOTDEF)
1931 print_dev_fd_list ()
1935 fprintf (stderr, "pid %d: dev_fd_list:", getpid ());
1938 for (i = 0; i < totfds; i++)
1941 fprintf (stderr, " %d", i);
1943 fprintf (stderr, "\n");
1948 make_dev_fd_filename (fd)
1953 ret = xmalloc (16 * sizeof (char));
1954 sprintf (ret, "/dev/fd/%d", fd);
1959 #endif /* HAVE_DEV_FD */
1961 /* Return a filename that will open a connection to the process defined by
1962 executing STRING. HAVE_DEV_FD, if defined, means open a pipe and return
1963 a filename in /dev/fd corresponding to a descriptor that is one of the
1964 ends of the pipe. If not defined, we use named pipes on systems that have
1965 them. Systems without /dev/fd and named pipes are out of luck.
1967 OPEN_FOR_READ_IN_CHILD, if 1, means open the named pipe for reading or
1968 use the read end of the pipe and dup that file descriptor to fd 0 in
1969 the child. If OPEN_FOR_READ_IN_CHILD is 0, we open the named pipe for
1970 writing or use the write end of the pipe in the child, and dup that
1971 file descriptor to fd 1 in the child. The parent does the opposite. */
1974 process_substitute (string, open_for_read_in_child)
1976 int open_for_read_in_child;
1981 #if defined (HAVE_DEV_FD)
1982 int parent_pipe_fd, child_pipe_fd;
1984 #endif /* HAVE_DEV_FD */
1985 #if defined (JOB_CONTROL)
1986 pid_t old_pipeline_pgrp;
1989 if (!string || !*string)
1990 return ((char *)NULL);
1992 #if !defined (HAVE_DEV_FD)
1993 pathname = make_named_pipe ();
1994 #else /* HAVE_DEV_FD */
1995 if (pipe (fildes) < 0)
1997 internal_error ("can't make pipes for process substitution: %s",
1999 return ((char *)NULL);
2001 /* If OPEN_FOR_READ_IN_CHILD == 1, we want to use the write end of
2002 the pipe in the parent, otherwise the read end. */
2003 parent_pipe_fd = fildes[open_for_read_in_child];
2004 child_pipe_fd = fildes[1 - open_for_read_in_child];
2005 pathname = make_dev_fd_filename (parent_pipe_fd);
2006 #endif /* HAVE_DEV_FD */
2010 internal_error ("cannot make pipe for process subsitution: %s",
2012 return ((char *)NULL);
2015 old_pid = last_made_pid;
2017 #if defined (JOB_CONTROL)
2018 old_pipeline_pgrp = pipeline_pgrp;
2019 pipeline_pgrp = shell_pgrp;
2020 cleanup_the_pipeline ();
2021 pid = make_child ((char *)NULL, 1);
2024 /* Cancel traps, in trap.c. */
2025 restore_original_signals ();
2026 setup_async_signals ();
2027 subshell_environment++;
2029 set_sigchld_handler ();
2030 stop_making_children ();
2031 pipeline_pgrp = old_pipeline_pgrp;
2032 #else /* !JOB_CONTROL */
2033 pid = make_child ((char *)NULL, 1);
2036 /* Cancel traps, in trap.c. */
2037 restore_original_signals ();
2038 setup_async_signals ();
2039 subshell_environment++;
2041 #endif /* !JOB_CONTROL */
2045 internal_error ("cannot make a child for process substitution: %s",
2048 #if defined (HAVE_DEV_FD)
2049 close (parent_pipe_fd);
2050 close (child_pipe_fd);
2051 #endif /* HAVE_DEV_FD */
2052 return ((char *)NULL);
2057 last_made_pid = old_pid;
2059 #if defined (JOB_CONTROL) && defined (PGRP_PIPE)
2061 #endif /* JOB_CONTROL && PGRP_PIPE */
2063 #if defined (HAVE_DEV_FD)
2064 close (child_pipe_fd);
2065 #endif /* HAVE_DEV_FD */
2070 set_sigint_handler ();
2072 #if defined (JOB_CONTROL)
2073 set_job_control (0);
2074 #endif /* JOB_CONTROL */
2076 #if !defined (HAVE_DEV_FD)
2077 /* Open the named pipe in the child. */
2078 fd = open (pathname, open_for_read_in_child ? O_RDONLY : O_WRONLY);
2081 internal_error ("cannot open named pipe %s for %s: %s", pathname,
2082 open_for_read_in_child ? "reading" : "writing", strerror (errno));
2085 #else /* HAVE_DEV_FD */
2087 #endif /* HAVE_DEV_FD */
2089 if (dup2 (fd, open_for_read_in_child ? 0 : 1) < 0)
2091 internal_error ("cannot duplicate named pipe %s as fd %d: %s",
2092 pathname, open_for_read_in_child ? 0 : 1, strerror (errno));
2098 /* Need to close any files that this process has open to pipes inherited
2100 if (current_fds_to_close)
2102 close_fd_bitmap (current_fds_to_close);
2103 current_fds_to_close = (struct fd_bitmap *)NULL;
2106 #if defined (HAVE_DEV_FD)
2107 /* Make sure we close the parent's end of the pipe and clear the slot
2108 in the fd list so it is not closed later, if reallocated by, for
2109 instance, pipe(2). */
2110 close (parent_pipe_fd);
2111 dev_fd_list[parent_pipe_fd] = 0;
2112 #endif /* HAVE_DEV_FD */
2114 result = parse_and_execute (string, "process substitution", 0);
2116 #if !defined (HAVE_DEV_FD)
2117 /* Make sure we close the named pipe in the child before we exit. */
2118 close (open_for_read_in_child ? 0 : 1);
2119 #endif /* !HAVE_DEV_FD */
2124 #endif /* PROCESS_SUBSTITUTION */
2126 /* Perform command substitution on STRING. This returns a string,
2129 command_substitute (string, quoted)
2135 char *istring = (char *)NULL;
2136 int istring_index, istring_size, c = 1;
2139 istring_index = istring_size = 0;
2141 /* Don't fork () if there is no need to. In the case of no command to
2142 run, just return NULL. */
2143 if (!string || !*string || (string[0] == '\n' && !string[1]))
2144 return ((char *)NULL);
2146 /* Pipe the output of executing STRING into the current shell. */
2147 if (pipe (fildes) < 0)
2149 internal_error ("Can't make pipes for command substitution!");
2153 old_pid = last_made_pid;
2154 #if defined (JOB_CONTROL)
2156 pid_t old_pipeline_pgrp = pipeline_pgrp;
2158 pipeline_pgrp = shell_pgrp;
2159 cleanup_the_pipeline ();
2160 pid = make_child ((char *)NULL, 0);
2162 /* Reset the signal handlers in the child, but don't free the
2164 reset_signal_handlers ();
2165 set_sigchld_handler ();
2166 stop_making_children ();
2167 pipeline_pgrp = old_pipeline_pgrp;
2169 #else /* !JOB_CONTROL */
2170 pid = make_child ((char *)NULL, 0);
2173 /* Reset the signal handlers in the child, but don't free the
2175 reset_signal_handlers ();
2176 #endif /* !JOB_CONTROL */
2180 internal_error ("Can't make a child for command substitution: %s",
2187 return ((char *)NULL);
2192 set_sigint_handler (); /* XXX */
2193 #if defined (JOB_CONTROL)
2194 set_job_control (0);
2196 if (dup2 (fildes[1], 1) < 0)
2199 ("command_substitute: cannot duplicate pipe as fd 1: %s",
2201 exit (EXECUTION_FAILURE);
2204 /* If standard output is closed in the parent shell
2205 (such as after `exec >&-'), file descriptor 1 will be
2206 the lowest available file descriptor, and end up in
2207 fildes[0]. This can happen for stdin and stderr as well,
2208 but stdout is more important -- it will cause no output
2209 to be generated from this command. */
2210 if ((fildes[1] != fileno (stdin)) &&
2211 (fildes[1] != fileno (stdout)) &&
2212 (fildes[1] != fileno (stderr)))
2215 if ((fildes[0] != fileno (stdin)) &&
2216 (fildes[0] != fileno (stdout)) &&
2217 (fildes[0] != fileno (stderr)))
2220 /* The currently executing shell is not interactive. */
2223 /* Command substitution does not inherit the -e flag. */
2224 exit_immediately_on_error = 0;
2226 remove_quoted_escapes (string);
2228 /* Give command substitution a place to jump back to on failure,
2229 so we don't go back up to main (). */
2230 result = setjmp (top_level);
2232 if (result == EXITPROG)
2233 exit (last_command_exit_value);
2235 exit (EXECUTION_FAILURE);
2237 exit (parse_and_execute (string, "command substitution", -1));
2243 istream = fdopen (fildes[0], "r");
2245 #if defined (JOB_CONTROL) && defined (PGRP_PIPE)
2247 #endif /* JOB_CONTROL && PGRP_PIPE */
2253 internal_error ("Can't reopen pipe to command substitution (fd %d): %s",
2254 fildes[0], strerror (errno));
2258 /* Read the output of the command through the pipe. */
2261 #if defined (NO_READ_RESTART_ON_SIGNAL)
2262 c = getc_with_restart (istream);
2265 #endif /* !NO_READ_RESTART_ON_SIGNAL */
2270 /* Add the character to ISTRING. */
2271 if (istring_index + 2 >= istring_size)
2273 while (istring_index + 2 >= istring_size)
2274 istring_size += DEFAULT_ARRAY_SIZE;
2275 istring = xrealloc (istring, istring_size);
2278 if (quoted || c == CTLESC || c == CTLNUL)
2279 istring[istring_index++] = CTLESC;
2281 istring[istring_index++] = c;
2282 istring[istring_index] = '\0';
2288 last_command_exit_value = wait_for (pid);
2289 last_command_subst_pid = pid;
2290 last_made_pid = old_pid;
2292 #if defined (JOB_CONTROL)
2293 /* If last_command_exit_value > 128, then the substituted command
2294 was terminated by a signal. If that signal was SIGINT, then send
2295 SIGINT to ourselves. This will break out of loops, for instance. */
2296 if (last_command_exit_value == (128 + SIGINT))
2297 kill (getpid (), SIGINT);
2299 /* wait_for gives the terminal back to shell_pgrp. If some other
2300 process group should have it, give it away to that group here. */
2301 if (interactive && pipeline_pgrp != (pid_t)0)
2302 give_terminal_to (pipeline_pgrp);
2303 #endif /* JOB_CONTROL */
2305 /* If we read no output, just return now and save ourselves some
2307 if (istring_index == 0)
2310 /* Strip trailing newlines from the output of the command. */
2313 while (istring_index > 0)
2315 if (istring[istring_index - 1] == '\n')
2319 /* If the newline was quoted, remove the quoting char. */
2320 if (istring[istring_index - 1] == CTLESC)
2326 istring[istring_index] = '\0';
2329 strip_trailing (istring, 1);
2335 /********************************************************
2337 * Utility functions for parameter expansion *
2339 ********************************************************/
2341 /* Handle removing a pattern from a string as a result of ${name%[%]value}
2342 or ${name#[#]value}. */
2344 parameter_brace_remove_pattern (value, temp, c)
2348 int pattern_specifier;
2350 char *pattern, *t, *tword;
2357 pattern_specifier = RP_LONG_LEFT;
2360 pattern_specifier = RP_SHORT_LEFT;
2367 pattern_specifier = RP_LONG_RIGHT;
2370 pattern_specifier = RP_SHORT_RIGHT;
2373 /* Posix.2 says that the WORD should be run through tilde expansion,
2374 parameter expansion, command substitution and arithmetic expansion.
2375 This leaves the result quoted, so quote_string_for_globbing () has
2376 to be called to fix it up for fnmatch (). */
2377 if (strchr (value, '~'))
2378 tword = tilde_expand (value);
2380 tword = savestring (value);
2382 /* expand_string_internal () leaves WORD quoted and does not perform
2384 l = expand_string_internal (tword, 0);
2386 pattern = string_list (l);
2391 tword = quote_string_for_globbing (pattern, 1);
2396 t = remove_pattern (temp, pattern, pattern_specifier);
2403 valid_brace_expansion_word (name, var_is_special)
2407 if (digit (*name) && all_digits (name))
2409 else if (var_is_special)
2411 else if (legal_identifier (name))
2416 /* Parameter expand NAME, and return a new string which is the expansion,
2417 or NULL if there was no expansion.
2418 VAR_IS_SPECIAL is non-zero if NAME is one of the special variables in
2419 the shell, e.g., "@", "$", "*", etc. QUOTED, if non-zero, means that
2420 NAME was found inside of a double-quoted expression. */
2422 parameter_brace_expand_word (name, var_is_special, quoted)
2424 int var_is_special, quoted;
2426 char *temp = (char *)NULL;
2428 /* Handle multiple digit arguments, as in ${11}. */
2431 int arg_index = atoi (name);
2433 temp = get_dollar_var_value (arg_index);
2435 else if (var_is_special) /* ${@} */
2440 tt = xmalloc (2 + strlen (name));
2441 tt[0] = '$'; tt[1] = '\0';
2442 strcpy (tt + 1, name);
2443 l = expand_string_leave_quoted (tt, quoted);
2445 temp = string_list (l);
2450 SHELL_VAR *var = find_variable (name);
2452 if (var && !invisible_p (var) && (temp = value_cell (var)))
2453 temp = quoted && temp && *temp ? quote_string (temp)
2454 : quote_escapes (temp);
2459 /* Expand the right side of a parameter expansion of the form ${NAMEcVALUE},
2460 depending on the value of C, the separating character. C can be one of
2461 "-", "+", or "=". */
2463 parameter_brace_expand_rhs (name, value, c, quoted)
2468 char *t, *t1, *temp;
2469 int i, lquote, hasdol;
2471 if (value[0] == '~' ||
2472 (strchr (value, '~') && unquoted_substring ("=~", value)))
2473 temp = tilde_expand (value);
2475 temp = savestring (value);
2477 /* This is a hack. A better fix is coming later. */
2479 if (*temp == '"' && temp[strlen (temp) - 1] == '"')
2482 t = string_extract_double_quoted (temp, &i); /* XXX */
2485 lquote = 1; /* XXX */
2488 /* XXX was quoted not lquote */
2489 l = *temp ? expand_string_for_rhs (temp, quoted||lquote, &hasdol, (int *)NULL)
2490 : (WORD_LIST *)NULL;
2492 /* expand_string_for_rhs does not dequote the word list it returns, but
2493 there are a few cases in which we need to add quotes. */
2494 if (lquote && quoted == 0 && hasdol == 0 && l && l->word->quoted == 0)
2499 temp = string_list (l);
2509 temp = (char *)NULL;
2511 if (c == '-' || c == '+')
2516 t = savestring (temp);
2518 t = savestring ("");
2519 t1 = dequote_string (t);
2521 bind_variable (name, t1);
2526 /* Deal with the right hand side of a ${name:?value} expansion in the case
2527 that NAME is null or not set. If VALUE is non-null it is expanded and
2528 used as the error message to print, otherwise a standard message is
2531 parameter_brace_expand_error (name, value)
2534 if (value && *value)
2536 WORD_LIST *l = expand_string (value, 0);
2537 char *temp1 = string_list (l);
2538 report_error ("%s: %s", name, temp1 ? temp1 : value);
2543 report_error ("%s: parameter null or not set", name);
2545 /* Free the data we have allocated during this expansion, since we
2546 are about to longjmp out. */
2551 /* Return 1 if NAME is something for which parameter_brace_expand_length is
2554 valid_length_expression (name)
2557 return (!name[1] || /* ${#} */
2558 ((name[1] == '@' || name[1] == '*') && !name[2]) || /* ${#@}, ${#*} */
2559 (digit (name[1]) && all_digits (name + 1)) || /* ${#11} */
2560 legal_identifier (name + 1)); /* ${#PS1} */
2563 /* Handle the parameter brace expansion that requires us to return the
2564 length of a parameter. */
2566 parameter_brace_expand_length (name)
2572 if (name[1] == '\0') /* ${#} */
2574 WORD_LIST *l = list_rest_of_args ();
2575 number = list_length (l);
2578 else if (name[1] != '*' && name[1] != '@')
2582 if (digit (name[1])) /* ${#1} */
2584 if (t = get_dollar_var_value (atoi (name + 1)))
2586 number = strlen (t);
2595 newname = savestring (name);
2597 list = expand_string (newname, 0);
2598 t = string_list (list);
2600 dispose_words (list);
2603 number = strlen (t);
2608 else /* ${#@} and ${#*} */
2610 #if !defined (KSH_INCOMPATIBLE)
2611 WORD_LIST *l = list_rest_of_args ();
2612 number = l ? list_length (l) : 0;
2615 if (t = string_rest_of_args (1))
2617 number = strlen (t);
2620 #endif /* KSH_INCOMPATIBLE */
2625 /* Make a word list which is the parameter and variable expansion,
2626 command substitution, arithmetic substitution, and quote removed
2627 expansion of WORD. Return a pointer to a WORD_LIST which is the
2628 result of the expansion. If WORD contains a null word, the word
2629 list returned is also null.
2631 QUOTED, when non-zero specifies that the text of WORD is treated
2632 as if it were surrounded by double quotes.
2633 CONTAINS_DOLLAR_AT and EXPANDED_SOMETHING are return values; when non-null
2634 they point to an integer value which receives information about expansion.
2635 CONTAINS_DOLLAR_AT gets non-zero if WORD contained "$@", else zero.
2636 EXPANDED_SOMETHING get non-zero if WORD contained any parameter expansions,
2639 This only does word splitting in the case of $@ expansion. In that
2640 case, we split on ' '. */
2642 /* Values for the local variable quoted_state. */
2644 #define PARTIALLY_QUOTED 1
2645 #define WHOLLY_QUOTED 2
2648 expand_word_internal (word, quoted, contains_dollar_at, expanded_something)
2651 int *contains_dollar_at;
2652 int *expanded_something;
2654 /* The thing that we finally output. */
2655 WORD_LIST *result = (WORD_LIST *)NULL;
2657 /* The intermediate string that we build while expanding. */
2658 char *istring = xmalloc (DEFAULT_ARRAY_SIZE);
2660 /* The current size of the above object. */
2661 int istring_size = DEFAULT_ARRAY_SIZE;
2663 /* Index into ISTRING. */
2664 int istring_index = 0;
2666 /* Temporary string storage. */
2667 char *temp = (char *)NULL;
2669 /* The text of WORD. */
2670 register char *string = word->word;
2672 /* The index into STRING. */
2675 /* This gets 1 if we see a $@ while quoted. */
2676 int quoted_dollar_at = 0;
2678 /* One of UNQUOTED, PARTIALLY_QUOTED, or WHOLLY_QUOTED, depending on
2679 whether WORD contains no quoting characters, a partially quoted
2680 string (e.g., "xx"ab), or is fully quoted (e.g., "xxab"). */
2681 int quoted_state = UNQUOTED;
2683 register int c; /* Current character. */
2684 int number; /* Temporary number value. */
2685 int t_index; /* For calls to string_extract_xxx. */
2686 char *command_subst_result; /* For calls to command_substitute (). */
2690 if (!string) goto final_exit;
2692 if (contains_dollar_at)
2693 *contains_dollar_at = 0;
2695 /* Begin the expansion. */
2701 /* Case on toplevel character. */
2705 goto finished_with_string;
2710 temp[1] = c = string[++sindex];
2718 #if defined (PROCESS_SUBSTITUTION)
2719 /* Process substitution. */
2726 if (string[++sindex] != '(' || quoted || posixly_correct)
2732 old_index = ++sindex; /* skip past both '<' and '(' */
2734 temp1 = extract_process_subst
2735 (string, (c == '<') ? "<(" : ">(", &old_index);
2738 /* If the process substitution specification is `<()', we want to
2739 open the pipe for writing in the child and produce output; if
2740 it is `>()', we want to open the pipe for reading in the child
2741 and consume input. */
2742 temp = process_substitute (temp1, (c == '>'));
2746 goto dollar_add_string;
2748 #endif /* PROCESS_SUBSTITUTION */
2750 /* See about breaking this into a separate function:
2752 param_expand (string, sindex, quoted, expanded_something,
2753 contains_dollar_at, quoted_dollar_at)
2755 int *sindex, quoted, *expanded_something, *contains_dollar_at;
2756 int *quoted_dollar_at;
2760 if (expanded_something)
2761 *expanded_something = 1;
2763 c = string[++sindex];
2765 /* Do simple cases first. Switch on what follows '$'. */
2779 temp = dollar_vars[digit_value (c)];
2780 if (unbound_vars_is_error && temp == (char *)NULL)
2782 report_error ("$%c: unbound variable", c);
2785 last_command_exit_value = 1;
2786 return (&expand_word_error);
2789 temp = savestring (temp);
2790 goto dollar_add_string;
2792 /* $$ -- pid of the invoking shell. */
2794 number = dollar_dollar_pid;
2797 temp = itos (number);
2799 if (string[sindex]) sindex++;
2801 /* Add TEMP to ISTRING. */
2803 istring = sub_append_string
2804 (temp, istring, &istring_index, &istring_size);
2805 temp = (char *)NULL;
2808 /* $# -- number of positional parameters. */
2811 WORD_LIST *list = list_rest_of_args ();
2812 number = list_length (list);
2813 dispose_words (list);
2817 /* $? -- return value of the last synchronous command. */
2819 number = last_command_exit_value;
2822 /* $- -- flags supplied to the shell on invocation or
2825 temp = which_set_flags ();
2826 goto dollar_add_string;
2828 /* $! -- Pid of the last asynchronous command. */
2830 number = (int)last_asynchronous_pid;
2832 /* If no asynchronous pids have been created, echo nothing. */
2833 if (number == (int)NO_PID)
2837 if (expanded_something)
2838 *expanded_something = 0;
2843 /* The only difference between this and $@ is when the
2845 case '*': /* `$*' */
2846 temp = string_rest_of_args (quoted);
2848 if (quoted && temp && *temp == '\0' /* && istring_index > 0 */)
2851 temp = (char *)NULL;
2854 /* In the case of a quoted string, quote the entire arg-list.
2858 char *james_brown = temp;
2859 temp = quote_string (temp);
2862 goto dollar_add_string;
2864 /* When we have "$@" what we want is "$1" "$2" "$3" ... This
2865 means that we have to turn quoting off after we split into
2866 the individually quoted arguments so that the final split
2867 on the first character of $IFS is still done. */
2868 case '@': /* `$@' */
2870 WORD_LIST *tlist = list_rest_of_args ();
2871 if (quoted && tlist)
2874 /* We want to flag the fact that we saw this. We can't turn
2875 off quoting entirely, because other characters in the
2876 string might need it (consider "\"$@\""), but we need some
2877 way to signal that the final split on the first character
2878 of $IFS should be done, even though QUOTED is 1. */
2880 quoted_dollar_at = 1;
2881 if (contains_dollar_at)
2882 *contains_dollar_at = 1;
2883 temp = string_list (tlist);
2884 dispose_words (tlist);
2885 goto dollar_add_string;
2888 /* ${[#]name[[:]#[#]%[%]-=?+[word]]} */
2891 int check_nullness = 0;
2893 int var_is_null = 0;
2894 int var_is_special = 0;
2898 name = string_extract (string, &t_index, "#%:-=?+}");
2899 value = (char *)NULL;
2901 /* If the name really consists of a special variable, then
2902 make sure that we have the entire name. */
2903 if (sindex == t_index &&
2904 (string[sindex] == '-' ||
2905 string[sindex] == '?' ||
2906 string[sindex] == '#'))
2911 tt = string_extract (string, &t_index, "#%:-=?+}");
2912 name = xmalloc (2 + (strlen (tt)));
2913 *name = string[sindex];
2914 strcpy (name + 1, tt);
2919 /* Find out what character ended the variable name. Then
2920 do the appropriate thing. */
2921 if (c = string[sindex])
2927 if (c = string[sindex])
2931 /* Determine the value of this variable. */
2932 if ((digit (*name) && all_digits (name)) ||
2933 (strlen (name) == 1 && member (*name, "#-?$!@*")))
2936 /* Check for special expansion things. */
2939 /* Handle ${#-} and ${#?}. They return the lengths of
2940 $- and $?, respectively. */
2941 if (string[sindex] == '}' &&
2944 (c == '-' || c == '?'))
2951 s = which_set_flags ();
2953 s = itos (last_command_exit_value);
2955 number = STRLEN (s);
2960 /* Don't allow things like ${#:-foo} to go by; they are
2961 errors. If we are not pointing at the character just
2962 after the closing brace, then we haven't gotten all of
2963 the name. Since it begins with a special character,
2964 this is a bad substitution. Explicitly check for ${#:},
2965 which the rules do not catch. */
2966 if (string[sindex - 1] != '}' || member (c, "?-=+") ||
2967 (string[sindex - 1] == '}' && !name[1] && c == '}' &&
2972 goto bad_substitution;
2975 /* Check NAME for validity before trying to go on. */
2976 if (!valid_length_expression (name))
2980 goto bad_substitution;
2983 number = parameter_brace_expand_length (name);
2985 /* We are pointing one character after the brace which
2986 closes this expression. Since the code at add_number
2987 increments SINDEX, we back up a single character. */
2992 /* ${@} is identical to $@. */
2993 if (name[0] == '@' && name[1] == '\0')
2996 quoted_dollar_at = 1;
2998 if (contains_dollar_at)
2999 *contains_dollar_at = 1;
3002 /* Make sure that NAME is valid before trying to go on. */
3003 if (!valid_brace_expansion_word (name, var_is_special))
3007 goto bad_substitution;
3011 parameter_brace_expand_word (name, var_is_special, quoted);
3016 if (!var_is_set || !temp || !*temp)
3019 if (!check_nullness)
3022 /* Get the rest of the stuff inside the braces. */
3025 /* Extract the contents of the ${ ... } expansion
3026 according to the Posix.2 rules. It's much less of
3027 a hack that the former extract_delimited_string ()
3029 value = extract_dollar_brace_string (string, &sindex);
3031 if (string[sindex] == '}')
3037 goto bad_substitution;
3041 value = (char *)NULL;
3043 /* Do the right thing based on which character ended the
3054 report_error ("%s: bad substitution", name ? name : "??");
3059 return &expand_word_error;
3062 if (!var_is_set && unbound_vars_is_error)
3064 report_error ("%s: unbound variable", name);
3069 last_command_exit_value = 1;
3071 return &expand_word_error;
3075 case '#': /* ${param#[#]pattern} */
3076 case '%': /* ${param%[%]pattern} */
3079 if (!value || !*value || !temp || !*temp)
3083 t = dequote_string (temp);
3087 t = parameter_brace_remove_pattern (value, temp, c);
3098 if (var_is_set && !var_is_null)
3100 /* We don't want the value of the named variable for
3101 anything, just the value of the right hand side. */
3107 temp = parameter_brace_expand_rhs
3108 (name, value, c, quoted);
3109 /* XXX - this is a hack. A better fix is
3111 if ((value[0] == '$' && value[1] == '@') ||
3112 (value[0] == '"' && value[1] == '$' && value[2] == '@'))
3116 if (contains_dollar_at)
3117 *contains_dollar_at = 1;
3122 temp = (char *)NULL;
3128 /* Otherwise do nothing; just use the value in TEMP. */
3130 else /* VAR not set or VAR is NULL. */
3133 temp = (char *)NULL;
3134 if (c == '=' && var_is_special)
3137 ("$%s: cannot assign in this way", name);
3142 return &expand_word_error;
3148 parameter_brace_expand_error (name, value);
3150 return &expand_word_fatal;
3152 return &expand_word_error;
3155 temp = parameter_brace_expand_rhs
3156 (name, value, c, quoted);
3160 } /* end case on closing character. */
3163 } /* end case '{' */
3166 /* Do command or arithmetic substitution. */
3168 /* We have to extract the contents of this paren substitution. */
3170 int old_index = ++sindex;
3172 temp = extract_command_subst (string, &old_index);
3175 /* For Posix.2-style `$(( ))' arithmetic substitution,
3176 extract the expression and pass it to the evaluator. */
3177 if (temp && *temp == '(')
3180 int last = strlen (t) - 1;
3184 report_error ("%s: bad arithmetic substitution", temp);
3188 return &expand_word_error;
3191 /* Cut off ending `)' */
3194 /* Expand variables found inside the expression. */
3198 l = expand_string (t, 1);
3199 t = string_list (l);
3203 /* No error messages. */
3204 this_command_name = (char *)NULL;
3206 number = evalexp (t);
3213 goto handle_command_substitution;
3216 /* Do straight arithmetic substitution. */
3218 /* We have to extract the contents of this
3219 arithmetic substitution. */
3222 int old_index = ++sindex;
3225 temp = extract_arithmetic_subst (string, &old_index);
3228 /* Do initial variable expansion. */
3229 l = expand_string (temp, 1);
3230 t = string_list (l);
3233 /* No error messages. */
3234 this_command_name = (char *)NULL;
3235 number = evalexp (t);
3244 /* Find the variable in VARIABLE_LIST. */
3249 temp = (char *)NULL;
3251 for (old_index = sindex;
3252 (c = string[sindex]) &&
3253 (isletter (c) || digit (c) || c == '_');
3255 name = substring (string, old_index, sindex);
3257 /* If this isn't a variable name, then just output the `$'. */
3258 if (!name || !*name)
3261 temp = savestring ("$");
3262 if (expanded_something)
3263 *expanded_something = 0;
3267 /* If the variable exists, return its value cell. */
3268 var = find_variable (name);
3270 if (var && !invisible_p (var) && value_cell (var))
3272 temp = value_cell (var);
3273 temp = quoted && temp && *temp ? quote_string (temp)
3274 : quote_escapes (temp);
3279 temp = (char *)NULL;
3281 if (unbound_vars_is_error)
3282 report_error ("%s: unbound variable", name);
3291 last_command_exit_value = 1;
3293 return &expand_word_error;
3296 break; /* End case '$': */
3298 case '`': /* Backquoted command substitution. */
3302 if (expanded_something)
3303 *expanded_something = 1;
3305 temp = string_extract (string, &sindex, "`");
3306 de_backslash (temp);
3308 handle_command_substitution:
3309 command_subst_result = command_substitute (temp, quoted);
3313 temp = command_subst_result;
3322 if (string[sindex + 1] == '\n')
3329 char *slashify_chars = "";
3331 c = string[++sindex];
3333 if (quoted == Q_HERE_DOCUMENT)
3334 slashify_chars = slashify_in_here_document;
3335 else if (quoted == Q_DOUBLE_QUOTES)
3336 slashify_chars = slashify_in_quotes;
3338 if (quoted && !member (c, slashify_chars))
3341 temp[0] = '\\'; temp[1] = c; temp[2] = '\0';
3348 /* This character is quoted, so add it in quoted mode. */
3349 temp = make_quoted_char (c);
3361 WORD_LIST *tresult = (WORD_LIST *)NULL;
3364 temp = string_extract_double_quoted (string, &sindex);
3366 /* If the quotes surrounded the entire string, then the
3367 whole word was quoted. */
3368 if (t_index == 1 && !string[sindex])
3369 quoted_state = WHOLLY_QUOTED;
3371 quoted_state = PARTIALLY_QUOTED;
3376 int quoting_flags = Q_DOUBLE_QUOTES;
3377 WORD_DESC *temp_word = make_word (temp);
3381 tresult = expand_word_internal
3382 (temp_word, quoting_flags, &dollar_at_flag, (int *)NULL);
3384 if (tresult == &expand_word_error || tresult == &expand_word_fatal)
3388 /* expand_word_internal has already freed temp_word->word
3389 for us because of the way it prints error messages. */
3390 temp_word->word = (char *)NULL;
3391 dispose_word (temp_word);
3395 dispose_word (temp_word);
3397 /* "$@" (a double-quoted dollar-at) expands into nothing,
3398 not even a NULL word, when there are no positional
3400 if (!tresult && dollar_at_flag)
3406 /* If we get "$@", we know we have expanded something, so we
3407 need to remember it for the final split on $IFS. This is
3408 a special case; it's the only case where a quoted string
3409 can expand into more than one word. It's going to come back
3410 from the above call to expand_word_internal as a list with
3411 a single word, in which all characters are quoted and
3412 separated by blanks. What we want to do is to turn it back
3413 into a list for the next piece of code. */
3414 dequote_list (tresult);
3419 if (expanded_something)
3420 *expanded_something = 1;
3425 /* What we have is "". This is a minor optimization. */
3427 tresult = (WORD_LIST *)NULL;
3430 /* The code above *might* return a list (consider the case of "$@",
3431 where it returns "$1", "$2", etc.). We can't throw away the
3432 rest of the list, and we have to make sure each word gets added
3433 as quoted. We test on tresult->next: if it is non-NULL, we
3434 quote the whole list, save it to a string with string_list, and
3435 add that string. We don't need to quote the results of this
3436 (and it would be wrong, since that would quote the separators
3437 as well), so we go directly to add_string. */
3442 quote_list (tresult);
3443 temp = string_list (tresult);
3444 dispose_words (tresult);
3449 temp = savestring (tresult->word->word);
3450 dispose_words (tresult);
3454 temp = (char *)NULL;
3456 /* We do not want to add quoted nulls to strings that are only
3457 partially quoted; we can throw them away. */
3458 if (!temp && (quoted_state == PARTIALLY_QUOTED))
3466 temp = quote_string (temp);
3487 temp = string_extract_single_quoted (string, &sindex);
3489 /* If the entire STRING was surrounded by single quotes,
3490 then the string is wholly quoted. */
3491 if (t_index == 1 && !string[sindex])
3492 quoted_state = WHOLLY_QUOTED;
3494 quoted_state = PARTIALLY_QUOTED;
3496 /* If all we had was '', it is a null expansion. */
3500 temp = (char *)NULL;
3503 remove_quoted_escapes (temp);
3505 /* We do not want to add quoted nulls to strings that are only
3506 partially quoted; such nulls are discarded. */
3507 if (!temp && (quoted_state == PARTIALLY_QUOTED))
3510 goto add_quoted_string;
3520 /* This is the fix for " $@ " */
3523 temp = make_quoted_char (c);
3530 if (istring_index + 1 >= istring_size)
3532 while (istring_index + 1 >= istring_size)
3533 istring_size += DEFAULT_ARRAY_SIZE;
3534 istring = xrealloc (istring, istring_size);
3536 istring[istring_index++] = c;
3537 istring[istring_index] = '\0';
3539 /* Next character. */
3544 finished_with_string:
3546 /* OK, we're ready to return. If we have a quoted string, and
3547 quoted_dollar_at is not set, we do no splitting at all; otherwise
3548 we split on ' '. The routines that call this will handle what to
3549 do if nothing has been expanded. */
3552 WORD_LIST *temp_list;
3554 /* Partially and wholly quoted strings which expand to the empty
3555 string are retained as an empty arguments. Unquoted strings
3556 which expand to the empty string are discarded. The single
3557 exception is the case of expanding "$@" when there are no
3558 positional parameters. In that case, we discard the expansion. */
3560 /* Because of how the code that handles "" and '' in partially
3561 quoted strings works, we need to make ISTRING into a QUOTED_NULL
3562 if we saw quoting characters, but the expansion was empty.
3563 "" and '' are tossed away before we get to this point when
3564 processing partially quoted strings. This makes "" and $xxx""
3565 equivalent when xxx is unset. */
3566 if (!*istring && quoted_state == PARTIALLY_QUOTED)
3568 if (istring_size < 2)
3569 istring = xrealloc (istring, istring_size += 2);
3570 istring[0] = CTLNUL;
3574 /* If we expand to nothing and there were no single or double quotes
3575 in the word, we throw it away. Otherwise, we return a NULL word.
3576 The single exception is for $@ surrounded by double quotes when
3577 there are no positional parameters. In that case, we also throw
3581 if (quoted_state == UNQUOTED ||
3582 (quoted_dollar_at && quoted_state == WHOLLY_QUOTED))
3583 temp_list = (WORD_LIST *)NULL;
3586 temp_list = make_word_list
3587 (make_word (istring), (WORD_LIST *)NULL);
3588 temp_list->word->quoted = quoted;
3591 else if (word->assignment)
3593 temp_list = make_word_list (make_word (istring), (WORD_LIST *)NULL);
3594 temp_list->word->quoted = quoted;
3595 temp_list->word->assignment = assignment (temp_list->word->word);
3599 char *ifs_chars = (char *)NULL;
3601 if (quoted_dollar_at)
3603 SHELL_VAR *ifs = find_variable ("IFS");
3605 ifs_chars = value_cell (ifs);
3607 ifs_chars = " \t\n";
3610 /* According to Posix.2, "$@" expands to a single word if
3611 IFS="" and the positional parameters are not empty. */
3612 if (quoted_dollar_at && ifs_chars && *ifs_chars)
3614 temp_list = list_string (istring, " ", 1);
3616 /* This turns quoted null strings back into CTLNULs */
3617 dequote_list (temp_list);
3618 quote_list (temp_list);
3624 tword = make_word (istring);
3625 temp_list = make_word_list (tword, (WORD_LIST *)NULL);
3626 tword->quoted = quoted || (quoted_state == WHOLLY_QUOTED);
3627 tword->assignment = word->assignment;
3632 result = (WORD_LIST *)
3633 list_append (REVERSE_LIST (result, WORD_LIST *), temp_list);
3636 result = (WORD_LIST *)NULL;
3641 /* **************************************************************** */
3643 /* Functions for Quote Removal */
3645 /* **************************************************************** */
3647 /* Perform quote removal on STRING. If QUOTED > 0, assume we are obeying the
3648 backslash quoting rules for within double quotes. */
3650 string_quote_removal (string, quoted)
3654 char *r, *result_string, *temp, *temp1;
3655 int sindex, tindex, c, dquote;
3657 /* The result can be no longer than the original string. */
3658 r = result_string = xmalloc (strlen (string) + 1);
3660 for (sindex = dquote = 0; c = string[sindex];)
3665 c = string[++sindex];
3666 if ((quoted || dquote) && !member (c, slashify_in_quotes))
3675 if (quoted || dquote)
3683 temp = string_extract_single_quoted (string, &tindex);
3696 dquote = 1 - dquote;
3702 return (result_string);
3705 /* Perform quote removal on word WORD. This allocates and returns a new
3708 word_quote_removal (word, quoted)
3715 t = string_quote_removal (word->word, quoted);
3720 /* Perform quote removal on all words in LIST. If QUOTED is non-zero,
3721 the members of the list are treated as if they are surrounded by
3722 double quotes. Return a new list, or NULL if LIST is NULL. */
3724 word_list_quote_removal (list, quoted)
3728 WORD_LIST *result = (WORD_LIST *)NULL, *t, *tresult;
3733 tresult = (WORD_LIST *)xmalloc (sizeof (WORD_LIST));
3734 tresult->word = word_quote_removal (t->word, quoted);
3735 tresult->next = (WORD_LIST *)NULL;
3736 result = (WORD_LIST *) list_append (result, tresult);
3742 /* Return 1 if CHARACTER appears in an unquoted portion of
3743 STRING. Return 0 otherwise. */
3745 unquoted_member (character, string)
3749 int sindex, tindex, c;
3754 while (c = string[sindex])
3772 temp = string_extract_double_quoted (string, &tindex);
3774 temp = string_extract_single_quoted (string, &tindex);
3788 /* Return 1 if SUBSTR appears in an unquoted portion of STRING. */
3790 unquoted_substring (substr, string)
3791 char *substr, *string;
3793 int sindex, tindex, c, sublen;
3796 if (!substr || !*substr)
3799 sublen = strlen (substr);
3802 while (c = string[sindex])
3804 if (STREQN (string + sindex, substr, sublen))
3822 temp = string_extract_double_quoted (string, &tindex);
3824 temp = string_extract_single_quoted (string, &tindex);
3839 /*******************************************
3841 * Functions to perform word splitting *
3843 *******************************************/
3845 /* This splits a single word into a WORD LIST on $IFS, but only if the word
3846 is not quoted. list_string () performs quote removal for us, even if we
3847 don't do any splitting. */
3856 SHELL_VAR *ifs = find_variable ("IFS");
3859 /* If IFS is unset, it defaults to " \t\n". */
3861 ifs_chars = value_cell (ifs);
3863 ifs_chars = " \t\n";
3865 if (w->quoted || !ifs_chars)
3868 #ifdef NOT_YET_MAYBE_LATER
3871 /* No splitting done if word quoted or ifs set to "". */
3873 wtemp = make_word (w->word);
3874 wtemp->quoted = w->quoted;
3875 result = make_word_list (wtemp);
3879 result = list_string (w->word, ifs_chars, w->quoted);
3882 result = (WORD_LIST *)NULL;
3886 /* Perform word splitting on LIST and return the RESULT. It is possible
3887 to return (WORD_LIST *)NULL. */
3889 word_list_split (list)
3892 WORD_LIST *result = (WORD_LIST *)NULL, *t, *tresult;
3897 tresult = word_split (t->word);
3898 result = (WORD_LIST *) list_append (result, tresult);
3904 /**************************************************
3906 * Functions to expand an entire WORD_LIST *
3908 **************************************************/
3910 static WORD_LIST *varlist = (WORD_LIST *)NULL;
3912 /* Separate out any initial variable assignments from TLIST. If set -k has
3913 been executed, remove all assignment statements from TLIST. Initial
3914 variable assignments and other environment assignments are placed
3917 separate_out_assignments (tlist)
3920 register WORD_LIST *vp, *lp;
3923 return ((WORD_LIST *)NULL);
3925 varlist = (WORD_LIST *)NULL;
3928 /* Separate out variable assignments at the start of the command.
3929 Loop invariant: vp->next == lp
3931 lp = list of words left after assignment statements skipped
3932 tlist = original list of words
3934 while (lp && lp->word->assignment)
3940 /* If lp != tlist, we have some initial assignment statements. */
3941 /* We make VARLIST point to the list of assignment words and
3942 TLIST point to the remaining words. */
3946 /* ASSERT(vp->next == lp); */
3947 vp->next = (WORD_LIST *)NULL; /* terminate variable list */
3948 tlist = lp; /* remainder of word list */
3951 /* vp == end of variable list */
3952 /* tlist == remainder of original word list without variable assignments */
3954 /* All the words in tlist were assignment statements */
3955 return ((WORD_LIST *)NULL);
3957 /* ASSERT(tlist != NULL); */
3958 /* ASSERT(tlist->word->assignment == 0); */
3960 /* If the -k option is in effect, we need to go through the remaining
3961 words, separate out the assignment words, and place them on VARLIST. */
3962 if (place_keywords_in_env)
3964 WORD_LIST *tp; /* tp == running pointer into tlist */
3969 /* Loop Invariant: tp->next == lp */
3970 /* Loop postcondition: tlist == word list without assignment statements */
3973 if (lp->word->assignment)
3975 /* Found an assignment statement, add this word to end of
3985 /* Remove the word pointed to by LP from TLIST. */
3986 tp->next = lp->next;
3987 /* ASSERT(vp == lp); */
3988 lp->next = (WORD_LIST *)NULL;
4001 /* Take the list of words in LIST and do the various substitutions. Return
4002 a new list of words which is the expanded list, and without things like
4003 variable assignments. */
4009 return (expand_words_internal (list, 1));
4012 /* Same as expand_words (), but doesn't hack variable or environment
4015 expand_words_no_vars (list)
4018 return (expand_words_internal (list, 0));
4021 /* Non-zero means to allow unmatched globbed filenames to expand to
4023 static int allow_null_glob_expansion = 0;
4025 /* The workhorse for expand_words () and expand_words_no_var ().
4026 First arg is LIST, a WORD_LIST of words.
4027 Second arg DO_VARS is non-zero if you want to do environment and
4028 variable assignments, else zero.
4030 This does all of the substitutions: brace expansion, tilde expansion,
4031 parameter expansion, command substitution, arithmetic expansion,
4032 process substitution, word splitting, and pathname expansion.
4033 Words with the `quoted' or `assignment' bits set, or for which no
4034 expansion is done, do not undergo word splitting. Words with the
4035 `assignment' but set do not undergo pathname expansion. */
4037 expand_words_internal (list, do_vars)
4041 register WORD_LIST *tlist, *new_list = (WORD_LIST *)NULL;
4042 WORD_LIST *orig_list;
4045 return ((WORD_LIST *)NULL);
4047 tlist = copy_word_list (list);
4051 tlist = separate_out_assignments (tlist);
4056 /* All the words were variable assignments, so they are placed
4057 into the shell's environment. */
4058 register WORD_LIST *lp;
4059 for (lp = varlist; lp; lp = lp->next)
4060 do_assignment (lp->word->word);
4061 dispose_words (varlist);
4062 varlist = (WORD_LIST *)NULL;
4064 return ((WORD_LIST *)NULL);
4068 /* Begin expanding the words that remain. The expansions take place on
4069 things that aren't really variable assignments. */
4071 #if defined (BRACE_EXPANSION)
4072 /* Do brace expansion on this word if there are any brace characters
4074 if (!no_brace_expansion)
4076 register char **expansions;
4077 WORD_LIST *braces = (WORD_LIST *)NULL, *disposables = (WORD_LIST *)NULL;
4086 /* Only do brace expansion if the word has a brace character. If
4087 not, just add the word list element to BRACES and continue. In
4088 the common case, at least when running shell scripts, this will
4089 degenerate to a bunch of calls to `strchr', and then what is
4090 basically a reversal of TLIST into BRACES, which is corrected
4091 by a call to reverse_list () on BRACES when the end of TLIST
4093 if (strchr (tlist->word->word, '{'))
4095 expansions = brace_expand (tlist->word->word);
4097 for (eindex = 0; expansions[eindex]; eindex++)
4099 braces = make_word_list (make_word (expansions[eindex]),
4101 free (expansions[eindex]);
4105 /* Add TLIST to the list of words to be freed after brace
4106 expansion has been performed. */
4107 tlist->next = disposables;
4108 disposables = tlist;
4112 tlist->next = braces;
4119 dispose_words (disposables);
4120 tlist = REVERSE_LIST (braces, WORD_LIST *);
4122 #endif /* BRACE_EXPANSION */
4126 /* We do tilde expansion all the time. This is what 1003.2 says. */
4129 register char *current_word;
4130 WORD_LIST *expanded, *t, *reversed, *next;
4131 int expanded_something = 0;
4133 current_word = tlist->word->word;
4137 /* Posix.2 section 3.6.1 says that tildes following `=' in words
4138 which are not assignment statements are not expanded. We do
4139 this only if POSIXLY_CORRECT is enabled. */
4140 if (current_word[0] == '~' ||
4141 (!posixly_correct && strchr (current_word, '~') &&
4142 unquoted_substring ("=~", current_word)))
4146 tt = tlist->word->word;
4147 tlist->word->word = tilde_expand (tt);
4151 expanded = expand_word_internal
4152 (tlist->word, 0, (int *)NULL, &expanded_something);
4154 if (expanded == &expand_word_error || expanded == &expand_word_fatal)
4156 /* By convention, each time this error is returned,
4157 tlist->word->word has already been freed. */
4158 tlist->word->word = (char *)NULL;
4160 /* Dispose our copy of the original list. */
4161 dispose_words (orig_list);
4162 /* Dispose the new list we're building. */
4163 dispose_words (new_list);
4165 if (expanded == &expand_word_error)
4166 longjmp (top_level, DISCARD);
4168 longjmp (top_level, FORCE_EOF);
4171 /* Don't split assignment words, even when they do not precede a
4173 if (expanded_something && tlist->word->assignment == 0)
4175 t = word_list_split (expanded);
4176 dispose_words (expanded);
4180 /* If no parameter expansion, command substitution, process
4181 substitution, or arithmetic substitution took place, then
4182 do not do word splitting. We still have to remove quoted
4183 null characters from the result. */
4184 word_list_remove_quoted_nulls (expanded);
4188 /* In the most common cases, t will be a list containing only one
4189 element, so the call to reverse_list would be wasted. */
4190 reversed = REVERSE_LIST (t, WORD_LIST *);
4191 new_list = (WORD_LIST *)list_append (reversed, new_list);
4196 new_list = REVERSE_LIST (new_list, WORD_LIST *);
4198 dispose_words (orig_list);
4200 #if defined (USE_POSIX_GLOB_LIBRARY)
4201 # define GLOB_FAILED(glist) !(glist)
4202 #else /* !USE_POSIX_GLOB_LIBRARY */
4203 # define GLOB_FAILED(glist) (glist) == (char **)&glob_error_return
4204 #endif /* !USE_POSIX_GLOB_LIBRARY */
4206 /* Okay, we're almost done. Now let's just do some filename
4210 char **temp_list = (char **)NULL;
4211 register int list_index;
4212 WORD_LIST *glob_list, *disposables;
4214 orig_list = disposables = (WORD_LIST *)NULL;
4217 /* orig_list == output list, despite the name. */
4218 if (!disallow_filename_globbing)
4222 /* For each word, either globbing is attempted or the word is
4223 added to orig_list. If globbing succeeds, the results are
4224 added to orig_list and the word (tlist) is added to the list
4225 of disposable words. If globbing fails and failed glob
4226 expansions are left unchanged (the shell default), the
4227 original word is added to orig_list. If globbing fails and
4228 failed glob expansions are removed, the original word is
4229 added to the list of disposable words. orig_list ends up
4230 in reverse order and requires a call to reverse_list to
4231 be set right. After all words are examined, the disposable
4237 /* If the word isn't quoted and there is an unquoted pattern
4238 matching character in the word, then glob it. */
4239 if (!tlist->word->quoted && !tlist->word->assignment &&
4240 unquoted_glob_pattern_p (tlist->word->word))
4242 temp_list = shell_glob_filename (tlist->word->word);
4244 /* Handle error cases.
4245 I don't think we should report errors like "No such file
4246 or directory". However, I would like to report errors
4247 like "Read failed". */
4249 if (GLOB_FAILED (temp_list))
4251 temp_list = (char **) xmalloc (sizeof (char *));
4252 temp_list[0] = (char *)NULL;
4255 /* Dequote the current word in case we have to use it. */
4258 register char *t = dequote_string (tlist->word->word);
4259 free (tlist->word->word);
4260 tlist->word->word = t;
4263 /* Make the array into a word list. */
4264 glob_list = (WORD_LIST *)NULL;
4265 for (list_index = 0; temp_list[list_index]; list_index++)
4266 glob_list = make_word_list
4267 (make_word (temp_list[list_index]), glob_list);
4271 orig_list = (WORD_LIST *)list_append
4272 (glob_list, orig_list);
4273 tlist->next = disposables;
4274 disposables = tlist;
4277 if (!allow_null_glob_expansion)
4279 /* Failed glob expressions are left unchanged. */
4280 tlist->next = orig_list;
4285 /* Failed glob expressions are removed. */
4286 tlist->next = disposables;
4287 disposables = tlist;
4292 /* Dequote the string. */
4293 register char *t = dequote_string (tlist->word->word);
4294 free (tlist->word->word);
4295 tlist->word->word = t;
4296 tlist->next = orig_list;
4300 free_array (temp_list);
4301 temp_list = (char **)NULL;
4307 dispose_words (disposables);
4309 new_list = REVERSE_LIST (orig_list, WORD_LIST *);
4313 /* Dequote the words, because we're not performing globbing. */
4314 register WORD_LIST *wl = new_list;
4318 wp = dequote_string (wl->word->word);
4319 free (wl->word->word);
4320 wl->word->word = wp;
4328 register WORD_LIST *lp;
4329 Function *assign_func;
4331 /* If the remainder of the words expand to nothing, Posix.2 requires
4332 that the variable and environment assignments affect the shell's
4334 assign_func = new_list ? assign_in_env : do_assignment;
4336 for (lp = varlist; lp; lp = lp->next)
4337 (*assign_func) (lp->word->word);
4339 dispose_words (varlist);
4340 varlist = (WORD_LIST *)NULL;
4346 /* Return nonzero if S has any unquoted special globbing chars in it. */
4348 unquoted_glob_pattern_p (string)
4349 register char *string;
4354 while (c = *string++)
4373 if (*string++ == '\0')
4380 /* PATHNAME can contain characters prefixed by CTLESC; this indicates
4381 that the character is to be quoted. We quote it here in the style
4382 that the glob library recognizes. If CONVERT_QUOTED_NULLS is non-zero,
4383 we change quoted null strings (pathname[0] == CTLNUL) into empty
4384 strings (pathname[0] == 0). If this is called after quote removal
4385 is performed, CONVERT_QUOTED_NULLS should be 0; if called when quote
4386 removal has not been done (for example, before attempting to match a
4387 pattern while executing a case statement), CONVERT_QUOTED_NULLS should
4390 quote_string_for_globbing (pathname, convert_quoted_nulls)
4392 int convert_quoted_nulls;
4397 temp = savestring (pathname);
4399 if (convert_quoted_nulls && QUOTED_NULL (pathname))
4405 for (i = 0; temp[i]; i++)
4407 if (temp[i] == CTLESC)
4414 /* Call the glob library to do globbing on PATHNAME. */
4416 shell_glob_filename (pathname)
4419 #if defined (USE_POSIX_GLOB_LIBRARY)
4420 extern int glob_dot_filenames;
4422 char *temp, **return_value;
4426 temp = quote_string_for_globbing (pathname, 0);
4428 filenames.gl_offs = 0;
4430 glob_flags = glob_dot_filenames ? GLOB_PERIOD : 0;
4431 glob_flags |= (GLOB_ERR | GLOB_DOOFFS);
4433 i = glob (temp, glob_flags, (Function *)NULL, &filenames);
4437 if (i == GLOB_NOSPACE || i == GLOB_ABEND)
4438 return ((char **)NULL);
4440 if (i == GLOB_NOMATCH)
4441 filenames.gl_pathv[0] = (char *)NULL;
4443 return (filenames.gl_pathv);
4445 #else /* !USE_POSIX_GLOB_LIBRARY */
4447 char *temp, **results;
4449 noglob_dot_filenames = !glob_dot_filenames;
4451 temp = quote_string_for_globbing (pathname, 0);
4453 results = glob_filename (temp);
4456 if (results && !(GLOB_FAILED(results)))
4457 sort_char_array (results);
4460 #endif /* !USE_POSIX_GLOB_LIBRARY */
4463 /*************************************************
4465 * Functions to manage special variables *
4467 *************************************************/
4469 /* An alist of name.function for each special variable. Most of the
4470 functions don't do much, and in fact, this would be faster with a
4471 switch statement, but by the end of this file, I am sick of switch
4474 /* The functions that get called. */
4476 sv_path (), sv_mail (), sv_uids (), sv_ignoreeof (),
4477 sv_glob_dot_filenames (), sv_nolinks (),
4478 sv_noclobber (), sv_allow_null_glob_expansion (), sv_strict_posix ();
4480 #if defined (READLINE)
4481 void sv_terminal (), sv_hostname_completion_file ();
4484 #if defined (HISTORY)
4485 void sv_histsize (), sv_histfilesize (),
4486 sv_history_control (), sv_command_oriented_history ();
4487 # if defined (BANG_HISTORY)
4488 void sv_histchars ();
4490 #endif /* HISTORY */
4492 #if defined (GETOPTS_BUILTIN)
4493 void sv_optind (), sv_opterr ();
4494 #endif /* GETOPTS_BUILTIN */
4496 #if defined (JOB_CONTROL)
4500 #define SET_INT_VAR(name, intvar) intvar = find_variable (name) != 0
4502 struct name_and_function {
4504 VFunction *function;
4505 } special_vars[] = {
4506 { "PATH", sv_path },
4507 { "MAIL", sv_mail },
4508 { "MAILPATH", sv_mail },
4509 { "MAILCHECK", sv_mail },
4511 { "POSIXLY_CORRECT", sv_strict_posix },
4512 { "POSIX_PEDANTIC", sv_strict_posix },
4513 /* Variables which only do something special when READLINE is defined. */
4514 #if defined (READLINE)
4515 { "TERM", sv_terminal },
4516 { "TERMCAP", sv_terminal },
4517 { "TERMINFO", sv_terminal },
4518 { "hostname_completion_file", sv_hostname_completion_file },
4519 { "HOSTFILE", sv_hostname_completion_file },
4520 #endif /* READLINE */
4522 /* Variables which only do something special when HISTORY is defined. */
4523 #if defined (HISTORY)
4524 { "HISTSIZE", sv_histsize },
4525 { "HISTFILESIZE", sv_histfilesize },
4526 { "command_oriented_history", sv_command_oriented_history },
4527 # if defined (BANG_HISTORY)
4528 { "histchars", sv_histchars },
4530 { "history_control", sv_history_control },
4531 { "HISTCONTROL", sv_history_control },
4532 #endif /* HISTORY */
4536 { "IGNOREEOF", sv_ignoreeof },
4537 { "ignoreeof", sv_ignoreeof },
4539 #if defined (GETOPTS_BUILTIN)
4540 { "OPTIND", sv_optind },
4541 { "OPTERR", sv_opterr },
4542 #endif /* GETOPTS_BUILTIN */
4544 #if defined (JOB_CONTROL)
4545 { "notify", sv_notify },
4546 #endif /* JOB_CONTROL */
4548 { "glob_dot_filenames", sv_glob_dot_filenames },
4549 { "allow_null_glob_expansion", sv_allow_null_glob_expansion },
4550 { "noclobber", sv_noclobber },
4551 { "nolinks", sv_nolinks },
4552 { (char *)0x00, (VFunction *)0x00 }
4555 /* The variable in NAME has just had its state changed. Check to see if it
4556 is one of the special ones where something special happens. */
4558 stupidly_hack_special_variables (name)
4563 while (special_vars[i].name)
4565 if (STREQ (special_vars[i].name, name))
4567 (*(special_vars[i].function)) (name);
4574 /* Set/unset noclobber. */
4579 SET_INT_VAR (name, noclobber);
4582 /* What to do just after the PATH variable has changed. */
4590 args = make_word_list (make_word ("-r"), NULL);
4591 hash_builtin (args);
4592 dispose_words (args);
4595 /* What to do just after one of the MAILxxxx variables has changed. NAME
4596 is the name of the variable. This is called with NAME set to one of
4597 MAIL, MAILCHECK, or MAILPATH. */
4602 /* If the time interval for checking the files has changed, then
4603 reset the mail timer. Otherwise, one of the pathname vars
4604 to the users mailbox has changed, so rebuild the array of
4606 if (name[4] == 'C') /* if (strcmp (name, "MAILCHECK") == 0) */
4607 reset_mail_timer ();
4611 remember_mail_dates ();
4615 #if defined (READLINE)
4616 /* What to do just after one of the TERMxxx variables has changed.
4617 If we are an interactive shell, then try to reset the terminal
4618 information in readline. */
4623 if (interactive_shell && !no_line_editing)
4624 rl_reset_terminal (get_string_value ("TERM"));
4628 sv_hostname_completion_file (name)
4631 hostname_list_initialized = 0;
4633 #endif /* READLINE */
4635 #if defined (HISTORY)
4636 /* What to do after the HISTSIZE variable changes.
4637 If there is a value for this variable (and it is numeric), then stifle
4638 the history. Otherwise, if there is NO value for this variable,
4639 unstifle the history. */
4644 char *temp = get_string_value (name);
4649 if (sscanf (temp, "%d", &num) == 1)
4651 stifle_history (num);
4652 if (history_lines_this_session > where_history ())
4653 history_lines_this_session = where_history ();
4657 unstifle_history ();
4660 /* What to do if the HISTFILESIZE variable changes. */
4662 sv_histfilesize (name)
4665 char *temp = get_string_value (name);
4670 if (sscanf (temp, "%d", &num) == 1)
4672 history_truncate_file (get_string_value ("HISTFILE"), num);
4673 if (num <= history_lines_in_file)
4674 history_lines_in_file = num;
4679 /* What to do after the HISTORY_CONTROL variable changes. */
4681 sv_history_control (name)
4684 char *temp = get_string_value (name);
4686 history_control = 0;
4690 if (strcmp (temp, "ignorespace") == 0)
4691 history_control = 1;
4692 else if (strcmp (temp, "ignoredups") == 0)
4693 history_control = 2;
4694 else if (strcmp (temp, "ignoreboth") == 0)
4695 history_control = 3;
4699 /* What to do after the COMMAND_ORIENTED_HISTORY variable changes. */
4701 sv_command_oriented_history (name)
4704 SET_INT_VAR (name, command_oriented_history);
4707 # if defined (BANG_HISTORY)
4708 /* Setting/unsetting of the history expansion character. */
4714 char *temp = get_string_value (name);
4718 history_expansion_char = *temp;
4719 if (temp[0] && temp[1])
4721 history_subst_char = temp[1];
4723 history_comment_char = temp[2];
4728 history_expansion_char = '!';
4729 history_subst_char = '^';
4730 history_comment_char = '#';
4733 # endif /* BANG_HISTORY */
4734 #endif /* HISTORY */
4737 sv_allow_null_glob_expansion (name)
4740 SET_INT_VAR (name, allow_null_glob_expansion);
4743 /* If the variable exists, then the value of it can be the number
4744 of times we actually ignore the EOF. The default is small,
4745 (smaller than csh, anyway). */
4754 eof_encountered = 0;
4756 tmp_var = find_variable (name);
4757 ignoreeof = tmp_var != 0;
4758 temp = tmp_var ? value_cell (tmp_var) : (char *)NULL;
4761 if (sscanf (temp, "%d", &new_limit) == 1)
4762 eof_encountered_limit = new_limit;
4764 eof_encountered_limit = 10; /* csh uses 26. */
4768 /* Control whether * matches .files in globbing. Yechh. */
4769 int glob_dot_filenames = 0;
4772 sv_glob_dot_filenames (name)
4775 SET_INT_VAR (name, glob_dot_filenames);
4778 #if defined (JOB_CONTROL)
4779 /* Job notification feature desired? */
4784 SET_INT_VAR (name, asynchronous_notification);
4786 #endif /* JOB_CONTROL */
4788 /* If the variable `nolinks' exists, it specifies that symbolic links are
4789 not to be followed in `cd' commands. */
4794 SET_INT_VAR (name, no_symbolic_links);
4797 /* Don't let users hack the user id variables. */
4803 register SHELL_VAR *v;
4805 buff = itos (current_user.uid);
4806 v = find_variable ("UID");
4808 v->attributes &= ~att_readonly;
4810 v = bind_variable ("UID", buff);
4811 v->attributes |= (att_readonly | att_integer);
4814 buff = itos (current_user.euid);
4815 v = find_variable ("EUID");
4817 v->attributes &= ~att_readonly;
4819 v = bind_variable ("EUID", buff);
4820 v->attributes |= (att_readonly | att_integer);
4824 #if defined (GETOPTS_BUILTIN)
4829 char *tt = get_string_value ("OPTIND");
4836 /* According to POSIX, setting OPTIND=1 resets the internal state
4838 if (s < 0 || s == 1)
4848 char *tt = get_string_value ("OPTERR");
4855 #endif /* GETOPTS_BUILTIN */
4858 sv_strict_posix (name)
4861 SET_INT_VAR (name, posixly_correct);
4862 if (posixly_correct)
4863 interactive_comments = 1;
4864 #if defined (READLINE)
4865 posix_readline_initialize (posixly_correct);
4866 #endif /* READLINE */