of list_append/list_length, since they're always called with
WORD_LIST * arguments
+ 5/8
+ ---
+command.h
+ - PF_STRINGEND,PF_STRINGBEG: new flags for the parameter expansion
+ functions; set if there are no characters following or preceding the
+ expansion, respectively
+
+subst.c
+ - string_list_dollar_atstar: new function, expands unquoted $* and $@
+ when word splitting will take place and the separator is not
+ whitespace, and the positional parameters can potentially contain
+ the separator. It splits the positional parameters before separating
+ them with the separator, taking care to handle null positional
+ parameters and proper merging with text immediately preceding or
+ following the expansion. Fixes bug that added a spurious empty
+ argument if one of the positional parameters ended with the
+ separator
+ - string_list_internal: take a new flag value that says to add an
+ additional separator at the end of the returned string if the
+ last word is a null word and it will be joined with text following
+ the expansion
+ - string_list_pos_params: call string_list_dollar_atstar as
+ appropriate
+ - list_string: take a new word flag: W_SPLITONLY. This means not to
+ perform quoted null character removal while splitting the word
+ and don't allow CTLESC to quote anything, and to return "" results
+ of splitting verbatim, but marked as W_QUOTED to preserve null
+ arguments
+ - expand_word_internal,param_expand: set PF_STRINGEND and PF_STRINGBEG
+ appropriately
+ - word_split: pass W_SPLITONLY through to list_string()
+ These changes fix the bug with adding an extra empty word if one of
+ the positional parameters ends with the first character of $IFS and
+ it's not whitespace. Changes tests/dollar-at-star6.sub output.
+
+arrayfunc.c
+ - array_value_internal: if we have an unquoted array expansion
+ subscripted with * or @, call string_list_dollar_atstar if
+ appropriate
+
+ 5/13
+ ----
+execute_cmd.c
+ - execute_disk_command: if we update SHLVL, do it after (maybe)
+ making the export environment and then update the export env in
+ place, so we don't have to rebuild it twice or rebuild it more
+ times than necessary
+ Report and fix from Gao Xiang <gaoxiang@kylinos.cn>
+
+ 5/14
+ ----
+variables.c
+ - adjust_shell_level,set_pwd: make sure variable binding works before
+ trying to set the variable as exported
+ Report and patch from Grisha Levit <grishalevit@gmail.com>
+
+subst.c
+ - function_substitute: make sure funsubs don't leave `-v' unset
+ after they return by adding an unwind-protect function
+ uw_restore_verbose()
+ Report and patch from Grisha Levit <grishalevit@gmail.com>
tests/dollar-at-star9.sub f
tests/dollar-at-star10.sub f
tests/dollar-at-star11.sub f
+tests/dollar-at-star12.sub f
+tests/dollar-at-star13.sub f
tests/dollar-at1.sub f
tests/dollar-at2.sub f
tests/dollar-at3.sub f
retval = quote_nosplit (temp);
free (temp);
}
+ else if (quoted == 0 && (flags & AV_ASSIGNRHS) == 0 &&
+ ifs_is_set && ifs_is_null == 0 &&
+ spctabnl (ifs_firstc[0]) == 0)
+ retval = string_list_dollar_atstar (l, quoted, 0);
else /* ${name[@]} or unquoted ${name[*]} */
retval = string_list_dollar_at (l, quoted, (flags & AV_ASSIGNRHS) ? PF_ASSIGNRHS : 0);
#define PF_ALLINDS 0x40 /* array, act as if [@] was supplied */
#define PF_BACKQUOTE 0x80 /* differentiate `` from $() for command_substitute */
#define PF_COMSUBNLS 0x100 /* for ${; ...; } and read_comsub() to not strip trailing newlines */
+#define PF_STRINGEND 0x200 /* set if there are no chars following this expansion */
+#define PF_STRINGBEG 0x400 /* set if there are no chars before this expansion */
/* Possible values for subshell_environment */
#define SUBSHELL_ASYNC 0x01 /* subshell caused by `command &' */
ALLPROG = print truefalse sleep finfo logname basename dirname fdflags \
tty pathchk tee head mkdir rmdir mkfifo mktemp printenv id whoami \
uname sync push ln unlink realpath strftime mypid setpgid seq rm \
- accept csv dsv cut stat getconf kv strptime chmod fltexpr jobid
+ accept csv dsv cut stat getconf kv strptime chmod fltexpr jobid rev
OTHERPROG = necho hello cat pushd asort
SUBDIRS = perl
static int
cutfile (SHELL_VAR *v, WORD_LIST *list, struct cutop *ops)
{
- int fd, unbuffered_read, r;
+ int fd, unbuffered_read, r, closefd;
char *line, *b;
size_t llen;
WORD_LIST *l;
l = list;
do
{
+ closefd = 0;
+
/* for each file */
if (l == 0 || (l->word->word[0] == '-' && l->word->word[1] == '\0'))
fd = 0;
else
- fd = open (l->word->word, O_RDONLY);
+ {
+ fd = open (l->word->word, O_RDONLY);
+ closefd = fd != -1;
+ }
if (fd < 0)
{
file_error (l->word->word);
r = cutline (v, ind, line, ops); /* can modify line */
ind += r;
}
- if (fd > 0)
+
+ if (closefd)
close (fd);
QUIT;
if (command)
{
- /* If we're optimizing out the fork (implicit `exec'), decrement the
- shell level like `exec' would do. Don't do this if we are already
- in a pipeline environment, assuming it's already been done. */
- if (nofork && pipe_in == NO_PIPE && pipe_out == NO_PIPE && (subshell_environment & SUBSHELL_PIPE) == 0)
- adjust_shell_level (-1);
-
#if defined (STRICT_POSIX)
if (posixly_correct == 0 || subst_assign_varlist == 0) /* Done below. */
#endif
{
maybe_make_export_env ();
+ /* If we're optimizing out the fork (implicit `exec'), decrement the
+ shell level like `exec' would do. Don't do this if we are already
+ in a pipeline environment, assuming it's already been done.
+ Since we've just (possibly) remade the export environment, it's
+ marked as not dirty, so we update SHLVL in place rather than
+ remake the whole thing again or force a remake we would not
+ otherwise have to do. This mostly hits command substitutions with
+ a lot of exported variables, since command_substitute already
+ calls maybe_make_export_env (). */
+ if (nofork && pipe_in == NO_PIPE && pipe_out == NO_PIPE && (subshell_environment & SUBSHELL_PIPE) == 0)
+ {
+ adjust_shell_level (-1);
+ update_export_env_inplace ("SHLVL=", 6, get_string_value ("SHLVL"));
+ array_needs_making = 0;
+ }
put_command_name_into_env (command);
}
}
expand_assignment_statements (command, 0);
maybe_make_export_env ();
+ /* See above for why we do this here. */
+ if (nofork && pipe_in == NO_PIPE && pipe_out == NO_PIPE && (subshell_environment & SUBSHELL_PIPE) == 0)
+ {
+ adjust_shell_level (-1);
+ update_export_env_inplace ("SHLVL=", 6, get_string_value ("SHLVL"));
+ array_needs_making = 0;
+ }
put_command_name_into_env (command);
}
#endif
result_size += strlen (t->word->word);
}
+ if (flags & 1)
+ result_size += sep_len;
+
r = result = (char *)xmalloc (result_size + 1);
for (t = list; t; t = t->next)
word_len = strlen (t->word->word);
FASTCOPY (t->word->word, r, word_len);
r += word_len;
+
+ /* FLAGS & 1 means to add an additional SEP to the end of the returned
+ string if and only if the last word is a null word, since it will be
+ joined with text following the expansion. */
+ if ((flags & 1) && t->next == 0 && (t->word->word == 0 || t->word->word[0] == '\0') && (t->word->flags & W_QUOTED))
+ {
+ if (sep_len > 1)
+ {
+ FASTCOPY (sep, r, sep_len);
+ r += sep_len;
+ }
+ else if (sep_len)
+ *r++ = sep[0];
+ }
}
*r = '\0';
return ret;
}
+/* Expand $* or $@ in a context where word splitting will be performed. We
+ separate the words in LIST with the first character of IFS and assume
+ that a later split will recreate the list.
+ To avoid issues with a non-whitespace separator producing spurious empty
+ words if the last character of one of the words in LIST is that same
+ separator, we split LIST and join each resultant word with SEP. We remove
+ quoted nulls from the result because the callers expect them not to
+ be present before another word splitting pass.
+ This does not use FLAGS yet, but could. */
+char *
+string_list_dollar_atstar (WORD_LIST *list, int quoted, int flags)
+{
+ char *ret;
+ WORD_LIST *l, *l2, *tl;
+#if defined (HANDLE_MULTIBYTE)
+# if defined (__GNUC__)
+ char sep[MB_CUR_MAX + 1];
+# else
+ char *sep = 0;
+# endif
+#else
+ char sep[2];
+#endif
+
+ if (list == 0)
+ return (NULL);
+
+#if defined (HANDLE_MULTIBYTE)
+# if !defined (__GNUC__)
+ sep = (char *)xmalloc (locale_mb_cur_max + 1);
+# endif /* !__GNUC__ */
+ if (ifs_firstc_len == 1)
+ {
+ sep[0] = ifs_firstc[0];
+ sep[1] = '\0';
+ }
+ else
+ {
+ memcpy (sep, ifs_firstc, ifs_firstc_len);
+ sep[ifs_firstc_len] = '\0';
+ }
+#else
+ sep[0] = ifs_firstc;
+ sep[1] = '\0';
+#endif
+
+ /* We want to split non-empty arguments, but preserve null arguments.
+ Preserving the null positional parameters and following them with SEP
+ is backwards compatible. */
+ /* If we want to remove (unquoted) null arguments, so $* is like $1 $2 ...,
+ then use PF_STRINGBEG and PF_STRINGEND to inhibit separators after the
+ first and last arguments so they are joined to whatever comes before
+ and after the $* and simply skip over them otherwise. */
+
+ /* Pre-process the list */
+ /* We arrange for null arguments to be preserved. */
+ for (l2 = tl = NULL, l = list; l; l = l->next)
+ {
+ char *new_string;
+ WORD_DESC *new_word;
+
+ new_word = copy_word (l->word);
+ new_word->flags |= W_SPLITONLY;
+ if (l->word->word[0] == '\0')
+ new_word->flags |= W_SAWQUOTEDNULL;
+
+ if (l2 == NULL)
+ l2 = tl = make_word_list (new_word, l2);
+ else
+ {
+ tl->next = make_word_list (new_word, (WORD_LIST *)NULL);
+ tl = tl->next;
+ }
+ }
+
+ /* XXX - this turns words that look like quoted nulls into "", which we
+ don't want here. */
+ l = word_list_split (l2); /* pre-split, preserving empty arguments */
+
+ /* We want to turn words that are QUOTED_NULL with W_HASQUOTEDNULL set in
+ the word flags back into "" but leave every other $'\177' alone. */
+ for (l2 = l; l2; l2 = l2->next)
+ if (QUOTED_NULL (l2->word->word) && (l2->word->flags & W_HASQUOTEDNULL))
+ {
+ l2->word->word[0] = '\0';
+ l2->word->flags &= ~W_HASQUOTEDNULL;
+ }
+
+ list_quote_escapes (l);
+
+ ret = string_list_internal (l, sep, (flags & PF_STRINGEND) ? 1 : 0);
+#if defined (HANDLE_MULTIBYTE) && !defined (__GNUC__)
+ free (sep);
+#endif
+
+ dispose_words (l2);
+ dispose_words (l);
+
+ return ret;
+}
+
/* Turn the positional parameters into a string, understanding quoting and
the various subtleties of using the first character of $IFS as the
separator. Calls string_list_dollar_at, string_list_dollar_star, and
ret = expand_no_split_dollar_star ? string_list_dollar_star (list, quoted, 0) : string_list_dollar_at (list, quoted, 0); /* Posix interp 888 */
else if (pchar == '*' && quoted == 0 && (pflags & PF_ASSIGNRHS)) /* XXX */
ret = expand_no_split_dollar_star ? string_list_dollar_star (list, quoted, 0) : string_list_dollar_at (list, quoted, 0); /* Posix interp 888 */
+ else if (pchar == '*' && quoted == 0 && (pflags & PF_ASSIGNRHS) == 0 &&
+ ifs_is_set && ifs_is_null == 0 &&
+#if defined (HANDLE_MULTIBYTE)
+ spctabnl (ifs_firstc[0]) == 0)
+#else
+ spctabnl (ifs_firstc) == 0)
+#endif
+ ret = string_list_dollar_atstar (list, quoted, 0);
else if (pchar == '*')
{
/* Even when unquoted, string_list_dollar_star does the right thing
that quotes the escapes. We could use string_list_internal with " "
as the second argument. */
ret = string_list_dollar_at (list, quoted, pflags); /* Posix interp 888 */
- else if (pchar == '@')
-#if 0
- /* XXX - param_expand uses string_list_dollar_at() for this case. */
- /* string_list_dollar_at quotes CTLESC, even if quoted == 0 */
- ret = string_list_dollar_at (list, quoted, 0);
+ else if (pchar == '@' && quoted == 0 && (pflags & PF_ASSIGNRHS) == 0 &&
+ ifs_is_set && ifs_is_null == 0 &&
+#if defined (HANDLE_MULTIBYTE)
+ spctabnl (ifs_firstc[0]) == 0) /* separate these cases for now */
#else
- ret = string_list_dollar_star (list, quoted, 0);
+ spctabnl (ifs_firstc) == 0) /* separate these cases for now */
#endif
+ ret = string_list_dollar_atstar (list, quoted, 0);
+ else if (pchar == '@')
+ ret = string_list_dollar_star (list, quoted, 0);
else
ret = string_list ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? quote_list (list) : list);
else if (*s == CTLNUL) xflags |= SX_NOESCCTLNUL;
}
+ if (flags & W_SPLITONLY)
+ xflags |= SX_NOCTLESC|SX_NOESCCTLNUL;
+
slen = 0;
/* Remove sequences of whitespace at the beginning of STRING, as
long as those characters appear in IFS. Do not do this if
want to preserve the quoted null character iff this is a quoted
empty string; otherwise the quoted null characters are removed
below. */
- if (QUOTED_NULL (current_word))
+ if ((flags & W_SPLITONLY) == 0 && QUOTED_NULL (current_word))
{
t = alloc_word_desc ();
t->word = make_quoted_char ('\0');
{
/* If we have something, then add it regardless. However,
perform quoted null character removal on the current word. */
- remove_quoted_nulls (current_word);
+ if ((flags & W_SPLITONLY) == 0)
+ remove_quoted_nulls (current_word);
/* We don't want to set the word flags based on the string contents
here -- that's mostly for the parser -- so we just allocate a
if (current_word == 0 || current_word[0] == '\0')
result->word->flags |= W_SAWQUOTEDNULL;
}
+ else if ((flags & W_SPLITONLY) && current_word[0] == '\0')
+ {
+ t = alloc_word_desc ();
+ t->word = current_word;
+ /* W_QUOTED for string_list_internal () */
+ t->flags |= W_QUOTED|W_HASQUOTEDNULL;
+ result = make_word_list (t, result);
+ free_word = 0;
+ }
/* If we're not doing sequences of separators in the traditional
Bourne shell style, then add a quoted null argument. */
set_shellopts ();
}
+static void
+uw_restore_verbose (void *vflag)
+{
+ change_flag ('v', (intptr_t) vflag ? FLAG_ON : FLAG_OFF);
+ set_shellopts ();
+}
+
/* Quote the output of nofork varsub command substitution in the way that the
caller of function_substitute expects. The caller guarantees that STRING
is non-null. This is equivalent to what read_comsub does to the output it
push_context (lambdafunc.name, 1, temporary_env); /* make local variables work */
this_shell_function = &lambdafunc;
- unwind_protect_int (verbose_flag);
+
+ add_unwind_protect (uw_restore_verbose, (void *) (intptr_t) verbose_flag);
change_flag ('v', FLAG_OFF);
/* When inherit_errexit option is not enabled, command substitution does
# endif
/* Posix interp 888: not RHS, no splitting, IFS set to '' */
temp = string_list_dollar_star (list, quoted, 0);
+ else if (expand_no_split_dollar_star == 0 && (pflags & PF_ASSIGNRHS) == 0 &&
+ ifs_is_set && ifs_is_null == 0 &&
+# if defined (HANDLE_MULTIBYTE)
+ spctabnl (ifs_firstc[0]) == 0)
+# else
+ spctabnl (ifs_firstc) == 0)
+# endif
+ {
+ int nflags;
+ /* XXX - only if $# > 1? */
+ nflags = (string[zindex+1] == '\0') ? PF_STRINGEND : 0;
+
+ temp = string_list_dollar_atstar (list, quoted, nflags);
+ }
else
{
temp = string_list_dollar_at (list, quoted, 0);
else
temp = string_list_dollar_at (list, quoted, pflags);
}
+ else if (quoted == 0 &&
+ ifs_is_set && ifs_is_null == 0 &&
+#if defined (HANDLE_MULTIBYTE)
+ spctabnl (ifs_firstc[0]) == 0)
+#else
+ spctabnl (ifs_firstc) == 0)
+#endif
+ {
+ int nflags;
+ /* XXX - only if $# > 1? */
+ nflags = (string[zindex+1] == '\0') ? PF_STRINGEND : 0;
+
+ temp = string_list_dollar_atstar (list, quoted, pflags|nflags);
+ }
else
temp = string_list_dollar_at (list, quoted, pflags);
if (temp)
{
istring = sub_append_string (temp, istring, &istring_index, &istring_size);
+ if (istring_index > 0)
+ pflags &= ~PF_STRINGBEG;
temp = (char *)0;
}
pflags |= PF_ASSIGNRHS;
if (word->flags & W_COMPLETE)
pflags |= PF_COMPLETE;
+ if (istring_index == 0)
+ pflags |= PF_STRINGBEG;
tword = param_expand (string, &sindex, quoted, &local_expanded,
&temp_has_dollar_at, "ed_dollar_at,
char *xifs;
xifs = ((w->flags & W_QUOTED) || ifs_chars == 0) ? "" : ifs_chars;
- result = list_string (w->word, xifs, w->flags & W_QUOTED);
+ result = list_string (w->word, xifs, w->flags & (W_QUOTED|W_SPLITONLY));
}
else
result = (WORD_LIST *)NULL;
/* Expand $@ into a single string, obeying POSIX rules. */
extern char *string_list_dollar_at (WORD_LIST *, int, int);
+/* A special function for expanding unquoted $* and $@ in a context where
+ word splitting will be performed using a non-whitespace separator and
+ the positional parameters potentially contain that separator. */
+extern char *string_list_dollar_atstar (WORD_LIST *, int, int);
+
/* Turn the positional parameters into a string, understanding quoting and
the various subtleties of using the first character of $IFS as the
separator. Calls string_list_dollar_at, string_list_dollar_star, and
test_runsub ./dollar-at-star10.sub
test_runsub ./dollar-at-star11.sub
+# tests for unquoted expansions of $* and $@ when word splitting will take
+# place and the separator is not whitespace
+test_runsub ./dollar-at-star12.sub
+test_runsub ./dollar-at-star13.sub
+
# tests for special expansion of "$*" and "${array[*]}" when used with other
# expansions -- bugs through bash-2.05b
test_runsub ./dollar-star1.sub
--- /dev/null
+OIFS=$IFS
+
+set -- a b+ c +d e; IFS=+;
+
+# these should be the same
+printf '<%s> ' $1 $2 $3 $4 $5; echo
+printf '<%s> ' $* ; echo
+printf '<%s> ' $@ ; echo
+
+set -- 'b+' 'c'
+
+# these should be the same
+echo =====
+printf '<%s> ' $1 $2 $3; echo
+printf '<%s> ' $* ; echo
+printf '<%s> ' $@ ; echo
+printf '<%s> ' ${*} ; echo
+printf '<%s> ' ${@} ; echo
+
+# these should be the same
+echo =====
+set -- a 'b+c' '+d+e' 'f+g+' h
+
+printf '<%s> ' $* ; echo
+printf '<%s> ' $@ ; echo
+
+echo =====
+array=(a 'b+' c '+d' e)
+printf '<%s> ' ${array[0]} ${array[1]} ${array[2]} ${array[3]} ${array[4]}; echo
+printf '<%s> ' ${array[*]} ; echo
+printf '<%s> ' ${array[@]} ; echo
+unset array
+
+array=(a 'b+c' '+d+e' 'f+g+' h)
+printf '<%s> ' ${array[0]} ${array[1]} ${array[2]} ${array[3]} ${array[4]}; echo
+printf '<%s> ' ${array[*]} ; echo
+printf '<%s> ' ${array[@]} ; echo
+unset array
+
+echo =====
+set -- $'\001\177+' 'b+' c; IFS=+;
+
+recho $1 $2 $3
+recho $*
+
+set -- $'\177+' 'b+' c; IFS=+;
+recho $1 $2 $3
+recho $*
+
+set -- $'a\177+' 'b+' c; IFS=+;
+recho $1 $2 $3
+recho $*
+
+set -- $'\001+' b+ c; IFS=+;
+recho $1 $2 $3
+recho $*
+
+set -- $'a\001+' b+ c; IFS=+;
+recho $1 $2 $3
+recho $*
--- /dev/null
+# from back in 2018 on dash@vger.kernel.org
+
+# IFS the default, these arguments should not be split
+set -- , ,
+IFS=,
+recho $@
+recho $*
+recho ${@}
+recho ${*}
+
+set -- $@
+recho $#
+
+# IFS already set, these arguments should be split
+set -- , ,
+recho $@
+recho $*
+recho ${@}
+recho ${*}
+
+set -- $@
+recho $#
+
+# need the space to be preserved
+set -- , ' ,'
+IFS=,
+recho $@
+recho $*
+
+set -- $@
+recho $#
+
+# need the , to preserve an empty argument before the trailing char
+# from back in 2018 on dash@vger.kernel.org
+set -- ',' ','
+
+recho ${@}a
+recho ${*}b
+
+recho a${@}
+recho b${*}
argv[1] = <>
argv[2] = <a>
argv[3] = <>
-argv[4] = <>
-argv[5] = <b>
-argv[6] = <>
-argv[7] = <>
-argv[8] = <c>
+argv[4] = <b>
+argv[5] = <>
+argv[6] = <c>
argv[1] = <'a'>
argv[2] = <'b'>
argv[3] = <'c'>
argv[1] = <>
argv[2] = <a>
argv[3] = <>
-argv[4] = <>
-argv[5] = <b>
-argv[6] = <>
-argv[7] = <>
-argv[8] = <c>
+argv[4] = <b>
+argv[5] = <>
+argv[6] = <c>
argv[1] = <'a'>
argv[2] = <'b'>
argv[3] = <'c'>
argv[1] = <>
argv[1] = </>
1:1
+ dollar-at-star12.sub
+<a> <b> <c> <> <d> <e>
+<a> <b> <c> <> <d> <e>
+<a> <b> <c> <> <d> <e>
+=====
+<b> <c>
+<b> <c>
+<b> <c>
+<b> <c>
+<b> <c>
+=====
+<a> <b> <c> <> <d> <e> <f> <g> <h>
+<a> <b> <c> <> <d> <e> <f> <g> <h>
+=====
+<a> <b> <c> <> <d> <e>
+<a> <b> <c> <> <d> <e>
+<a> <b> <c> <> <d> <e>
+<a> <b> <c> <> <d> <e> <f> <g> <h>
+<a> <b> <c> <> <d> <e> <f> <g> <h>
+<a> <b> <c> <> <d> <e> <f> <g> <h>
+=====
+argv[1] = <^A^?>
+argv[2] = <b>
+argv[3] = <c>
+argv[1] = <^A^?>
+argv[2] = <b>
+argv[3] = <c>
+argv[1] = <^?>
+argv[2] = <b>
+argv[3] = <c>
+argv[1] = <^?>
+argv[2] = <b>
+argv[3] = <c>
+argv[1] = <a^?>
+argv[2] = <b>
+argv[3] = <c>
+argv[1] = <a^?>
+argv[2] = <b>
+argv[3] = <c>
+argv[1] = <^A>
+argv[2] = <b>
+argv[3] = <c>
+argv[1] = <^A>
+argv[2] = <b>
+argv[3] = <c>
+argv[1] = <a^A>
+argv[2] = <b>
+argv[3] = <c>
+argv[1] = <a^A>
+argv[2] = <b>
+argv[3] = <c>
+ dollar-at-star13.sub
+argv[1] = <>
+argv[2] = <>
+argv[1] = <>
+argv[2] = <>
+argv[1] = <>
+argv[2] = <>
+argv[1] = <>
+argv[2] = <>
+argv[1] = <2>
+argv[1] = <>
+argv[2] = <>
+argv[1] = <>
+argv[2] = <>
+argv[1] = <>
+argv[2] = <>
+argv[1] = <>
+argv[2] = <>
+argv[1] = <2>
+argv[1] = <>
+argv[2] = < >
+argv[1] = <>
+argv[2] = < >
+argv[1] = <2>
+argv[1] = <>
+argv[2] = <>
+argv[3] = <a>
+argv[1] = <>
+argv[2] = <>
+argv[3] = <b>
+argv[1] = <a>
+argv[2] = <>
+argv[1] = <b>
+argv[2] = <>
dollar-star1.sub
xa|xb|xc
xa|xb|xc
-unset GROUPS UID 2>/dev/null
+unset GROUPS 2>/dev/null
${THIS_SH} ./test.tests >${BASH_TSTOUT} 2>&1
diff ${BASH_TSTOUT} test.right && rm -f ${BASH_TSTOUT}
new_level[3] = '\0';
}
- temp_var = bind_variable ("SHLVL", new_level, 0);
- set_auto_export (temp_var);
+ if (temp_var = bind_variable ("SHLVL", new_level, 0))
+ set_auto_export (temp_var);
}
static void
if (posixly_correct && current_dir)
{
temp_var = bind_variable ("PWD", current_dir, 0);
- set_auto_export (temp_var);
+ if (temp_var)
+ set_auto_export (temp_var);
}
free (current_dir);
}
{
set_working_directory (home_string);
temp_var = bind_variable ("PWD", home_string, 0);
- set_auto_export (temp_var);
+ if (temp_var)
+ set_auto_export (temp_var);
}
else
{
if (temp_string)
{
temp_var = bind_variable ("PWD", temp_string, 0);
- set_auto_export (temp_var);
+ if (temp_var)
+ set_auto_export (temp_var);
free (temp_string);
}
}