Implementation of spawnl and spawnlp.
diff --git a/dlls/msvcrt/msvcrt.spec b/dlls/msvcrt/msvcrt.spec index 7c10e9f..5729933 100644 --- a/dlls/msvcrt/msvcrt.spec +++ b/dlls/msvcrt/msvcrt.spec
@@ -442,9 +442,9 @@ @ varargs _snprintf(str long str) snprintf @ forward -noimport _snwprintf ntdll._snwprintf @ cdecl _sopen(str long long) MSVCRT__sopen -@ stub _spawnl #(str str) varargs +@ varargs _spawnl(str str) _spawnl @ stub _spawnle #(str str) varargs -@ stub _spawnlp #(str str) varargs +@ varargs _spawnlp(str str) _spawnlp @ stub _spawnlpe #(str str) varargs @ cdecl _spawnv(long str ptr) _spawnv @ cdecl _spawnve(long str ptr ptr) _spawnve
diff --git a/dlls/msvcrt/process.c b/dlls/msvcrt/process.c index b9c805c..4f946a2 100644 --- a/dlls/msvcrt/process.c +++ b/dlls/msvcrt/process.c
@@ -109,6 +109,45 @@ return ret; } +/* INTERNAL: Convert va_list to a single 'delim'-separated string */ +static char* msvcrt_valisttos(const char* arg0, va_list ap, char delim) +{ + va_list search = ap; + long size; + char *arg; + char *ret; + int strsize; + + if (!arg0 && !delim) + return NULL; + + /* get length */ + size = strlen(arg0) + 1; + while((arg = va_arg(search, char *)) != NULL) + { + size += strlen(arg) + 1; + } + + if (!(ret = (char *)MSVCRT_calloc(size + 1, 1))) + return NULL; + + /* fill string */ + search = ap; + size = 0; + strsize = strlen(arg0); + memcpy(ret+size,arg0,strsize); + ret[size+strsize] = delim; + size += strsize + 1; + while((arg = va_arg(search, char *)) != NULL) + { + strsize = strlen(search); + memcpy(ret+size,search,strsize); + ret[size+strsize] = delim; + size += strsize + 1; + } + return ret; +} + /********************************************************************* * _cwait (MSVCRT.@) */ @@ -143,6 +182,47 @@ } /********************************************************************* + * _spawnl (MSVCRT.@) + */ +int _spawnl(int flags, const char* name, const char* arg0, ...) +{ + va_list ap; + char * args; + int ret; + + va_start(ap, arg0); + args = msvcrt_valisttos(arg0, ap, ' '); + va_end(ap); + + ret = msvcrt_spawn(flags, name, args, NULL); + MSVCRT_free(args); + + return ret; +} + +/********************************************************************* + * _spawnl (MSVCRT.@) + */ +int _spawnlp(int flags, const char* name, const char* arg0, ...) +{ + va_list ap; + char * args; + int ret; + char fullname[MAX_PATH]; + + _searchenv(name, "PATH", fullname); + + va_start(ap, arg0); + args = msvcrt_valisttos(arg0, ap, ' '); + va_end(ap); + + ret = msvcrt_spawn(flags, name, args, NULL); + MSVCRT_free(args); + + return ret; +} + +/********************************************************************* * _spawnve (MSVCRT.@) */ int _spawnve(int flags, const char* name, const char* const* argv,