|
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" |