mirror of
https://https.git.savannah.gnu.org/git/gnulib.git
synced 2026-06-15 23:35:50 +00:00
1e4ece4ab9
behavior with strdup module. * lib/.cppi-disable: Remove strcase.h, strdup.h, strndup.h, strnlen.h. * lib/memmem.h: Remove; all uses removed. This is now done by <string.h>. * lib/mempcpy.h: Likewise. * lib/memrchr.h: Likewise. * lib/stpcpy.h: Likewise. * lib/stpncpy.h: Likewise. * lib/strcase.h: Likewise. * lib/strchrnul.h: Likewise. * lib/strdup.h: Likewise. * lib/strndup.h: Likewise. * lib/strnlen.h: Likewise. * lib/strpbrk.h: Likewise. * lib/strsep.h: Likewise. * lib/strstr.h: Likewise. * lib/strtok_r.h: Likewise. * lib/string_.h: New file. * lib/argp-namefrob.h: Don't include no-longer-existent include files. Rely on <string.h> instead. * lib/canon-host.c: Likewise. * lib/chdir-long.c: Likewise. * lib/concatpath.c: Likewise. * lib/exclude.c: Likewise. * lib/fchdir.c: Likewise. * lib/getaddrinfo.c: Likewise. * lib/getcwd.c: Likewise. * lib/getsubopt.c: Likewise. * lib/glob.c: Likewise. * lib/hard-locale.c: Likewise. * lib/iconvme.c: Likewise. * lib/javacomp.c: Likewise. * lib/mempcpy.c: Likewise. * lib/memrchr.c: Likewise. * lib/regex_internal.h: Likewise. * lib/stpncpy.c: Likewise. * lib/strcasecmp.c: Likewise. * lib/strchrnul.c: Likewise. * lib/strdup.c: Likewise. * lib/striconv.c: Likewise. * lib/striconveh.c: Likewise. * lib/striconveha.c: Likewise. * lib/strncasecmp.c: Likewise. * lib/strndup.c: Likewise. * lib/strnlen.c: Likewise. * lib/strsep.c: Likewise. * lib/strstr.c: Likewise. * lib/strtok_r.c: Likewise. * lib/userspec.c: Likewise. * lib/w32spawn.h: Likewise. * lib/xstrndup.c: Likewise. * lib/mountlist.c (strstr): Remove decl. * m4/string_h.m4: New file. * m4/memmem.m4 (gl_FUNC_MEMMEM): Set HAVE_DECL_MEMMEM if necessary. * m4/mempcpy.m4 (gl_FUNC_MEMPCPY): Set HAVE_MEMPCPY if necessary. * m4/memrchr.m4 (gl_FUNC_MEMRCHR): Set HAVE_MEMRCHR * m4/stpcpy.m4 (gl_FUNC_STPCPY): Set HAVE_STPCPY if necessary. * m4/stpncpy.m4 (gl_PREREQ_STPNCPY): Set HAVE_STPNCPY if necessary. * m4/strcase.m4 (gl_FUNC_STRCASECMP): Set REPLACE_STRCASECMP if necessary. (gl_FUNC_STRNCASECMP): Set HAVE_DECL_STRNCASECMP if necessary. * m4/strchrnul.m4 (gl_FUNC_STRCHRNUL): Set HAVE_STRCHRNUL if necessary. * m4/strdup.m4 (gl_FUNC_STRDUP): Set HAVE_DECL_STRDUP if necessary. * m4/strndup.m4 (gl_FUNC_STRNDUP): Set HAVE_DECL_STRNLEN and HAVE_DECL_STRDUP if necessary. (gl_PREREQ_STRNLEN): Don't bother to check for strnlen decl, since gl_FUNC_STRNDUP does that now. * m4/strnlen.m4 (gl_FUNC_STRNLEN): Set HAVE_DECL_STRNLEN if necessary. Check for decl here... (gl_PREREQ_STRNLEN): ... not here. * m4/strpbrk.m4 (gl_FUNC_STRPBRK): Set HAVE_STRPBRK if necessary. * m4/strsep.m4 (gl_FUNC_STRSEP): Set HAVE_STRSEP if necessary. * m4/strstr.m4 (gl_FUNC_STRSTR): Set REPLACE_STRSTR if necessary. * m4/strtok_r.m4 (gl_FUNC_STRTOK_R): Set HAVE_DECL_STRTOK_R if necessary. * modules/string: New file. * modules/memmem (Files): Remove special-purpose include file. (Depends-on): Add string. (Include): Include <string.h>, not the removed file. * modules/mempcpy: Likewise. * modules/memrchr: Likewise. * modules/stpcpy: Likewise. * modules/stpncpy: Likewise. * modules/strcase: Likewise. * modules/strchrnul: Likewise. * modules/strdup: Likewise. * modules/strndup: Likewise. * modules/strnlen: Likewise. * modules/strpbrk: Likewise. * modules/strsep: Likewise. * modules/strstr: Likewise. * modules/strtok_r: Likewise. * tests/test-dirname.c: Don't include "stdup.h", since <string.h> now suffices. * tests/test-memmem.c: Don't include "memmem.h", since <string.h> now suffices.
170 lines
5.0 KiB
C
170 lines
5.0 KiB
C
/* Auxiliary functions for the creation of subprocesses. Native Woe32 API.
|
|
Copyright (C) 2003, 2006, 2007 Free Software Foundation, Inc.
|
|
Written by Bruno Haible <bruno@clisp.org>, 2003.
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2, or (at your option)
|
|
any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software Foundation,
|
|
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
|
|
|
/* Get declarations of the Win32 API functions. */
|
|
#define WIN32_LEAN_AND_MEAN
|
|
#include <windows.h>
|
|
|
|
/* Get _get_osfhandle() and _open_osfhandle(). */
|
|
#include <io.h>
|
|
|
|
#include <stdbool.h>
|
|
#include <string.h>
|
|
#include <errno.h>
|
|
|
|
#include "xalloc.h"
|
|
|
|
/* Duplicates a file handle, making the copy uninheritable. */
|
|
static int
|
|
dup_noinherit (int fd)
|
|
{
|
|
HANDLE curr_process = GetCurrentProcess ();
|
|
HANDLE old_handle = (HANDLE) _get_osfhandle (fd);
|
|
HANDLE new_handle;
|
|
int nfd;
|
|
|
|
if (!DuplicateHandle (curr_process, /* SourceProcessHandle */
|
|
old_handle, /* SourceHandle */
|
|
curr_process, /* TargetProcessHandle */
|
|
(PHANDLE) &new_handle, /* TargetHandle */
|
|
(DWORD) 0, /* DesiredAccess */
|
|
FALSE, /* InheritHandle */
|
|
DUPLICATE_SAME_ACCESS)) /* Options */
|
|
error (EXIT_FAILURE, 0, _("DuplicateHandle failed with error code 0x%08x"),
|
|
GetLastError ());
|
|
|
|
nfd = _open_osfhandle ((long) new_handle, O_BINARY);
|
|
if (nfd < 0)
|
|
error (EXIT_FAILURE, errno, _("_open_osfhandle failed"));
|
|
|
|
return nfd;
|
|
}
|
|
|
|
/* Prepares an argument vector before calling spawn().
|
|
Note that spawn() does not by itself call the command interpreter
|
|
(getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") :
|
|
({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
|
GetVersionEx(&v);
|
|
v.dwPlatformId == VER_PLATFORM_WIN32_NT;
|
|
}) ? "cmd.exe" : "command.com").
|
|
Instead it simply concatenates the arguments, separated by ' ', and calls
|
|
CreateProcess(). We must quote the arguments since Win32 CreateProcess()
|
|
interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a
|
|
special way:
|
|
- Space and tab are interpreted as delimiters. They are not treated as
|
|
delimiters if they are surrounded by double quotes: "...".
|
|
- Unescaped double quotes are removed from the input. Their only effect is
|
|
that within double quotes, space and tab are treated like normal
|
|
characters.
|
|
- Backslashes not followed by double quotes are not special.
|
|
- But 2*n+1 backslashes followed by a double quote become
|
|
n backslashes followed by a double quote (n >= 0):
|
|
\" -> "
|
|
\\\" -> \"
|
|
\\\\\" -> \\"
|
|
*/
|
|
#define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037"
|
|
#define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037"
|
|
static char **
|
|
prepare_spawn (char **argv)
|
|
{
|
|
size_t argc;
|
|
char **new_argv;
|
|
size_t i;
|
|
|
|
/* Count number of arguments. */
|
|
for (argc = 0; argv[argc] != NULL; argc++)
|
|
;
|
|
|
|
/* Allocate new argument vector. */
|
|
new_argv = XNMALLOC (argc + 1, char *);
|
|
|
|
/* Put quoted arguments into the new argument vector. */
|
|
for (i = 0; i < argc; i++)
|
|
{
|
|
const char *string = argv[i];
|
|
|
|
if (string[0] == '\0')
|
|
new_argv[i] = xstrdup ("\"\"");
|
|
else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL)
|
|
{
|
|
bool quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL);
|
|
size_t length;
|
|
unsigned int backslashes;
|
|
const char *s;
|
|
char *quoted_string;
|
|
char *p;
|
|
|
|
length = 0;
|
|
backslashes = 0;
|
|
if (quote_around)
|
|
length++;
|
|
for (s = string; *s != '\0'; s++)
|
|
{
|
|
char c = *s;
|
|
if (c == '"')
|
|
length += backslashes + 1;
|
|
length++;
|
|
if (c == '\\')
|
|
backslashes++;
|
|
else
|
|
backslashes = 0;
|
|
}
|
|
if (quote_around)
|
|
length += backslashes + 1;
|
|
|
|
quoted_string = (char *) xmalloc (length + 1);
|
|
|
|
p = quoted_string;
|
|
backslashes = 0;
|
|
if (quote_around)
|
|
*p++ = '"';
|
|
for (s = string; *s != '\0'; s++)
|
|
{
|
|
char c = *s;
|
|
if (c == '"')
|
|
{
|
|
unsigned int j;
|
|
for (j = backslashes + 1; j > 0; j--)
|
|
*p++ = '\\';
|
|
}
|
|
*p++ = c;
|
|
if (c == '\\')
|
|
backslashes++;
|
|
else
|
|
backslashes = 0;
|
|
}
|
|
if (quote_around)
|
|
{
|
|
unsigned int j;
|
|
for (j = backslashes; j > 0; j--)
|
|
*p++ = '\\';
|
|
*p++ = '"';
|
|
}
|
|
*p = '\0';
|
|
|
|
new_argv[i] = quoted_string;
|
|
}
|
|
else
|
|
new_argv[i] = (char *) string;
|
|
}
|
|
new_argv[argc] = NULL;
|
|
|
|
return new_argv;
|
|
}
|