Commit e0ca651e authored by Francois Gouget's avatar Francois Gouget Committed by Alexandre Julliard

Rewrite msvcrt_{argvtos,valisttos} to be more efficient.

Warn about the ' ' and '"' handling of the exec and spawn functions. Copy the command line in MSVCRT_system to make it writable.
parent 9360a50f
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include "msvcrt/process.h" #include "msvcrt/process.h"
#include "msvcrt/stdlib.h" #include "msvcrt/stdlib.h"
#include "msvcrt/string.h"
DEFAULT_DEBUG_CHANNEL(msvcrt); DEFAULT_DEBUG_CHANNEL(msvcrt);
...@@ -26,7 +27,7 @@ static const unsigned int CMD = 'c' << 16 | 'm' << 8 | 'd'; ...@@ -26,7 +27,7 @@ static const unsigned int CMD = 'c' << 16 | 'm' << 8 | 'd';
static const unsigned int COM = 'c' << 16 | 'o' << 8 | 'm'; static const unsigned int COM = 'c' << 16 | 'o' << 8 | 'm';
/* INTERNAL: Spawn a child process */ /* INTERNAL: Spawn a child process */
static int msvcrt_spawn(int flags, const char* exe, char* args, char* env) static int msvcrt_spawn(int flags, const char* exe, char* cmdline, char* env)
{ {
STARTUPINFOA si; STARTUPINFOA si;
PROCESS_INFORMATION pi; PROCESS_INFORMATION pi;
...@@ -45,7 +46,7 @@ static int msvcrt_spawn(int flags, const char* exe, char* args, char* env) ...@@ -45,7 +46,7 @@ static int msvcrt_spawn(int flags, const char* exe, char* args, char* env)
memset(&si, 0, sizeof(si)); memset(&si, 0, sizeof(si));
si.cb = sizeof(si); si.cb = sizeof(si);
if (!CreateProcessA(exe, args, NULL, NULL, TRUE, if (!CreateProcessA(exe, cmdline, NULL, NULL, TRUE,
flags == _P_DETACH ? DETACHED_PROCESS : 0, flags == _P_DETACH ? DETACHED_PROCESS : 0,
env, NULL, &si, &pi)) env, NULL, &si, &pi))
{ {
...@@ -75,76 +76,90 @@ static int msvcrt_spawn(int flags, const char* exe, char* args, char* env) ...@@ -75,76 +76,90 @@ static int msvcrt_spawn(int flags, const char* exe, char* args, char* env)
return -1; /* can't reach here */ return -1; /* can't reach here */
} }
/* INTERNAL: Convert argv list to a single 'delim'-separated string */ /* INTERNAL: Convert argv list to a single 'delim'-separated string, with an
* extra '\0' to terminate it
*/
static char* msvcrt_argvtos(const char* const* arg, char delim) static char* msvcrt_argvtos(const char* const* arg, char delim)
{ {
const char* const* search = arg; const char* const* a;
long size = 0; long size;
char *ret; char* p;
char* ret;
if (!arg && !delim) if (!arg && !delim)
return NULL; {
/* Return NULL for an empty environment list */
return NULL;
}
/* get length */ /* get length */
while(*search) a = arg;
size = 0;
while (*a)
{ {
size += strlen(*search) + 1; size += strlen(*a) + 1;
search++; a++;
} }
if (!(ret = (char *)MSVCRT_calloc(size + 1, 1))) ret = (char*)MSVCRT_malloc(size + 1);
if (!ret)
return NULL; return NULL;
/* fill string */ /* fill string */
search = arg; a = arg;
size = 0; p = ret;
while(*search) while (*a)
{ {
int strsize = strlen(*search); int len = strlen(*a);
memcpy(ret+size,*search,strsize); memcpy(ret+size,*a,len);
ret[size+strsize] = delim; p += len;
size += strsize + 1; *p++ = delim;
search++; a++;
} }
*p='\0';
return ret; return ret;
} }
/* INTERNAL: Convert va_list to a single 'delim'-separated string */ /* INTERNAL: Convert va_list to a single 'delim'-separated string, with an
static char* msvcrt_valisttos(const char* arg0, va_list ap, char delim) * extra '\0' to terminate it
*/
static char* msvcrt_valisttos(const char* arg0, va_list alist, char delim)
{ {
va_list search = ap; va_list alist2 = alist;
long size; long size;
char *arg; const char *arg;
char* p;
char *ret; char *ret;
int strsize;
if (!arg0 && !delim) if (!arg0 && !delim)
return NULL;
/* get length */
size = strlen(arg0) + 1;
while((arg = va_arg(search, char *)) != NULL)
{ {
size += strlen(arg) + 1; /* Return NULL for an empty environment list */
return NULL;
} }
if (!(ret = (char *)MSVCRT_calloc(size + 1, 1))) /* get length */
arg = arg0;
size = 0;
do {
size += strlen(arg) + 1;
arg = va_arg(alist, char*);
} while (arg != NULL);
ret = (char*)MSVCRT_malloc(size + 1);
if (!ret)
return NULL; return NULL;
/* fill string */ /* fill string */
search = ap; arg = arg0;
size = 0; p = ret;
strsize = strlen(arg0); do {
memcpy(ret+size,arg0,strsize); int len = strlen(arg);
ret[size+strsize] = delim; memcpy(p,arg,len);
size += strsize + 1; p += len;
while((arg = va_arg(search, char *)) != NULL) *p++ = delim;
{ arg = va_arg(alist2, char*);
strsize = strlen(search); } while (arg != NULL);
memcpy(ret+size,search,strsize); *p = '\0';
ret[size+strsize] = delim;
size += strsize + 1;
}
return ret; return ret;
} }
...@@ -183,6 +198,9 @@ int _cwait(int *status, int pid, int action) ...@@ -183,6 +198,9 @@ int _cwait(int *status, int pid, int action)
/********************************************************************* /*********************************************************************
* _execl (MSVCRT.@) * _execl (MSVCRT.@)
*
* Like on Windows, this function does not handle arguments with spaces
* or double-quotes.
*/ */
int _execl(const char* name, const char* arg0, ...) int _execl(const char* name, const char* arg0, ...)
{ {
...@@ -202,6 +220,9 @@ int _execl(const char* name, const char* arg0, ...) ...@@ -202,6 +220,9 @@ int _execl(const char* name, const char* arg0, ...)
/********************************************************************* /*********************************************************************
* _execlp (MSVCRT.@) * _execlp (MSVCRT.@)
*
* Like on Windows, this function does not handle arguments with spaces
* or double-quotes.
*/ */
int _execlp(const char* name, const char* arg0, ...) int _execlp(const char* name, const char* arg0, ...)
{ {
...@@ -224,6 +245,9 @@ int _execlp(const char* name, const char* arg0, ...) ...@@ -224,6 +245,9 @@ int _execlp(const char* name, const char* arg0, ...)
/********************************************************************* /*********************************************************************
* _execv (MSVCRT.@) * _execv (MSVCRT.@)
*
* Like on Windows, this function does not handle arguments with spaces
* or double-quotes.
*/ */
int _execv(const char* name, char* const* argv) int _execv(const char* name, char* const* argv)
{ {
...@@ -232,6 +256,9 @@ int _execv(const char* name, char* const* argv) ...@@ -232,6 +256,9 @@ int _execv(const char* name, char* const* argv)
/********************************************************************* /*********************************************************************
* _execve (MSVCRT.@) * _execve (MSVCRT.@)
*
* Like on Windows, this function does not handle arguments with spaces
* or double-quotes.
*/ */
int _execve(const char* name, char* const* argv, const char* const* envv) int _execve(const char* name, char* const* argv, const char* const* envv)
{ {
...@@ -240,6 +267,9 @@ int _execve(const char* name, char* const* argv, const char* const* envv) ...@@ -240,6 +267,9 @@ int _execve(const char* name, char* const* argv, const char* const* envv)
/********************************************************************* /*********************************************************************
* _execvpe (MSVCRT.@) * _execvpe (MSVCRT.@)
*
* Like on Windows, this function does not handle arguments with spaces
* or double-quotes.
*/ */
int _execvpe(const char* name, char* const* argv, const char* const* envv) int _execvpe(const char* name, char* const* argv, const char* const* envv)
{ {
...@@ -252,6 +282,9 @@ int _execvpe(const char* name, char* const* argv, const char* const* envv) ...@@ -252,6 +282,9 @@ int _execvpe(const char* name, char* const* argv, const char* const* envv)
/********************************************************************* /*********************************************************************
* _execvp (MSVCRT.@) * _execvp (MSVCRT.@)
*
* Like on Windows, this function does not handle arguments with spaces
* or double-quotes.
*/ */
int _execvp(const char* name, char* const* argv) int _execvp(const char* name, char* const* argv)
{ {
...@@ -260,6 +293,9 @@ int _execvp(const char* name, char* const* argv) ...@@ -260,6 +293,9 @@ int _execvp(const char* name, char* const* argv)
/********************************************************************* /*********************************************************************
* _spawnl (MSVCRT.@) * _spawnl (MSVCRT.@)
*
* Like on Windows, this function does not handle arguments with spaces
* or double-quotes.
*/ */
int _spawnl(int flags, const char* name, const char* arg0, ...) int _spawnl(int flags, const char* name, const char* arg0, ...)
{ {
...@@ -279,6 +315,9 @@ int _spawnl(int flags, const char* name, const char* arg0, ...) ...@@ -279,6 +315,9 @@ int _spawnl(int flags, const char* name, const char* arg0, ...)
/********************************************************************* /*********************************************************************
* _spawnlp (MSVCRT.@) * _spawnlp (MSVCRT.@)
*
* Like on Windows, this function does not handle arguments with spaces
* or double-quotes.
*/ */
int _spawnlp(int flags, const char* name, const char* arg0, ...) int _spawnlp(int flags, const char* name, const char* arg0, ...)
{ {
...@@ -301,6 +340,9 @@ int _spawnlp(int flags, const char* name, const char* arg0, ...) ...@@ -301,6 +340,9 @@ int _spawnlp(int flags, const char* name, const char* arg0, ...)
/********************************************************************* /*********************************************************************
* _spawnve (MSVCRT.@) * _spawnve (MSVCRT.@)
*
* Like on Windows, this function does not handle arguments with spaces
* or double-quotes.
*/ */
int _spawnve(int flags, const char* name, const char* const* argv, int _spawnve(int flags, const char* name, const char* const* argv,
const char* const* envv) const char* const* envv)
...@@ -326,6 +368,9 @@ int _spawnve(int flags, const char* name, const char* const* argv, ...@@ -326,6 +368,9 @@ int _spawnve(int flags, const char* name, const char* const* argv,
/********************************************************************* /*********************************************************************
* _spawnv (MSVCRT.@) * _spawnv (MSVCRT.@)
*
* Like on Windows, this function does not handle arguments with spaces
* or double-quotes.
*/ */
int _spawnv(int flags, const char* name, const char* const* argv) int _spawnv(int flags, const char* name, const char* const* argv)
{ {
...@@ -334,6 +379,9 @@ int _spawnv(int flags, const char* name, const char* const* argv) ...@@ -334,6 +379,9 @@ int _spawnv(int flags, const char* name, const char* const* argv)
/********************************************************************* /*********************************************************************
* _spawnvpe (MSVCRT.@) * _spawnvpe (MSVCRT.@)
*
* Like on Windows, this function does not handle arguments with spaces
* or double-quotes.
*/ */
int _spawnvpe(int flags, const char* name, const char* const* argv, int _spawnvpe(int flags, const char* name, const char* const* argv,
const char* const* envv) const char* const* envv)
...@@ -345,6 +393,9 @@ int _spawnvpe(int flags, const char* name, const char* const* argv, ...@@ -345,6 +393,9 @@ int _spawnvpe(int flags, const char* name, const char* const* argv,
/********************************************************************* /*********************************************************************
* _spawnvp (MSVCRT.@) * _spawnvp (MSVCRT.@)
*
* Like on Windows, this function does not handle arguments with spaces
* or double-quotes.
*/ */
int _spawnvp(int flags, const char* name, const char* const* argv) int _spawnvp(int flags, const char* name, const char* const* argv)
{ {
...@@ -356,8 +407,15 @@ int _spawnvp(int flags, const char* name, const char* const* argv) ...@@ -356,8 +407,15 @@ int _spawnvp(int flags, const char* name, const char* const* argv)
*/ */
int MSVCRT_system(const char* cmd) int MSVCRT_system(const char* cmd)
{ {
/* FIXME: should probably launch cmd interpreter in COMSPEC */ char* cmdcopy;
return msvcrt_spawn(_P_WAIT, cmd, NULL, NULL); int res;
/* Make a writable copy for CreateProcess */
cmdcopy=_strdup(cmd);
/* FIXME: should probably launch cmd interpreter in COMSPEC */
res=msvcrt_spawn(_P_WAIT, NULL, cmdcopy, NULL);
MSVCRT_free(cmdcopy);
return res;
} }
/********************************************************************* /*********************************************************************
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment