diff -r 000000000000 -r e4d67989cc36 genericopenlibs/openenvcore/libc/src/spawn.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/genericopenlibs/openenvcore/libc/src/spawn.cpp Tue Feb 02 02:01:42 2010 +0200 @@ -0,0 +1,549 @@ +// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// +// + +#include +#include "spawn_r.h" +#include +#include +#include +#include +#include +#include +#include "sysreent.h" + +extern "C" { + +// ----------------------------------------------------------------------------- +// posix_spawn_file_actions_init +// Initialize the file actions structure +// ----------------------------------------------------------------------------- +EXPORT_C int posix_spawn_file_actions_init(posix_spawn_file_actions_t* file_actions) + { + file_actions->_fa = new file_actions_t; + if (!file_actions->_fa) + { + return ENOMEM; + } + return 0; + } + +// ----------------------------------------------------------------------------- +// posix_spawn_file_actions_addopen +// Add an open action to the file actions structure +// ----------------------------------------------------------------------------- +EXPORT_C int posix_spawn_file_actions_addopen( + posix_spawn_file_actions_t* file_actions, + int fid, + const char* path, + int oflag, + mode_t mode) + { + if (fid < 0 || fid > OPEN_MAX) + { + return EBADF; + } + + TFileAction* fa = new TFileAction; + if (!fa) + { + return ENOMEM; + } + + memset(fa, 0, sizeof(TFileAction)); + fa->iOp = EOpen; + fa->iFid1 = fid; + fa->iOFlag = oflag; + fa->iMode = mode; + + int len = strlen(path)+1; + wchar_t* wpath = new wchar_t[len]; + if (!wpath) + { + delete fa; + return ENOMEM; + } + + if (mbstowcs(wpath, path, len) == (size_t)-1) + { + delete fa; + delete[] wpath; + return EILSEQ; + } + + fa->iPath = new TFileName; + fa->iPath->Copy((TText16*)wpath, len); + delete[] wpath; + + (file_actions->_fa->iActions).AddLast(*fa); + if (file_actions->_fa->iIter == NULL) + { + (file_actions->_fa->iIter).SetToFirst(); + } + + return 0; + } + +// ----------------------------------------------------------------------------- +// posix_spawn_file_actions_adddup2 +// Add a dup2 action to the file actions structure +// ----------------------------------------------------------------------------- +EXPORT_C int posix_spawn_file_actions_adddup2( + posix_spawn_file_actions_t* file_actions, + int fid1, + int fid2) + { + if (fid1 < 0 || fid2 < 0 || fid1 > OPEN_MAX || fid2 > OPEN_MAX) + { + return EBADF; + } + + TFileAction* fa = new TFileAction; + if (!fa) + { + return ENOMEM; + } + + memset(fa, 0, sizeof(TFileAction)); + fa->iOp = EDup; + fa->iFid1 = fid1; + fa->iFid2 = fid2; + + (file_actions->_fa->iActions).AddLast(*fa); + if (file_actions->_fa->iIter == NULL) + { + (file_actions->_fa->iIter).SetToFirst(); + } + + return 0; + } + +// ----------------------------------------------------------------------------- +// posix_spawn_file_actions_addclose +// Add a close action to the file actions structure +// ----------------------------------------------------------------------------- +EXPORT_C int posix_spawn_file_actions_addclose( + posix_spawn_file_actions_t* file_actions, + int fid) + { + if (fid < 0 || fid > OPEN_MAX) + { + return EBADF; + } + + TFileAction* fa = new TFileAction; + if (!fa) + { + return ENOMEM; + } + + memset(fa, 0, sizeof(TFileAction)); + fa->iOp = EClose; + fa->iFid1 = fid; + (file_actions->_fa->iActions).AddLast(*fa); + if (file_actions->_fa->iIter == NULL) + { + (file_actions->_fa->iIter).SetToFirst(); + } + + return 0; + } + +// ----------------------------------------------------------------------------- +// posix_spawn_file_actions_destroy +// Empty and destroy the file actions structure +// ----------------------------------------------------------------------------- +EXPORT_C int posix_spawn_file_actions_destroy(posix_spawn_file_actions_t* file_actions) + { + if (!file_actions || !file_actions->_fa) + { + return EINVAL; + } + + if (file_actions->_fa->iActions.IsEmpty()) + { + delete file_actions->_fa; + return 0; + } + + TFileAction* fa = (file_actions->_fa->iIter)++; + while (fa) + { + if (fa->iPath) + { + delete fa->iPath; + } + + delete fa; + fa = (file_actions->_fa->iIter)++; + } + + file_actions->_fa->iActions.Reset(); + delete file_actions->_fa; + return 0; + } + +// ----------------------------------------------------------------------------- +// posix_spawnattr_init +// Initialize the spawn attributes structure +// ----------------------------------------------------------------------------- +EXPORT_C int posix_spawnattr_init(posix_spawnattr_t* attrp) + { + // we don't support these flags. simply set all attribs to 0. + if (!attrp) + { + return EINVAL; + } + memset(attrp, 0, sizeof(posix_spawnattr_t)); + return 0; + } + +// ----------------------------------------------------------------------------- +// posix_spawnattr_getsigdefault +// Returns the sigdefault attribute +// ----------------------------------------------------------------------------- +EXPORT_C int posix_spawnattr_getsigdefault( + const posix_spawnattr_t* attrp, + sigset_t* sigdefault) + { + if (!attrp || !sigdefault) + { + return EINVAL; + } + + *sigdefault = attrp->_sd; + return 0; + } + +// ----------------------------------------------------------------------------- +// posix_spawnattr_getflags +// Return the flags attribute +// ----------------------------------------------------------------------------- +EXPORT_C int posix_spawnattr_getflags( + const posix_spawnattr_t* attrp, + short* flags) + { + if (!attrp || !flags) + { + return EINVAL; + } + + *flags = attrp->_flags; + return 0; + } + +// ----------------------------------------------------------------------------- +// posix_spawnattr_getpgroup +// Return the process group attribute +// ----------------------------------------------------------------------------- +EXPORT_C int posix_spawnattr_getpgroup( + const posix_spawnattr_t* attrp, + pid_t* pgroup) + { + if (!attrp || !pgroup) + { + return EINVAL; + } + + *pgroup = attrp->_pgrp; + return 0; + } + +// ----------------------------------------------------------------------------- +// posix_spawnattr_getschedparam +// Return scheduling parameters attribute +// ----------------------------------------------------------------------------- +EXPORT_C int posix_spawnattr_getschedparam( + const posix_spawnattr_t* attrp, + struct sched_param* schedparam) + { + if (!attrp || !schedparam) + { + return EINVAL; + } + + *schedparam = attrp->_sp; + return 0; + } + +// ----------------------------------------------------------------------------- +// posix_spawnattr_getschedpolicy +// Return the scheduling policy attribute +// ----------------------------------------------------------------------------- +EXPORT_C int posix_spawnattr_getschedpolicy( + const posix_spawnattr_t* attrp, + int* policy) + { + if (!attrp || !policy) + { + return EINVAL; + } + + *policy = attrp->_policy; + return 0; + } + +// ----------------------------------------------------------------------------- +// posix_spawnattr_getsigmask +// Return the signal mask attribute +// ----------------------------------------------------------------------------- +EXPORT_C int posix_spawnattr_getsigmask( + const posix_spawnattr_t* attrp, + sigset_t* sigmask) + { + if (!attrp || !sigmask) + { + return EINVAL; + } + + *sigmask = attrp->_sm; + return 0; + } + +// ----------------------------------------------------------------------------- +// posix_spawnattr_setsigdefault +// Sets the sigdefault attribute +// ----------------------------------------------------------------------------- +EXPORT_C int posix_spawnattr_setsigdefault( + posix_spawnattr_t* attrp, + const sigset_t* sigdefault) + { + if (!attrp || !sigdefault) + { + return EINVAL; + } + + attrp->_sd = *sigdefault; + return 0; + } + +// ----------------------------------------------------------------------------- +// posix_spawnattr_setflags +// Sets the flags attribute +// ----------------------------------------------------------------------------- +EXPORT_C int posix_spawnattr_setflags(posix_spawnattr_t* attrp, short flags) + { + if (!attrp) + { + return EINVAL; + } + + attrp->_flags = flags; + return 0; + } + +// ----------------------------------------------------------------------------- +// posix_spawnattr_setpgroup +// Sets the process group attribute +// ----------------------------------------------------------------------------- +EXPORT_C int posix_spawnattr_setpgroup(posix_spawnattr_t* attrp, pid_t pgroup) + { + if (!attrp) + { + return EINVAL; + } + + attrp->_pgrp = pgroup; + return 0; + } + +// ----------------------------------------------------------------------------- +// posix_spawnattr_setschedparam +// Sets the scheduling parameters attribute +// ----------------------------------------------------------------------------- +EXPORT_C int posix_spawnattr_setschedparam( + posix_spawnattr_t* attrp, + const struct sched_param* schedparam) + { + if (!attrp || !schedparam) + { + return EINVAL; + } + + attrp->_sp = *schedparam; + return 0; + } + +// ----------------------------------------------------------------------------- +// posix_spawnattr_setschedpolicy +// Sets the scheduling policy attribute +// ----------------------------------------------------------------------------- +EXPORT_C int posix_spawnattr_setschedpolicy(posix_spawnattr_t* attrp, int policy) + { + if (!attrp) + { + return EINVAL; + } + + attrp->_policy = policy; + return 0; + } + +// ----------------------------------------------------------------------------- +// posix_spawnattr_setsigdefault +// Sets the sigmask attribute +// ----------------------------------------------------------------------------- +EXPORT_C int posix_spawnattr_setsigmask( + posix_spawnattr_t* attrp, + const sigset_t* sigmask) + { + if (!attrp || !sigmask) + { + return EINVAL; + } + + attrp->_sm = *sigmask; + return 0; + } + +// ----------------------------------------------------------------------------- +// posix_spawnattr_setsigdefault +// Empty and cleanup the spawn attributes structure +// ----------------------------------------------------------------------------- +EXPORT_C int posix_spawnattr_destroy(posix_spawnattr_t* /*attrp*/) + { + // nothing to do + return 0; + } + +// ----------------------------------------------------------------------------- +// posix_spawn +// Launch a child process specified by path and obtain its pid +// This API allows the caller to specify command line arguments and envp for the child +// In addition, one can also specify a set of file operations that will be performed +// and a set of attributes that will be applied in the child before it enters its main. +// ----------------------------------------------------------------------------- +EXPORT_C int posix_spawn( + pid_t* pid, + const char* path, + const posix_spawn_file_actions_t* file_actions, + const posix_spawnattr_t* attrp, + char *const argv[], + char *const envp[]) + { + if(path == NULL || *path == '\0') + { + return ECHILD; + } + + int len = strlen(path) + 1; + wchar_t* wpath = new wchar_t[len]; + if (mbstowcs(wpath, path, len) == (size_t)-1) + { + delete[] wpath; + return EILSEQ; + } + + int ret = 0; + + wchar_t* wargs = NULL; + wchar_t** wenvp = NULL; + + if (argv && argv[1]) + { + TInt totlen = 0; + // argv[0] is (or atleast should be) the exe name + for (int i = 1; argv[i]; ++i) + { + totlen += strlen(argv[i]) + 1; + } + + wargs = new wchar_t[totlen+1]; + + if (!wargs) + { + ret = ENOMEM; + goto bailout; + } + + wchar_t* wp = wargs; + // argv[0] is (or atleast should be) the exe name + for (int i = 1; argv[i]; ++i) + { + int len = strlen(argv[i]); + if (mbstowcs(wp, argv[i], len) == (size_t)-1) + { + ret = EILSEQ; + goto bailout; + } + wp[len++] = L' '; + wp += len; + } + + // replace the last blank with a null character + *(--wp) = 0; + } + + if (envp) + { + TInt count = 0; + for (; envp[count]; ++count) {} + + //coverity[alloc_fn] + + //coverity[assign] + + wenvp = new wchar_t*[count+1]; + if (!wenvp) + { + ret = ENOMEM; + goto bailout; + } + + for (int i = 0; i < count; ++i) + { + int len = strlen(envp[i]) + 1; + wenvp[i] = new wchar_t[len]; + if (wenvp[i] == NULL) + { + ret = ENOMEM; + goto bailout; + } + + if (mbstowcs(wenvp[i], envp[i], len) == (size_t)-1) + { + ret = EILSEQ; + wenvp[i+1] = NULL; + goto bailout; + } + } + + wenvp[count] = 0; + } + + //coverity[leave_without_push] + + ret = _posix_spawn_r(pid, wpath, file_actions, attrp, wargs, wenvp); + +bailout: + delete[] wpath; + if (wargs) + { + delete[] wargs; + } + + if (wenvp) + { + for (int i = 0; wenvp[i]; ++i) + { + delete wenvp[i]; + } + delete wenvp; + } + + return ret; + } + +} //extern "C"