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