os/ossrv/genericopenlibs/openenvcore/libc/src/spawn.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 // Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
     2 // All rights reserved.
     3 // This component and the accompanying materials are made available
     4 // under the terms of "Eclipse Public License v1.0"
     5 // which accompanies this distribution, and is available
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 // 
    15 //
    16 
    17 #include <e32std.h>
    18 #include "spawn_r.h"
    19 #include <spawn.h>
    20 #include <sys/syslimits.h>
    21 #include <errno.h>
    22 #include <wchar.h>
    23 #include <stdlib.h>
    24 #include <string.h>
    25 #include "sysreent.h"
    26 
    27 extern "C" {
    28 
    29 // -----------------------------------------------------------------------------
    30 // posix_spawn_file_actions_init
    31 // Initialize the file actions structure
    32 // -----------------------------------------------------------------------------
    33 EXPORT_C int posix_spawn_file_actions_init(posix_spawn_file_actions_t* file_actions)
    34 	{
    35 	file_actions->_fa = new file_actions_t;
    36 	if (!file_actions->_fa)
    37 		{
    38 		return ENOMEM;
    39 		}
    40 	return 0;
    41 	}
    42 
    43 // -----------------------------------------------------------------------------
    44 // posix_spawn_file_actions_addopen
    45 // Add an open action to the file actions structure
    46 // -----------------------------------------------------------------------------
    47 EXPORT_C int posix_spawn_file_actions_addopen(
    48 				posix_spawn_file_actions_t* file_actions, 
    49 				int fid,
    50 				const char* path, 
    51 				int oflag, 
    52 				mode_t mode)
    53 	{
    54 	if (fid < 0 || fid > OPEN_MAX)
    55 		{
    56 		return EBADF;
    57 		}
    58 		
    59 	TFileAction* fa = new TFileAction;
    60 	if (!fa)
    61 		{
    62 		return ENOMEM;
    63 		}
    64 	
    65 	memset(fa, 0, sizeof(TFileAction));	
    66 	fa->iOp = EOpen;
    67 	fa->iFid1 = fid;
    68 	fa->iOFlag = oflag;
    69 	fa->iMode = mode;
    70 	
    71 	int len = strlen(path)+1;
    72 	wchar_t* wpath = new wchar_t[len];
    73 	if (!wpath)
    74 		{
    75 		delete fa;
    76 		return ENOMEM;
    77 		}
    78 		
    79 	if (mbstowcs(wpath, path, len) == (size_t)-1)
    80 		{
    81 		delete fa;
    82 		delete[] wpath;
    83 		return EILSEQ;
    84 		}
    85 	
    86 	fa->iPath = new TFileName;
    87 	fa->iPath->Copy((TText16*)wpath, len);
    88 	delete[] wpath;
    89 	
    90 	(file_actions->_fa->iActions).AddLast(*fa);
    91 	if (file_actions->_fa->iIter == NULL)
    92 		{
    93 		(file_actions->_fa->iIter).SetToFirst();
    94 		}
    95 	
    96 	return 0;
    97 	}
    98 	
    99 // -----------------------------------------------------------------------------
   100 // posix_spawn_file_actions_adddup2
   101 // Add a dup2 action to the file actions structure
   102 // -----------------------------------------------------------------------------
   103 EXPORT_C int posix_spawn_file_actions_adddup2(
   104 				posix_spawn_file_actions_t* file_actions, 
   105 				int fid1, 
   106 				int fid2)
   107 	{
   108 	if (fid1 < 0 || fid2 < 0 || fid1 > OPEN_MAX || fid2 > OPEN_MAX)
   109 		{
   110 		return EBADF;
   111 		}
   112 		
   113 	TFileAction* fa = new TFileAction;
   114 	if (!fa)
   115 		{
   116 		return ENOMEM;
   117 		}
   118 
   119 	memset(fa, 0, sizeof(TFileAction));		
   120 	fa->iOp = EDup;
   121 	fa->iFid1 = fid1;
   122 	fa->iFid2 = fid2;
   123 	
   124 	(file_actions->_fa->iActions).AddLast(*fa);
   125 	if (file_actions->_fa->iIter == NULL)
   126 		{
   127 		(file_actions->_fa->iIter).SetToFirst();
   128 		}
   129 		
   130 	return 0;
   131 	}
   132 
   133 // -----------------------------------------------------------------------------
   134 // posix_spawn_file_actions_addclose
   135 // Add a close action to the file actions structure
   136 // -----------------------------------------------------------------------------
   137 EXPORT_C int posix_spawn_file_actions_addclose(
   138 				posix_spawn_file_actions_t* file_actions, 
   139 				int fid)
   140 	{
   141 	if (fid < 0 || fid > OPEN_MAX)
   142 		{
   143 		return EBADF;
   144 		}
   145 		
   146 	TFileAction* fa = new TFileAction;
   147 	if (!fa)
   148 		{
   149 		return ENOMEM;
   150 		}
   151 	
   152 	memset(fa, 0, sizeof(TFileAction));	
   153 	fa->iOp = EClose;
   154 	fa->iFid1 = fid;
   155 	(file_actions->_fa->iActions).AddLast(*fa);
   156 	if (file_actions->_fa->iIter == NULL)
   157 		{
   158 		(file_actions->_fa->iIter).SetToFirst();
   159 		}
   160 		
   161 	return 0;
   162 	}
   163 
   164 // -----------------------------------------------------------------------------
   165 // posix_spawn_file_actions_destroy
   166 // Empty and destroy the file actions structure
   167 // -----------------------------------------------------------------------------
   168 EXPORT_C int posix_spawn_file_actions_destroy(posix_spawn_file_actions_t* file_actions)
   169 	{
   170 	if (!file_actions || !file_actions->_fa)
   171 		{
   172 		return EINVAL;
   173 		}
   174 		
   175 	if (file_actions->_fa->iActions.IsEmpty())
   176 		{
   177 		delete file_actions->_fa;
   178 		return 0;
   179 		}
   180 	
   181 	TFileAction* fa = (file_actions->_fa->iIter)++;
   182 	while (fa)
   183 		{
   184 		if (fa->iPath)
   185 			{
   186 			delete fa->iPath;
   187 			}
   188 			
   189 		delete fa;
   190 		fa = (file_actions->_fa->iIter)++;
   191 		}
   192 		
   193 	file_actions->_fa->iActions.Reset();
   194 	delete file_actions->_fa;
   195 	return 0;
   196 	}
   197 
   198 // -----------------------------------------------------------------------------
   199 // posix_spawnattr_init
   200 // Initialize the spawn attributes structure
   201 // -----------------------------------------------------------------------------
   202 EXPORT_C int posix_spawnattr_init(posix_spawnattr_t* attrp)
   203 	{
   204 	// we don't support these flags. simply set all attribs to 0.
   205 	if (!attrp)
   206 		{
   207 		return EINVAL;
   208 		}
   209 	memset(attrp, 0, sizeof(posix_spawnattr_t));
   210 	return 0;
   211 	}
   212 
   213 // -----------------------------------------------------------------------------
   214 // posix_spawnattr_getsigdefault
   215 // Returns the sigdefault attribute
   216 // -----------------------------------------------------------------------------
   217 EXPORT_C int posix_spawnattr_getsigdefault(
   218 				const posix_spawnattr_t* attrp, 
   219 				sigset_t* sigdefault)
   220 	{
   221 	if (!attrp || !sigdefault)
   222 		{
   223 		return EINVAL;
   224 		}
   225 	
   226 	*sigdefault = attrp->_sd;
   227 	return 0;
   228 	}
   229 
   230 // -----------------------------------------------------------------------------
   231 // posix_spawnattr_getflags
   232 // Return the flags attribute
   233 // -----------------------------------------------------------------------------
   234 EXPORT_C int posix_spawnattr_getflags(
   235 				const posix_spawnattr_t* attrp,
   236 				short* flags)
   237 	{
   238 	if (!attrp || !flags)
   239 		{
   240 		return EINVAL;
   241 		}
   242 	
   243 	*flags = attrp->_flags;
   244 	return 0;
   245 	}
   246 
   247 // -----------------------------------------------------------------------------
   248 // posix_spawnattr_getpgroup
   249 // Return the process group attribute
   250 // -----------------------------------------------------------------------------
   251 EXPORT_C int posix_spawnattr_getpgroup(
   252 				const posix_spawnattr_t* attrp, 
   253 				pid_t* pgroup)
   254 	{
   255 	if (!attrp || !pgroup)
   256 		{
   257 		return EINVAL;
   258 		}
   259 	
   260 	*pgroup = attrp->_pgrp;
   261 	return 0;
   262 	}
   263 
   264 // -----------------------------------------------------------------------------
   265 // posix_spawnattr_getschedparam
   266 // Return scheduling parameters attribute
   267 // -----------------------------------------------------------------------------
   268 EXPORT_C int posix_spawnattr_getschedparam(
   269 				const posix_spawnattr_t* attrp,
   270           		struct sched_param* schedparam)
   271 	{
   272 	if (!attrp || !schedparam)
   273 		{
   274 		return EINVAL;
   275 		}
   276 	
   277 	*schedparam = attrp->_sp;
   278 	return 0;
   279 	}
   280 
   281 // -----------------------------------------------------------------------------
   282 // posix_spawnattr_getschedpolicy
   283 // Return the scheduling policy attribute
   284 // -----------------------------------------------------------------------------
   285 EXPORT_C int posix_spawnattr_getschedpolicy(
   286 				const posix_spawnattr_t* attrp, 
   287 				int* policy)
   288 	{
   289 	if (!attrp || !policy)
   290 		{
   291 		return EINVAL;
   292 		}
   293 	
   294 	*policy = attrp->_policy;
   295 	return 0;
   296 	}
   297 
   298 // -----------------------------------------------------------------------------
   299 // posix_spawnattr_getsigmask
   300 // Return the signal mask attribute
   301 // -----------------------------------------------------------------------------
   302 EXPORT_C int posix_spawnattr_getsigmask(
   303 				const posix_spawnattr_t* attrp, 
   304 				sigset_t* sigmask)
   305 	{
   306 	if (!attrp || !sigmask)
   307 		{
   308 		return EINVAL;
   309 		}
   310 	
   311 	*sigmask = attrp->_sm;
   312 	return 0;
   313 	}
   314 
   315 // -----------------------------------------------------------------------------
   316 // posix_spawnattr_setsigdefault
   317 // Sets the sigdefault attribute
   318 // -----------------------------------------------------------------------------
   319 EXPORT_C int posix_spawnattr_setsigdefault(
   320 				posix_spawnattr_t* attrp,
   321 				const sigset_t* sigdefault)
   322 	{
   323 	if (!attrp || !sigdefault)
   324 		{
   325 		return EINVAL;
   326 		}
   327 	
   328 	attrp->_sd = *sigdefault;
   329 	return 0;
   330 	}
   331 
   332 // -----------------------------------------------------------------------------
   333 // posix_spawnattr_setflags
   334 // Sets the flags attribute
   335 // -----------------------------------------------------------------------------
   336 EXPORT_C int posix_spawnattr_setflags(posix_spawnattr_t* attrp, short flags)
   337 	{
   338 	if (!attrp)
   339 		{
   340 		return EINVAL;
   341 		}
   342 	
   343 	attrp->_flags = flags;
   344 	return 0;
   345 	}
   346 
   347 // -----------------------------------------------------------------------------
   348 // posix_spawnattr_setpgroup
   349 // Sets the process group attribute
   350 // -----------------------------------------------------------------------------
   351 EXPORT_C int posix_spawnattr_setpgroup(posix_spawnattr_t* attrp, pid_t pgroup)
   352 	{
   353 	if (!attrp)
   354 		{
   355 		return EINVAL;
   356 		}
   357 	
   358 	attrp->_pgrp = pgroup;
   359 	return 0;
   360 	}
   361 
   362 // -----------------------------------------------------------------------------
   363 // posix_spawnattr_setschedparam
   364 // Sets the scheduling parameters attribute
   365 // -----------------------------------------------------------------------------
   366 EXPORT_C int posix_spawnattr_setschedparam(
   367 				posix_spawnattr_t* attrp,
   368 				const struct sched_param* schedparam)
   369 	{
   370 	if (!attrp || !schedparam)
   371 		{
   372 		return EINVAL;
   373 		}
   374 	
   375 	attrp->_sp = *schedparam;
   376 	return 0;
   377 	}
   378 
   379 // -----------------------------------------------------------------------------
   380 // posix_spawnattr_setschedpolicy
   381 // Sets the scheduling policy attribute
   382 // -----------------------------------------------------------------------------
   383 EXPORT_C int posix_spawnattr_setschedpolicy(posix_spawnattr_t* attrp, int policy)
   384 	{
   385 	if (!attrp)
   386 		{
   387 		return EINVAL;
   388 		}
   389 	
   390 	attrp->_policy = policy;
   391 	return 0;
   392 	}
   393 
   394 // -----------------------------------------------------------------------------
   395 // posix_spawnattr_setsigdefault
   396 // Sets the sigmask attribute
   397 // -----------------------------------------------------------------------------
   398 EXPORT_C int posix_spawnattr_setsigmask(
   399 				posix_spawnattr_t* attrp, 
   400 				const sigset_t* sigmask)
   401 	{
   402 	if (!attrp || !sigmask)
   403 		{
   404 		return EINVAL;
   405 		}
   406 	
   407 	attrp->_sm = *sigmask;
   408 	return 0;
   409 	}
   410 
   411 // -----------------------------------------------------------------------------
   412 // posix_spawnattr_setsigdefault
   413 // Empty and cleanup the spawn attributes structure
   414 // -----------------------------------------------------------------------------
   415 EXPORT_C int posix_spawnattr_destroy(posix_spawnattr_t* /*attrp*/)
   416 	{
   417 	// nothing to do
   418 	return 0;
   419 	}
   420 
   421 // -----------------------------------------------------------------------------
   422 // posix_spawn
   423 // Launch a child process specified by path and obtain its pid
   424 // This API allows the caller to specify command line arguments and envp for the child
   425 // In addition, one can also specify a set of file operations that will be performed
   426 // and a set of attributes that will be applied in the child before it enters its main.
   427 // -----------------------------------------------------------------------------
   428 EXPORT_C int posix_spawn(
   429 				pid_t* pid, 
   430 				const char* path,
   431 				const posix_spawn_file_actions_t* file_actions,
   432 				const posix_spawnattr_t* attrp, 
   433 				char *const argv[],
   434 				char *const envp[])
   435 	{
   436 	if(path == NULL || *path == '\0')
   437 		{
   438 		return ECHILD;
   439 		}
   440 		
   441 	int len = strlen(path) + 1;
   442 	wchar_t* wpath = new wchar_t[len];
   443 	if (mbstowcs(wpath, path, len) == (size_t)-1)
   444 		{
   445 		delete[] wpath;
   446 		return EILSEQ;
   447 		}
   448 	
   449 	int ret = 0;
   450 	
   451 	wchar_t* wargs = NULL;
   452 	wchar_t** wenvp = NULL;
   453 	
   454 	if (argv && argv[1])
   455 		{
   456 		TInt totlen = 0;
   457 		// argv[0] is (or atleast should be) the exe name
   458 		for (int i = 1; argv[i]; ++i)
   459 			{
   460 			totlen += strlen(argv[i]) + 1;
   461 			}
   462 			
   463 		wargs = new wchar_t[totlen+1];
   464 		
   465 		if (!wargs)
   466 			{
   467 			ret = ENOMEM;
   468 			goto bailout;
   469 			}
   470 
   471 		wchar_t* wp = wargs;
   472 		// argv[0] is (or atleast should be) the exe name
   473 		for (int i = 1; argv[i]; ++i)
   474 			{
   475 			int len = strlen(argv[i]);
   476 			if (mbstowcs(wp, argv[i], len) == (size_t)-1)
   477 				{
   478 				ret = EILSEQ;
   479 				goto bailout;
   480 				}
   481 			wp[len++] = L' ';
   482 			wp += len;
   483 			}
   484 		
   485 		// replace the last blank with a null character
   486 		*(--wp) = 0;
   487 		}
   488 	
   489 	if (envp)
   490 		{
   491 		TInt count = 0;
   492 		for (; envp[count]; ++count) {}
   493 
   494 		//coverity[alloc_fn]
   495 
   496 		//coverity[assign]
   497 	
   498 		wenvp = new wchar_t*[count+1];
   499 		if (!wenvp)
   500 			{
   501 			ret = ENOMEM;
   502 			goto bailout;
   503 			}
   504 			
   505 		for (int i = 0; i < count; ++i)
   506 			{
   507 			int len = strlen(envp[i]) + 1;
   508 			wenvp[i] = new wchar_t[len];
   509 			if (wenvp[i] == NULL)
   510 				{
   511 				ret = ENOMEM;
   512 				goto bailout;
   513 				}
   514 			
   515 			if (mbstowcs(wenvp[i], envp[i], len) == (size_t)-1)
   516 				{
   517 				ret = EILSEQ;
   518 				wenvp[i+1] = NULL;
   519 				goto bailout;
   520 				}
   521 			}
   522 				
   523 		wenvp[count] = 0;
   524 		}
   525 
   526 	//coverity[leave_without_push]
   527 
   528 	ret = _posix_spawn_r(pid, wpath, file_actions, attrp, wargs, wenvp);
   529 
   530 bailout:
   531 	delete[] wpath;
   532 	if (wargs)
   533 		{
   534 		delete[] wargs;
   535 		}
   536 		
   537 	if (wenvp)
   538 		{
   539 		for (int i = 0; wenvp[i]; ++i)
   540 			{
   541 			delete wenvp[i];
   542 			}
   543 		delete wenvp;
   544 		}
   545 
   546 	return ret;
   547 	}
   548 
   549 }  //extern "C"