mirror of
https://sourceware.org/git/glibc.git
synced 2025-07-29 11:41:21 +03:00
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:
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>
|
1998-03-11 Ulrich Drepper <drepper@cygnus.com>
|
||||||
|
|
||||||
* nss/nss_db/db-XXX.c (lookup): Copy data to safe place before
|
* 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
|
else
|
||||||
# Most GNU programs take a -v and spit out some text including
|
# 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.
|
# 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
|
libc_cv_prog_as_gnu=yes
|
||||||
else
|
else
|
||||||
libc_cv_prog_as_gnu=no
|
libc_cv_prog_as_gnu=no
|
||||||
@ -1563,7 +1563,7 @@ if eval "test \"`echo '$''{'libc_cv_prog_ld_gnu'+set}'`\" = set"; then
|
|||||||
else
|
else
|
||||||
# Most GNU programs take a -v and spit out some text including
|
# 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.
|
# 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
|
libc_cv_prog_ld_gnu=yes
|
||||||
else
|
else
|
||||||
libc_cv_prog_ld_gnu=no
|
libc_cv_prog_ld_gnu=no
|
||||||
|
@ -27,6 +27,10 @@
|
|||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <stdio-common/_itoa.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
|
#ifndef MAP_ANON
|
||||||
/* This is the only dl-sysdep.c function that is actually needed at run-time
|
/* This is the only dl-sysdep.c function that is actually needed at run-time
|
||||||
by _dl_map_object. */
|
by _dl_map_object. */
|
||||||
@ -89,7 +93,7 @@ _dl_sysdep_output (int fd, const char *msg, ...)
|
|||||||
do
|
do
|
||||||
{
|
{
|
||||||
size_t len = strlen (msg);
|
size_t len = strlen (msg);
|
||||||
__write (fd, msg, len);
|
__libc_write (fd, msg, len);
|
||||||
msg = va_arg (ap, const char *);
|
msg = va_arg (ap, const char *);
|
||||||
}
|
}
|
||||||
while (msg != NULL);
|
while (msg != NULL);
|
||||||
@ -124,19 +128,19 @@ _dl_debug_message (int new_line, const char *msg, ...)
|
|||||||
char buf[7] = "00000:\t";
|
char buf[7] = "00000:\t";
|
||||||
assert (pid >= 0 && pid < 100000);
|
assert (pid >= 0 && pid < 100000);
|
||||||
_itoa_word (pid, &buf[5], 10, 0);
|
_itoa_word (pid, &buf[5], 10, 0);
|
||||||
__write (_dl_debug_fd, buf, 7);
|
__libc_write (_dl_debug_fd, buf, 7);
|
||||||
new_line = 0;
|
new_line = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
endp = strchr (msg, '\n');
|
endp = strchr (msg, '\n');
|
||||||
if (endp == NULL)
|
if (endp == NULL)
|
||||||
{
|
{
|
||||||
__write (_dl_debug_fd, msg, strlen (msg));
|
__libc_write (_dl_debug_fd, msg, strlen (msg));
|
||||||
msg = va_arg (ap, const char *);
|
msg = va_arg (ap, const char *);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
__write (_dl_debug_fd, msg, endp - msg + 1);
|
__libc_write (_dl_debug_fd, msg, endp - msg + 1);
|
||||||
msg = endp + 1;
|
msg = endp + 1;
|
||||||
new_line = 1;
|
new_line = 1;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Profiling of shared libraries.
|
/* 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.
|
This file is part of the GNU C Library.
|
||||||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
|
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
|
||||||
Based on the BSD mcount implementation.
|
Based on the BSD mcount implementation.
|
||||||
@ -35,6 +35,10 @@
|
|||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <atomicity.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
|
/* The LD_PROFILE feature has to be implemented different to the
|
||||||
normal profiling using the gmon/ functions. The problem is that an
|
normal profiling using the gmon/ functions. The problem is that an
|
||||||
arbitrary amount of processes simulataneously can be run using
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TEMP_FAILURE_RETRY (__write (fd, buf, (expected_size
|
if (TEMP_FAILURE_RETRY (__libc_write (fd, buf, (expected_size
|
||||||
& (_dl_pagesize - 1)))) < 0)
|
& (_dl_pagesize - 1))))
|
||||||
|
< 0)
|
||||||
goto cannot_create;
|
goto cannot_create;
|
||||||
}
|
}
|
||||||
else if (st.st_size != expected_size)
|
else if (st.st_size != expected_size)
|
||||||
|
@ -66,8 +66,7 @@ RTLD_NEXT used in code not dynamically loaded"));
|
|||||||
l = l->l_loader;
|
l = l->l_loader;
|
||||||
|
|
||||||
{
|
{
|
||||||
struct link_map *map = l;
|
struct link_map *mapscope[2] = { l, NULL };
|
||||||
struct link_map *mapscope[2] = { map, NULL };
|
|
||||||
args->loadbase = _dl_lookup_symbol_skip (args->name, &args->ref,
|
args->loadbase = _dl_lookup_symbol_skip (args->name, &args->ref,
|
||||||
mapscope, NULL, match);
|
mapscope, NULL, match);
|
||||||
}
|
}
|
||||||
|
@ -68,8 +68,7 @@ RTLD_NEXT used in code not dynamically loaded"));
|
|||||||
l = l->l_loader;
|
l = l->l_loader;
|
||||||
|
|
||||||
{
|
{
|
||||||
struct link_map *map = l;
|
struct link_map *mapscope[2] = { l, NULL };
|
||||||
struct link_map *mapscope[2] = { map, NULL };
|
|
||||||
args->loadbase = _dl_lookup_versioned_symbol_skip (args->name,
|
args->loadbase = _dl_lookup_versioned_symbol_skip (args->name,
|
||||||
&args->ref,
|
&args->ref,
|
||||||
mapscope,
|
mapscope,
|
||||||
|
16
elf/rtld.c
16
elf/rtld.c
@ -349,7 +349,7 @@ dl_main (const ElfW(Phdr) *phdr,
|
|||||||
Grant the user some education. */
|
Grant the user some education. */
|
||||||
if (_dl_argc < 2)
|
if (_dl_argc < 2)
|
||||||
_dl_sysdep_fatal ("\
|
_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\
|
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\
|
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\
|
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\
|
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\
|
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\
|
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);
|
NULL);
|
||||||
|
|
||||||
++_dl_skip_args;
|
++_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)
|
while ((p = strsep (&list, " :")) != NULL)
|
||||||
if (! __libc_enable_secure || strchr (p, '/') == 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);
|
lt_library, 0);
|
||||||
if (new_map->l_opencount == 1)
|
if (new_map->l_opencount == 1)
|
||||||
/* It is no duplicate. */
|
/* 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");
|
runp = file + strspn (file, ": \t\n");
|
||||||
while ((p = strsep (&runp, ": \t\n")) != NULL)
|
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);
|
lt_library, 0);
|
||||||
if (new_map->l_opencount == 1)
|
if (new_map->l_opencount == 1)
|
||||||
/* It is no duplicate. */
|
/* 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)
|
if (problem != NULL)
|
||||||
{
|
{
|
||||||
char *p = strndupa (problem, file_size - (problem - file));
|
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);
|
lt_library, 0);
|
||||||
if (new_map->l_opencount == 1)
|
if (new_map->l_opencount == 1)
|
||||||
/* It is no duplicate. */
|
/* It is no duplicate. */
|
||||||
|
@ -107,17 +107,17 @@ main (int argc, char *argv[])
|
|||||||
int test;
|
int test;
|
||||||
int fail = 0;
|
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)
|
if (argc > 1)
|
||||||
{
|
{
|
||||||
command_line_test (argv[1]);
|
command_line_test (argv[1]);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setenv ("IFS", IFS, 1);
|
||||||
|
for (test = 0; test_case[test].retval != -1; test++)
|
||||||
|
if (testit (&test_case[test]))
|
||||||
|
++fail;
|
||||||
|
|
||||||
pw = getpwnam ("root");
|
pw = getpwnam ("root");
|
||||||
if (pw != NULL)
|
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 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 */
|
/* Some forward declarations */
|
||||||
static int parse_dollars (char **word, size_t *word_length, size_t *max_length,
|
static int parse_dollars (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,
|
wordexp_t *pwordexp, const char *ifs,
|
||||||
const char *ifs_white)
|
const char *ifs_white, int quoted)
|
||||||
internal_function;
|
internal_function;
|
||||||
static int parse_backtick (char **word, size_t *word_length,
|
static int parse_backtick (char **word, size_t *word_length,
|
||||||
size_t *max_length, const char *words,
|
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,
|
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)
|
||||||
{
|
{
|
||||||
/* We are poised just after a '*' or a '{'. */
|
/* We are poised just after a '*', a '[' or a '?'. */
|
||||||
int error;
|
int error;
|
||||||
glob_t globbuf;
|
glob_t globbuf;
|
||||||
int match;
|
int match;
|
||||||
char *matching_word;
|
char *matching_word;
|
||||||
|
int quoted = 0; /* 1 if singly-quoted, 2 if doubly */
|
||||||
|
|
||||||
for (; words[*offset]; (*offset)++)
|
for (; words[*offset]; (*offset)++)
|
||||||
switch (words[*offset])
|
{
|
||||||
{
|
if ((ifs && strchr (ifs, words[*offset])) ||
|
||||||
case ' ':
|
(!ifs && strchr (" \t\n", words[*offset])))
|
||||||
case '\t':
|
/* Reached IFS */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '$':
|
/* Sort out quoting */
|
||||||
error = parse_dollars (word, word_length, max_length, words, offset,
|
if (words[*offset] == '\'')
|
||||||
flags, pwordexp, ifs, ifs_white);
|
if (quoted == 0)
|
||||||
if (error)
|
{
|
||||||
return error;
|
quoted = 1;
|
||||||
|
continue;
|
||||||
continue;
|
}
|
||||||
|
else if (quoted == 1)
|
||||||
default:
|
{
|
||||||
if (ifs == NULL || strchr (ifs, words[*offset]) == NULL)
|
quoted = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (words[*offset] == '"')
|
||||||
|
if (quoted == 0)
|
||||||
{
|
{
|
||||||
*word = w_addchar (*word, word_length, max_length, words[*offset]);
|
quoted = 2;
|
||||||
if (*word == NULL)
|
continue;
|
||||||
return WRDE_NOSPACE;
|
}
|
||||||
|
else if (quoted == 2)
|
||||||
|
{
|
||||||
|
quoted = 0;
|
||||||
continue;
|
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);
|
error = glob (*word, GLOB_NOCHECK, NULL, &globbuf);
|
||||||
|
|
||||||
@ -599,8 +636,8 @@ parse_arith (char **word, size_t *word_length, size_t *max_length,
|
|||||||
{
|
{
|
||||||
case '$':
|
case '$':
|
||||||
error = parse_dollars (&expr, &expr_length, &expr_maxlen,
|
error = parse_dollars (&expr, &expr_length, &expr_maxlen,
|
||||||
words, offset, flags, NULL, NULL, NULL);
|
words, offset, flags, NULL, NULL, NULL, 1);
|
||||||
/* The first NULL here is to tell parse_dollars not to
|
/* The ``1'' here is to tell parse_dollars not to
|
||||||
* split the fields.
|
* split the fields.
|
||||||
*/
|
*/
|
||||||
if (error)
|
if (error)
|
||||||
@ -951,7 +988,7 @@ static int
|
|||||||
internal_function
|
internal_function
|
||||||
parse_param (char **word, size_t *word_length, size_t *max_length,
|
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 *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 "$" */
|
/* We are poised just after "$" */
|
||||||
enum remove_pattern_enum
|
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;
|
size_t pat_maxlen = 0;
|
||||||
char *env = NULL;
|
char *env = NULL;
|
||||||
char *pattern = NULL;
|
char *pattern = NULL;
|
||||||
char *value;
|
char *value = NULL;
|
||||||
char action = '\0';
|
char action = '\0';
|
||||||
enum remove_pattern_enum remove = RP_NONE;
|
enum remove_pattern_enum remove = RP_NONE;
|
||||||
int colon_seen = 0;
|
int colon_seen = 0;
|
||||||
int depth = 0;
|
int depth = 0;
|
||||||
int substitute_length = 0;
|
int substitute_length = 0;
|
||||||
int error;
|
int error;
|
||||||
|
int star = 0;
|
||||||
|
|
||||||
for (; words[*offset]; ++(*offset))
|
for (; words[*offset]; ++(*offset))
|
||||||
{
|
{
|
||||||
@ -1164,12 +1202,16 @@ parse_param (char **word, size_t *word_length, size_t *max_length,
|
|||||||
break;
|
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]);
|
env = w_addchar (env, &env_length, &env_maxlen, words[*offset]);
|
||||||
if (env == NULL)
|
if (env == NULL)
|
||||||
goto no_space;
|
goto no_space;
|
||||||
|
|
||||||
|
if (star)
|
||||||
|
goto envsubst;
|
||||||
|
|
||||||
break;
|
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);
|
--(*offset);
|
||||||
|
|
||||||
envsubst:
|
envsubst:
|
||||||
@ -1190,10 +1233,92 @@ envsubst:
|
|||||||
*offset = start - 1;
|
*offset = start - 1;
|
||||||
*word = w_addchar (*word, word_length, max_length, '$');
|
*word = w_addchar (*word, word_length, max_length, '$');
|
||||||
free (env);
|
free (env);
|
||||||
free (pattern);
|
|
||||||
return *word ? 0 : WRDE_NOSPACE;
|
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);
|
value = getenv (env);
|
||||||
|
|
||||||
if (action != '\0' || remove != RP_NONE)
|
if (action != '\0' || remove != RP_NONE)
|
||||||
@ -1343,18 +1468,19 @@ envsubst:
|
|||||||
{
|
{
|
||||||
/* Substitute word */
|
/* Substitute word */
|
||||||
wordexp_t we;
|
wordexp_t we;
|
||||||
char *expand_me = pattern;
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (pwordexp == NULL)
|
if (quoted)
|
||||||
{
|
{
|
||||||
/* No field-splitting is allowed, so imagine
|
/* No field-splitting is allowed, so imagine
|
||||||
quotes around the word. */
|
quotes around the word. */
|
||||||
expand_me = alloca (strlen (pattern) + 2);
|
char *qtd_pattern = malloc (3 + strlen (pattern));
|
||||||
sprintf (expand_me, "\"%s\"", pattern);
|
sprintf (qtd_pattern, "\"%s\"", pattern);
|
||||||
|
free (pattern);
|
||||||
|
pattern = qtd_pattern;
|
||||||
}
|
}
|
||||||
|
|
||||||
error = wordexp (expand_me, &we, flags);
|
error = wordexp (pattern, &we, flags);
|
||||||
if (error)
|
if (error)
|
||||||
{
|
{
|
||||||
free (env);
|
free (env);
|
||||||
@ -1363,7 +1489,7 @@ envsubst:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Fingers crossed that the quotes worked.. */
|
/* Fingers crossed that the quotes worked.. */
|
||||||
assert (pwordexp || we.we_wordc == 1);
|
assert (!quoted || we.we_wordc == 1);
|
||||||
|
|
||||||
/* Substitute */
|
/* Substitute */
|
||||||
for (i = 0; i < we.we_wordc; i++)
|
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 */
|
/* Quoted - no field split */
|
||||||
*word = w_addstr (*word, word_length, max_length, value);
|
*word = w_addstr (*word, word_length, max_length, value);
|
||||||
@ -1454,10 +1581,19 @@ envsubst:
|
|||||||
do
|
do
|
||||||
{
|
{
|
||||||
char *field_end = field_begin;
|
char *field_end = field_begin;
|
||||||
char *field;
|
|
||||||
char *next_field;
|
char *next_field;
|
||||||
char ch;
|
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 */
|
/* Skip IFS whitespace before the field */
|
||||||
while (*field_begin && strchr (ifs_white, *field_begin) != NULL)
|
while (*field_begin && strchr (ifs_white, *field_begin) != NULL)
|
||||||
field_begin++;
|
field_begin++;
|
||||||
@ -1487,22 +1623,15 @@ envsubst:
|
|||||||
next_field++;
|
next_field++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Null-terminate it and make a copy */
|
/* Null-terminate it */
|
||||||
*field_end = 0;
|
*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;
|
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;
|
field_begin = next_field;
|
||||||
} while (seen_nonws_ifs || (field_begin && *field_begin));
|
} while (seen_nonws_ifs || (field_begin && *field_begin));
|
||||||
}
|
}
|
||||||
@ -1532,7 +1661,8 @@ static int
|
|||||||
internal_function
|
internal_function
|
||||||
parse_dollars (char **word, size_t *word_length, size_t *max_length,
|
parse_dollars (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)
|
wordexp_t *pwordexp, const char *ifs, const char *ifs_white,
|
||||||
|
int quoted)
|
||||||
{
|
{
|
||||||
/* We are poised _at_ "$" */
|
/* We are poised _at_ "$" */
|
||||||
switch (words[1 + *offset])
|
switch (words[1 + *offset])
|
||||||
@ -1546,10 +1676,17 @@ parse_dollars (char **word, size_t *word_length, size_t *max_length,
|
|||||||
case '(':
|
case '(':
|
||||||
if (words[2 + *offset] == '(')
|
if (words[2 + *offset] == '(')
|
||||||
{
|
{
|
||||||
(*offset) += 3;
|
/* Differentiate between $((1+3)) and $((echo);(ls)) */
|
||||||
/* Call parse_arith -- 0 is for "no brackets" */
|
int i = 3 + *offset;
|
||||||
return parse_arith (word, word_length, max_length, words, offset,
|
while (words[i] && words[i] != ')')
|
||||||
flags, 0);
|
++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)
|
if (flags & WRDE_NOCMD)
|
||||||
@ -1569,7 +1706,7 @@ parse_dollars (char **word, size_t *word_length, size_t *max_length,
|
|||||||
default:
|
default:
|
||||||
++(*offset); /* parse_param needs to know if "{" is there */
|
++(*offset); /* parse_param needs to know if "{" is there */
|
||||||
return parse_param (word, word_length, max_length, words, offset, flags,
|
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
|
static int
|
||||||
internal_function
|
internal_function
|
||||||
parse_dquote (char **word, size_t *word_length, size_t *max_length,
|
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 */
|
/* We are poised just after a double-quote */
|
||||||
int error;
|
int error;
|
||||||
@ -1654,9 +1792,9 @@ parse_dquote (char **word, size_t *word_length, size_t *max_length,
|
|||||||
|
|
||||||
case '$':
|
case '$':
|
||||||
error = parse_dollars (word, word_length, max_length, words, offset,
|
error = parse_dollars (word, word_length, max_length, words, offset,
|
||||||
flags, NULL, NULL, NULL);
|
flags, pwordexp, ifs, ifs_white, 1);
|
||||||
/* The first NULL here is to tell parse_dollars not to
|
/* The ``1'' here is to tell parse_dollars not to
|
||||||
* split the fields.
|
* split the fields. It may need to, however ("$@").
|
||||||
*/
|
*/
|
||||||
if (error)
|
if (error)
|
||||||
return error;
|
return error;
|
||||||
@ -1735,7 +1873,7 @@ wordexp (const char *words, wordexp_t *pwordexp, int flags)
|
|||||||
char *ifs;
|
char *ifs;
|
||||||
char ifs_white[4];
|
char ifs_white[4];
|
||||||
char **old_wordv = pwordexp->we_wordv;
|
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)
|
if (flags & WRDE_REUSE)
|
||||||
/* Minimal implementation of WRDE_REUSE for now */
|
/* Minimal implementation of WRDE_REUSE for now */
|
||||||
@ -1826,7 +1964,8 @@ wordexp (const char *words, wordexp_t *pwordexp, int flags)
|
|||||||
|
|
||||||
case '$':
|
case '$':
|
||||||
error = parse_dollars (&word, &word_length, &max_length, words,
|
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)
|
if (error)
|
||||||
goto do_error;
|
goto do_error;
|
||||||
@ -1850,7 +1989,7 @@ wordexp (const char *words, wordexp_t *pwordexp, int flags)
|
|||||||
case '"':
|
case '"':
|
||||||
++words_offset;
|
++words_offset;
|
||||||
error = parse_dquote (&word, &word_length, &max_length, words,
|
error = parse_dquote (&word, &word_length, &max_length, words,
|
||||||
&words_offset, flags);
|
&words_offset, flags, pwordexp, ifs, ifs_white);
|
||||||
|
|
||||||
if (error)
|
if (error)
|
||||||
goto do_error;
|
goto do_error;
|
||||||
@ -1877,7 +2016,8 @@ wordexp (const char *words, wordexp_t *pwordexp, int flags)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case '*':
|
case '*':
|
||||||
case '{':
|
case '[':
|
||||||
|
case '?':
|
||||||
error = parse_glob (&word, &word_length, &max_length, words,
|
error = parse_glob (&word, &word_length, &max_length, words,
|
||||||
&words_offset, flags, pwordexp, ifs, ifs_white);
|
&words_offset, flags, pwordexp, ifs, ifs_white);
|
||||||
|
|
||||||
@ -1953,8 +2093,13 @@ wordexp (const char *words, wordexp_t *pwordexp, int flags)
|
|||||||
|
|
||||||
do_error:
|
do_error:
|
||||||
/* 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)
|
if (word != NULL)
|
||||||
free (word);
|
free (word);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user