Update.
1998-03-11 15:27 Ulrich Drepper <drepper@cygnus.com> * elf/rtld.c: Update help message. Install link maps for preloaded objects using main_map as loader. * elf/dl-misc.c: Use __libc_write instead of __write for debugging. * elf/dl-profile.c: Likewise. * elf/dlsym.c: Little optimization. * elf/dlvsym.c: Likewise. 1998-03-11 14:56 Ulrich Drepper <drepper@cygnus.com> * posix/wordexp-test.c: Move test for parameter list at the very beginning. 1998-03-11 00:16 Tim Waugh <tim@cyberelk.demon.co.uk> * posix/wordexp.c (wordexp): Set we_wordc to zero initially unless WRDE_REUSE flag is set. (parse_param): Allow `*', `@', and numbers in parameter names. (parse_dollars): Differentiate between arithmetic expansion and a command substitution that starts immediately with a sub-shell (like ``$((1+3))'' as opposed to ``$((echo);(ls))''). (parse_param): Memory allocated with __alloca in a block was referenced outside that block. Adjusted to use malloc/free. (parse_param): Adjusted field-splitting algorithm so that there is not necessarily a field split at the end of a parameter expansion. 1998-03-10 19:52 Tim Waugh <tim@cyberelk.demon.co.uk> * posix/wordexp.c (wordexp): If about to return WRDE_NOSPACE, don't free words that have already been allocated. (parse_param): A dollar sign on its own will never have a pattern associated with it (like "${HOME%%/}" has), so don't try to free it. (parse_glob): Attempt to glob when an unquoted `[' is found (rather than an unquoted '{' (!)). Also for unquoted '?'. (parse_glob): Sorted out quoting in a glob-able word. (parse_param): Added $* and $@ handling.
This commit is contained in:
parent
5afdca0087
commit
2bcf29ba7c
40
ChangeLog
40
ChangeLog
|
@ -1,3 +1,43 @@
|
|||
1998-03-11 15:27 Ulrich Drepper <drepper@cygnus.com>
|
||||
|
||||
* elf/rtld.c: Update help message.
|
||||
Install link maps for preloaded objects using main_map as loader.
|
||||
|
||||
* elf/dl-misc.c: Use __libc_write instead of __write for debugging.
|
||||
* elf/dl-profile.c: Likewise.
|
||||
|
||||
* elf/dlsym.c: Little optimization.
|
||||
* elf/dlvsym.c: Likewise.
|
||||
|
||||
1998-03-11 14:56 Ulrich Drepper <drepper@cygnus.com>
|
||||
|
||||
* posix/wordexp-test.c: Move test for parameter list at the very
|
||||
beginning.
|
||||
|
||||
1998-03-11 00:16 Tim Waugh <tim@cyberelk.demon.co.uk>
|
||||
|
||||
* posix/wordexp.c (wordexp): Set we_wordc to zero initially unless
|
||||
WRDE_REUSE flag is set.
|
||||
(parse_param): Allow `*', `@', and numbers in parameter names.
|
||||
(parse_dollars): Differentiate between arithmetic expansion and a
|
||||
command substitution that starts immediately with a sub-shell
|
||||
(like ``$((1+3))'' as opposed to ``$((echo);(ls))'').
|
||||
(parse_param): Memory allocated with __alloca in a block was
|
||||
referenced outside that block. Adjusted to use malloc/free.
|
||||
(parse_param): Adjusted field-splitting algorithm so that there is
|
||||
not necessarily a field split at the end of a parameter expansion.
|
||||
|
||||
1998-03-10 19:52 Tim Waugh <tim@cyberelk.demon.co.uk>
|
||||
|
||||
* posix/wordexp.c (wordexp): If about to return WRDE_NOSPACE,
|
||||
don't free words that have already been allocated.
|
||||
(parse_param): A dollar sign on its own will never have a pattern
|
||||
associated with it (like "${HOME%%/}" has), so don't try to free it.
|
||||
(parse_glob): Attempt to glob when an unquoted `[' is found
|
||||
(rather than an unquoted '{' (!)). Also for unquoted '?'.
|
||||
(parse_glob): Sorted out quoting in a glob-able word.
|
||||
(parse_param): Added $* and $@ handling.
|
||||
|
||||
1998-03-11 Ulrich Drepper <drepper@cygnus.com>
|
||||
|
||||
* nss/nss_db/db-XXX.c (lookup): Copy data to safe place before
|
||||
|
|
4
configure
vendored
4
configure
vendored
|
@ -1545,7 +1545,7 @@ if eval "test \"`echo '$''{'libc_cv_prog_as_gnu'+set}'`\" = set"; then
|
|||
else
|
||||
# Most GNU programs take a -v and spit out some text including
|
||||
# the word 'GNU'. Some try to read stdin, so give them /dev/null.
|
||||
if $AS -v </dev/null 2>&1 | grep GNU 2>&1 > /dev/null; then
|
||||
if $AS -v </dev/null 2>&1 | grep GNU > /dev/null 2>&1; then
|
||||
libc_cv_prog_as_gnu=yes
|
||||
else
|
||||
libc_cv_prog_as_gnu=no
|
||||
|
@ -1563,7 +1563,7 @@ if eval "test \"`echo '$''{'libc_cv_prog_ld_gnu'+set}'`\" = set"; then
|
|||
else
|
||||
# Most GNU programs take a -v and spit out some text including
|
||||
# the word 'GNU'. Some try to read stdin, so give them /dev/null.
|
||||
if $LD -v </dev/null 2>&1 | grep GNU 2>&1 > /dev/null; then
|
||||
if $LD -v </dev/null 2>&1 | grep GNU > /dev/null 2>&1; then
|
||||
libc_cv_prog_ld_gnu=yes
|
||||
else
|
||||
libc_cv_prog_ld_gnu=no
|
||||
|
|
|
@ -27,6 +27,10 @@
|
|||
#include <sys/stat.h>
|
||||
#include <stdio-common/_itoa.h>
|
||||
|
||||
/* We have prototype anywhere. */
|
||||
extern ssize_t __libc_write __P ((int __fd, __const __ptr_t __buf,
|
||||
size_t __n));
|
||||
|
||||
#ifndef MAP_ANON
|
||||
/* This is the only dl-sysdep.c function that is actually needed at run-time
|
||||
by _dl_map_object. */
|
||||
|
@ -89,7 +93,7 @@ _dl_sysdep_output (int fd, const char *msg, ...)
|
|||
do
|
||||
{
|
||||
size_t len = strlen (msg);
|
||||
__write (fd, msg, len);
|
||||
__libc_write (fd, msg, len);
|
||||
msg = va_arg (ap, const char *);
|
||||
}
|
||||
while (msg != NULL);
|
||||
|
@ -124,19 +128,19 @@ _dl_debug_message (int new_line, const char *msg, ...)
|
|||
char buf[7] = "00000:\t";
|
||||
assert (pid >= 0 && pid < 100000);
|
||||
_itoa_word (pid, &buf[5], 10, 0);
|
||||
__write (_dl_debug_fd, buf, 7);
|
||||
__libc_write (_dl_debug_fd, buf, 7);
|
||||
new_line = 0;
|
||||
}
|
||||
|
||||
endp = strchr (msg, '\n');
|
||||
if (endp == NULL)
|
||||
{
|
||||
__write (_dl_debug_fd, msg, strlen (msg));
|
||||
__libc_write (_dl_debug_fd, msg, strlen (msg));
|
||||
msg = va_arg (ap, const char *);
|
||||
}
|
||||
else
|
||||
{
|
||||
__write (_dl_debug_fd, msg, endp - msg + 1);
|
||||
__libc_write (_dl_debug_fd, msg, endp - msg + 1);
|
||||
msg = endp + 1;
|
||||
new_line = 1;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* Profiling of shared libraries.
|
||||
Copyright (C) 1997 Free Software Foundation, Inc.
|
||||
Copyright (C) 1997, 1998 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
|
||||
Based on the BSD mcount implementation.
|
||||
|
@ -35,6 +35,10 @@
|
|||
#include <sys/stat.h>
|
||||
#include <atomicity.h>
|
||||
|
||||
/* We have prototype anywhere. */
|
||||
extern ssize_t __libc_write __P ((int __fd, __const __ptr_t __buf,
|
||||
size_t __n));
|
||||
|
||||
/* The LD_PROFILE feature has to be implemented different to the
|
||||
normal profiling using the gmon/ functions. The problem is that an
|
||||
arbitrary amount of processes simulataneously can be run using
|
||||
|
@ -305,8 +309,9 @@ _dl_start_profile (struct link_map *map, const char *output_dir)
|
|||
return;
|
||||
}
|
||||
|
||||
if (TEMP_FAILURE_RETRY (__write (fd, buf, (expected_size
|
||||
& (_dl_pagesize - 1)))) < 0)
|
||||
if (TEMP_FAILURE_RETRY (__libc_write (fd, buf, (expected_size
|
||||
& (_dl_pagesize - 1))))
|
||||
< 0)
|
||||
goto cannot_create;
|
||||
}
|
||||
else if (st.st_size != expected_size)
|
||||
|
|
|
@ -66,8 +66,7 @@ RTLD_NEXT used in code not dynamically loaded"));
|
|||
l = l->l_loader;
|
||||
|
||||
{
|
||||
struct link_map *map = l;
|
||||
struct link_map *mapscope[2] = { map, NULL };
|
||||
struct link_map *mapscope[2] = { l, NULL };
|
||||
args->loadbase = _dl_lookup_symbol_skip (args->name, &args->ref,
|
||||
mapscope, NULL, match);
|
||||
}
|
||||
|
|
|
@ -68,8 +68,7 @@ RTLD_NEXT used in code not dynamically loaded"));
|
|||
l = l->l_loader;
|
||||
|
||||
{
|
||||
struct link_map *map = l;
|
||||
struct link_map *mapscope[2] = { map, NULL };
|
||||
struct link_map *mapscope[2] = { l, NULL };
|
||||
args->loadbase = _dl_lookup_versioned_symbol_skip (args->name,
|
||||
&args->ref,
|
||||
mapscope,
|
||||
|
|
16
elf/rtld.c
16
elf/rtld.c
|
@ -349,7 +349,7 @@ dl_main (const ElfW(Phdr) *phdr,
|
|||
Grant the user some education. */
|
||||
if (_dl_argc < 2)
|
||||
_dl_sysdep_fatal ("\
|
||||
Usage: ld.so [--list|--verify] EXECUTABLE-FILE [ARGS-FOR-PROGRAM...]\n\
|
||||
Usage: ld.so [OPTION]... EXECUTABLE-FILE [ARGS-FOR-PROGRAM...]\n\
|
||||
You have invoked `ld.so', the helper program for shared library executables.\n\
|
||||
This program usually lives in the file `/lib/ld.so', and special directives\n\
|
||||
in executable files using ELF shared libraries tell the system's program\n\
|
||||
|
@ -360,7 +360,13 @@ command line to load and run an ELF executable file; this is like executing\n\
|
|||
that file itself, but always uses this helper program from the file you\n\
|
||||
specified, instead of the helper program file specified in the executable\n\
|
||||
file you run. This is mostly of use for maintainers to test new versions\n\
|
||||
of this helper program; chances are you did not intend to run this program.\n",
|
||||
of this helper program; chances are you did not intend to run this program.\n\
|
||||
\n\
|
||||
--list list all dependencies and how they are resolved\n\
|
||||
--verify verify that given object really is a dynamically linked\n\
|
||||
object we get handle\n\
|
||||
--library-path PATH use given PATH instead of content of the environment\n\
|
||||
variable LD_LIBRARY_PATH\n",
|
||||
NULL);
|
||||
|
||||
++_dl_skip_args;
|
||||
|
@ -509,7 +515,7 @@ of this helper program; chances are you did not intend to run this program.\n",
|
|||
while ((p = strsep (&list, " :")) != NULL)
|
||||
if (! __libc_enable_secure || strchr (p, '/') == NULL)
|
||||
{
|
||||
struct link_map *new_map = _dl_map_object (NULL, p, 1,
|
||||
struct link_map *new_map = _dl_map_object (main_map, p, 1,
|
||||
lt_library, 0);
|
||||
if (new_map->l_opencount == 1)
|
||||
/* It is no duplicate. */
|
||||
|
@ -570,7 +576,7 @@ of this helper program; chances are you did not intend to run this program.\n",
|
|||
runp = file + strspn (file, ": \t\n");
|
||||
while ((p = strsep (&runp, ": \t\n")) != NULL)
|
||||
{
|
||||
struct link_map *new_map = _dl_map_object (NULL, p, 1,
|
||||
struct link_map *new_map = _dl_map_object (main_map, p, 1,
|
||||
lt_library, 0);
|
||||
if (new_map->l_opencount == 1)
|
||||
/* It is no duplicate. */
|
||||
|
@ -584,7 +590,7 @@ of this helper program; chances are you did not intend to run this program.\n",
|
|||
if (problem != NULL)
|
||||
{
|
||||
char *p = strndupa (problem, file_size - (problem - file));
|
||||
struct link_map *new_map = _dl_map_object (NULL, p, 1,
|
||||
struct link_map *new_map = _dl_map_object (main_map, p, 1,
|
||||
lt_library, 0);
|
||||
if (new_map->l_opencount == 1)
|
||||
/* It is no duplicate. */
|
||||
|
|
|
@ -107,17 +107,17 @@ main (int argc, char *argv[])
|
|||
int test;
|
||||
int fail = 0;
|
||||
|
||||
setenv ("IFS", IFS, 1);
|
||||
for (test = 0; test_case[test].retval != -1; test++)
|
||||
if (testit (&test_case[test]))
|
||||
++fail;
|
||||
|
||||
if (argc > 1)
|
||||
{
|
||||
command_line_test (argv[1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
setenv ("IFS", IFS, 1);
|
||||
for (test = 0; test_case[test].retval != -1; test++)
|
||||
if (testit (&test_case[test]))
|
||||
++fail;
|
||||
|
||||
pw = getpwnam ("root");
|
||||
if (pw != NULL)
|
||||
{
|
||||
|
|
275
posix/wordexp.c
275
posix/wordexp.c
|
@ -48,11 +48,14 @@
|
|||
* This is a recursive-descent-style word expansion routine.
|
||||
*/
|
||||
|
||||
/* This variable is defined and initialized in the startup code. */
|
||||
extern char **__libc_argv;
|
||||
|
||||
/* Some forward declarations */
|
||||
static int parse_dollars (char **word, size_t *word_length, size_t *max_length,
|
||||
const char *words, size_t *offset, int flags,
|
||||
wordexp_t *pwordexp, const char *ifs,
|
||||
const char *ifs_white)
|
||||
const char *ifs_white, int quoted)
|
||||
internal_function;
|
||||
static int parse_backtick (char **word, size_t *word_length,
|
||||
size_t *max_length, const char *words,
|
||||
|
@ -332,39 +335,73 @@ parse_glob (char **word, size_t *word_length, size_t *max_length,
|
|||
const char *words, size_t *offset, int flags,
|
||||
wordexp_t *pwordexp, const char *ifs, const char *ifs_white)
|
||||
{
|
||||
/* We are poised just after a '*' or a '{'. */
|
||||
/* We are poised just after a '*', a '[' or a '?'. */
|
||||
int error;
|
||||
glob_t globbuf;
|
||||
int match;
|
||||
char *matching_word;
|
||||
int quoted = 0; /* 1 if singly-quoted, 2 if doubly */
|
||||
|
||||
for (; words[*offset]; (*offset)++)
|
||||
switch (words[*offset])
|
||||
{
|
||||
case ' ':
|
||||
case '\t':
|
||||
{
|
||||
if ((ifs && strchr (ifs, words[*offset])) ||
|
||||
(!ifs && strchr (" \t\n", words[*offset])))
|
||||
/* Reached IFS */
|
||||
break;
|
||||
|
||||
case '$':
|
||||
error = parse_dollars (word, word_length, max_length, words, offset,
|
||||
flags, pwordexp, ifs, ifs_white);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
continue;
|
||||
|
||||
default:
|
||||
if (ifs == NULL || strchr (ifs, words[*offset]) == NULL)
|
||||
/* Sort out quoting */
|
||||
if (words[*offset] == '\'')
|
||||
if (quoted == 0)
|
||||
{
|
||||
quoted = 1;
|
||||
continue;
|
||||
}
|
||||
else if (quoted == 1)
|
||||
{
|
||||
quoted = 0;
|
||||
continue;
|
||||
}
|
||||
else if (words[*offset] == '"')
|
||||
if (quoted == 0)
|
||||
{
|
||||
*word = w_addchar (*word, word_length, max_length, words[*offset]);
|
||||
if (*word == NULL)
|
||||
return WRDE_NOSPACE;
|
||||
|
||||
quoted = 2;
|
||||
continue;
|
||||
}
|
||||
else if (quoted == 2)
|
||||
{
|
||||
quoted = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
/* Sort out other special characters */
|
||||
if (quoted != 1 && words[*offset] == '$')
|
||||
{
|
||||
error = parse_dollars (word, word_length, max_length, words, offset,
|
||||
flags, pwordexp, ifs, ifs_white, quoted == 2);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
continue;
|
||||
}
|
||||
else if (words[*offset] == '\\')
|
||||
{
|
||||
if (quoted)
|
||||
error = parse_qtd_backslash (word, word_length, max_length, words,
|
||||
offset);
|
||||
else
|
||||
error = parse_backslash (word, word_length, max_length, words,
|
||||
offset);
|
||||
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
*word = w_addchar (*word, word_length, max_length, words[*offset]);
|
||||
if (*word == NULL)
|
||||
return WRDE_NOSPACE;
|
||||
}
|
||||
|
||||
error = glob (*word, GLOB_NOCHECK, NULL, &globbuf);
|
||||
|
||||
|
@ -599,8 +636,8 @@ parse_arith (char **word, size_t *word_length, size_t *max_length,
|
|||
{
|
||||
case '$':
|
||||
error = parse_dollars (&expr, &expr_length, &expr_maxlen,
|
||||
words, offset, flags, NULL, NULL, NULL);
|
||||
/* The first NULL here is to tell parse_dollars not to
|
||||
words, offset, flags, NULL, NULL, NULL, 1);
|
||||
/* The ``1'' here is to tell parse_dollars not to
|
||||
* split the fields.
|
||||
*/
|
||||
if (error)
|
||||
|
@ -951,7 +988,7 @@ static int
|
|||
internal_function
|
||||
parse_param (char **word, size_t *word_length, size_t *max_length,
|
||||
const char *words, size_t *offset, int flags, wordexp_t *pwordexp,
|
||||
const char *ifs, const char *ifs_white)
|
||||
const char *ifs, const char *ifs_white, int quoted)
|
||||
{
|
||||
/* We are poised just after "$" */
|
||||
enum remove_pattern_enum
|
||||
|
@ -969,13 +1006,14 @@ parse_param (char **word, size_t *word_length, size_t *max_length,
|
|||
size_t pat_maxlen = 0;
|
||||
char *env = NULL;
|
||||
char *pattern = NULL;
|
||||
char *value;
|
||||
char *value = NULL;
|
||||
char action = '\0';
|
||||
enum remove_pattern_enum remove = RP_NONE;
|
||||
int colon_seen = 0;
|
||||
int depth = 0;
|
||||
int substitute_length = 0;
|
||||
int error;
|
||||
int star = 0;
|
||||
|
||||
for (; words[*offset]; ++(*offset))
|
||||
{
|
||||
|
@ -1164,12 +1202,16 @@ parse_param (char **word, size_t *word_length, size_t *max_length,
|
|||
break;
|
||||
}
|
||||
|
||||
if ((words[start] == '{') || isalpha (words[*offset]))
|
||||
star = strchr ("*@", words[*offset]) != NULL;
|
||||
if (isalnum (words[*offset]) || star)
|
||||
{
|
||||
env = w_addchar (env, &env_length, &env_maxlen, words[*offset]);
|
||||
if (env == NULL)
|
||||
goto no_space;
|
||||
|
||||
if (star)
|
||||
goto envsubst;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1178,7 +1220,8 @@ parse_param (char **word, size_t *word_length, size_t *max_length,
|
|||
}
|
||||
}
|
||||
|
||||
/* End of input string */
|
||||
/* End of input string -- remember to reparse the character that we stopped
|
||||
* at. */
|
||||
--(*offset);
|
||||
|
||||
envsubst:
|
||||
|
@ -1190,10 +1233,92 @@ envsubst:
|
|||
*offset = start - 1;
|
||||
*word = w_addchar (*word, word_length, max_length, '$');
|
||||
free (env);
|
||||
free (pattern);
|
||||
return *word ? 0 : WRDE_NOSPACE;
|
||||
}
|
||||
|
||||
/* Is it `$*' or `$@' ? */
|
||||
if (strpbrk (env, "*@") != NULL)
|
||||
{
|
||||
size_t plist_len = 1;
|
||||
int p;
|
||||
|
||||
if (env[1] != '\0')
|
||||
{
|
||||
/* Bad substitution if there is more than one character */
|
||||
fprintf (stderr, "${%s}: bad substitution\n", env);
|
||||
return WRDE_SYNTAX;
|
||||
}
|
||||
|
||||
if (!quoted || *env == '*')
|
||||
{
|
||||
/* Build up value parameter by parameter (copy them) */
|
||||
for (p = 1; __libc_argv[p]; p++)
|
||||
{
|
||||
char * old_pointer = value;
|
||||
|
||||
if (value)
|
||||
value[plist_len - 1] = 0;
|
||||
|
||||
plist_len += 1 + strlen (__libc_argv[p]);
|
||||
|
||||
/* First realloc will act as malloc because value is
|
||||
* initialised to NULL. */
|
||||
value = realloc (value, plist_len);
|
||||
if (value == NULL)
|
||||
{
|
||||
free (old_pointer);
|
||||
return WRDE_NOSPACE;
|
||||
}
|
||||
|
||||
strcat (value, __libc_argv[p]);
|
||||
if (__libc_argv[p + 1])
|
||||
{
|
||||
value[plist_len - 1] = '\0';
|
||||
value[plist_len - 2] = ' ';
|
||||
}
|
||||
}
|
||||
|
||||
if (value)
|
||||
goto maybe_fieldsplit;
|
||||
}
|
||||
|
||||
/* Each parameter is a separate word ("$@") */
|
||||
if (__libc_argv[0] == NULL)
|
||||
{
|
||||
/* This can happen if the application is started without any
|
||||
parameter, not even a name. This is legal according to
|
||||
POSIX since the giving parameters is only a "should" rule. */
|
||||
*word = __strdup ("");
|
||||
*max_length = *word_length = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (p = 1; __libc_argv[p + 1]; p++)
|
||||
{
|
||||
char *copy = __strdup (__libc_argv[p]);
|
||||
if (copy == NULL)
|
||||
return WRDE_NOSPACE;
|
||||
|
||||
strcpy (copy, __libc_argv[p]);
|
||||
error = w_addword (pwordexp, copy);
|
||||
if (error)
|
||||
{
|
||||
free (copy);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
/* Last parameter becomes current word */
|
||||
if (__libc_argv[p])
|
||||
{
|
||||
*word = __strdup (__libc_argv[p]);
|
||||
*max_length = *word_length = strlen (*word);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
value = getenv (env);
|
||||
|
||||
if (action != '\0' || remove != RP_NONE)
|
||||
|
@ -1343,18 +1468,19 @@ envsubst:
|
|||
{
|
||||
/* Substitute word */
|
||||
wordexp_t we;
|
||||
char *expand_me = pattern;
|
||||
int i;
|
||||
|
||||
if (pwordexp == NULL)
|
||||
if (quoted)
|
||||
{
|
||||
/* No field-splitting is allowed, so imagine
|
||||
quotes around the word. */
|
||||
expand_me = alloca (strlen (pattern) + 2);
|
||||
sprintf (expand_me, "\"%s\"", pattern);
|
||||
char *qtd_pattern = malloc (3 + strlen (pattern));
|
||||
sprintf (qtd_pattern, "\"%s\"", pattern);
|
||||
free (pattern);
|
||||
pattern = qtd_pattern;
|
||||
}
|
||||
|
||||
error = wordexp (expand_me, &we, flags);
|
||||
error = wordexp (pattern, &we, flags);
|
||||
if (error)
|
||||
{
|
||||
free (env);
|
||||
|
@ -1363,7 +1489,7 @@ envsubst:
|
|||
}
|
||||
|
||||
/* Fingers crossed that the quotes worked.. */
|
||||
assert (pwordexp || we.we_wordc == 1);
|
||||
assert (!quoted || we.we_wordc == 1);
|
||||
|
||||
/* Substitute */
|
||||
for (i = 0; i < we.we_wordc; i++)
|
||||
|
@ -1439,7 +1565,8 @@ envsubst:
|
|||
}
|
||||
|
||||
|
||||
if (pwordexp == NULL)
|
||||
maybe_fieldsplit:
|
||||
if (quoted || !pwordexp)
|
||||
{
|
||||
/* Quoted - no field split */
|
||||
*word = w_addstr (*word, word_length, max_length, value);
|
||||
|
@ -1454,10 +1581,19 @@ envsubst:
|
|||
do
|
||||
{
|
||||
char *field_end = field_begin;
|
||||
char *field;
|
||||
char *next_field;
|
||||
char ch;
|
||||
|
||||
/* If this isn't the first field, start a new word */
|
||||
if (field_begin != value)
|
||||
{
|
||||
if (w_addword (pwordexp, *word) == WRDE_NOSPACE)
|
||||
return WRDE_NOSPACE;
|
||||
|
||||
*word = NULL;
|
||||
*word_length = *max_length = 0;
|
||||
}
|
||||
|
||||
/* Skip IFS whitespace before the field */
|
||||
while (*field_begin && strchr (ifs_white, *field_begin) != NULL)
|
||||
field_begin++;
|
||||
|
@ -1487,22 +1623,15 @@ envsubst:
|
|||
next_field++;
|
||||
}
|
||||
|
||||
/* Null-terminate it and make a copy */
|
||||
/* Null-terminate it */
|
||||
*field_end = 0;
|
||||
field = __strdup (field_begin);
|
||||
if (field == NULL)
|
||||
|
||||
/* Tag a copy onto the current word */
|
||||
*word = w_addstr (*word, word_length, max_length,
|
||||
__strdup (field_begin));
|
||||
if (*word == NULL)
|
||||
return WRDE_NOSPACE;
|
||||
|
||||
/* Tag the field onto the word list */
|
||||
if (w_addword (pwordexp, field) == WRDE_NOSPACE)
|
||||
{
|
||||
free (field);
|
||||
return WRDE_NOSPACE;
|
||||
}
|
||||
|
||||
*word = NULL;
|
||||
*word_length = *max_length = 0;
|
||||
|
||||
field_begin = next_field;
|
||||
} while (seen_nonws_ifs || (field_begin && *field_begin));
|
||||
}
|
||||
|
@ -1532,7 +1661,8 @@ static int
|
|||
internal_function
|
||||
parse_dollars (char **word, size_t *word_length, size_t *max_length,
|
||||
const char *words, size_t *offset, int flags,
|
||||
wordexp_t *pwordexp, const char *ifs, const char *ifs_white)
|
||||
wordexp_t *pwordexp, const char *ifs, const char *ifs_white,
|
||||
int quoted)
|
||||
{
|
||||
/* We are poised _at_ "$" */
|
||||
switch (words[1 + *offset])
|
||||
|
@ -1546,10 +1676,17 @@ parse_dollars (char **word, size_t *word_length, size_t *max_length,
|
|||
case '(':
|
||||
if (words[2 + *offset] == '(')
|
||||
{
|
||||
(*offset) += 3;
|
||||
/* Call parse_arith -- 0 is for "no brackets" */
|
||||
return parse_arith (word, word_length, max_length, words, offset,
|
||||
flags, 0);
|
||||
/* Differentiate between $((1+3)) and $((echo);(ls)) */
|
||||
int i = 3 + *offset;
|
||||
while (words[i] && words[i] != ')')
|
||||
++i;
|
||||
if (words[i] == ')' && words[i + 1] == ')')
|
||||
{
|
||||
(*offset) += 3;
|
||||
/* Call parse_arith -- 0 is for "no brackets" */
|
||||
return parse_arith (word, word_length, max_length, words, offset,
|
||||
flags, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & WRDE_NOCMD)
|
||||
|
@ -1569,7 +1706,7 @@ parse_dollars (char **word, size_t *word_length, size_t *max_length,
|
|||
default:
|
||||
++(*offset); /* parse_param needs to know if "{" is there */
|
||||
return parse_param (word, word_length, max_length, words, offset, flags,
|
||||
pwordexp, ifs, ifs_white);
|
||||
pwordexp, ifs, ifs_white, quoted);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1640,7 +1777,8 @@ parse_backtick (char **word, size_t *word_length, size_t *max_length,
|
|||
static int
|
||||
internal_function
|
||||
parse_dquote (char **word, size_t *word_length, size_t *max_length,
|
||||
const char *words, size_t *offset, int flags)
|
||||
const char *words, size_t *offset, int flags,
|
||||
wordexp_t *pwordexp, const char * ifs, const char * ifs_white)
|
||||
{
|
||||
/* We are poised just after a double-quote */
|
||||
int error;
|
||||
|
@ -1654,9 +1792,9 @@ parse_dquote (char **word, size_t *word_length, size_t *max_length,
|
|||
|
||||
case '$':
|
||||
error = parse_dollars (word, word_length, max_length, words, offset,
|
||||
flags, NULL, NULL, NULL);
|
||||
/* The first NULL here is to tell parse_dollars not to
|
||||
* split the fields.
|
||||
flags, pwordexp, ifs, ifs_white, 1);
|
||||
/* The ``1'' here is to tell parse_dollars not to
|
||||
* split the fields. It may need to, however ("$@").
|
||||
*/
|
||||
if (error)
|
||||
return error;
|
||||
|
@ -1735,7 +1873,7 @@ wordexp (const char *words, wordexp_t *pwordexp, int flags)
|
|||
char *ifs;
|
||||
char ifs_white[4];
|
||||
char **old_wordv = pwordexp->we_wordv;
|
||||
size_t old_wordc = pwordexp->we_wordc;
|
||||
size_t old_wordc = (flags & WRDE_REUSE) ? pwordexp->we_wordc : 0;
|
||||
|
||||
if (flags & WRDE_REUSE)
|
||||
/* Minimal implementation of WRDE_REUSE for now */
|
||||
|
@ -1826,7 +1964,8 @@ wordexp (const char *words, wordexp_t *pwordexp, int flags)
|
|||
|
||||
case '$':
|
||||
error = parse_dollars (&word, &word_length, &max_length, words,
|
||||
&words_offset, flags, pwordexp, ifs, ifs_white);
|
||||
&words_offset, flags, pwordexp, ifs, ifs_white,
|
||||
0);
|
||||
|
||||
if (error)
|
||||
goto do_error;
|
||||
|
@ -1850,7 +1989,7 @@ wordexp (const char *words, wordexp_t *pwordexp, int flags)
|
|||
case '"':
|
||||
++words_offset;
|
||||
error = parse_dquote (&word, &word_length, &max_length, words,
|
||||
&words_offset, flags);
|
||||
&words_offset, flags, pwordexp, ifs, ifs_white);
|
||||
|
||||
if (error)
|
||||
goto do_error;
|
||||
|
@ -1877,7 +2016,8 @@ wordexp (const char *words, wordexp_t *pwordexp, int flags)
|
|||
break;
|
||||
|
||||
case '*':
|
||||
case '{':
|
||||
case '[':
|
||||
case '?':
|
||||
error = parse_glob (&word, &word_length, &max_length, words,
|
||||
&words_offset, flags, pwordexp, ifs, ifs_white);
|
||||
|
||||
|
@ -1953,8 +2093,13 @@ wordexp (const char *words, wordexp_t *pwordexp, int flags)
|
|||
|
||||
do_error:
|
||||
/* Error:
|
||||
free memory used, set we_wordc and wd_wordv back to what they were.
|
||||
* free memory used (unless error is WRDE_NOSPACE), and
|
||||
* set we_wordc and wd_wordv back to what they were.
|
||||
*/
|
||||
|
||||
if (error == WRDE_NOSPACE)
|
||||
return WRDE_NOSPACE;
|
||||
|
||||
if (word != NULL)
|
||||
free (word);
|
||||
|
||||
|
|
Loading…
Reference in a new issue