OLD | NEW |
1 /*- | 1 /*- |
2 * Copyright (c) 2008 Ed Schouten <ed@FreeBSD.org> | 2 * Copyright (c) 2008 Ed Schouten <ed@FreeBSD.org> |
3 * All rights reserved. | 3 * All rights reserved. |
4 * | 4 * |
5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
6 * modification, are permitted provided that the following conditions | 6 * modification, are permitted provided that the following conditions |
7 * are met: | 7 * are met: |
8 * 1. Redistributions of source code must retain the above copyright | 8 * 1. Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * 2. Redistributions in binary form must reproduce the above copyright | 10 * 2. Redistributions in binary form must reproduce the above copyright |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
84 <<_execve>>, <<execvpe>>, <<_exit>>, <<_open>>, <<sigaction>>, | 84 <<_execve>>, <<execvpe>>, <<_exit>>, <<_open>>, <<sigaction>>, |
85 <<sigprocmask>>, <<waitpid>>, <<sched_setscheduler>>, | 85 <<sigprocmask>>, <<waitpid>>, <<sched_setscheduler>>, |
86 <<sched_setparam>>, <<setegid>>, <<seteuid>>, <<setpgid>>, <<vfork>>. | 86 <<sched_setparam>>, <<setegid>>, <<seteuid>>, <<setpgid>>, <<vfork>>. |
87 */ | 87 */ |
88 | 88 |
89 #ifndef _NO_POSIX_SPAWN | 89 #ifndef _NO_POSIX_SPAWN |
90 | 90 |
91 #include <sys/cdefs.h> | 91 #include <sys/cdefs.h> |
92 | 92 |
93 #include <sys/signal.h> | 93 #include <sys/signal.h> |
94 #include <sys/queue.h> | |
95 #include <sys/wait.h> | 94 #include <sys/wait.h> |
96 #include <_syslist.h> | 95 #include <_syslist.h> |
97 | 96 |
98 #include <errno.h> | 97 #include <errno.h> |
99 #include <fcntl.h> | 98 #include <fcntl.h> |
100 #include <sched.h> | |
101 #include <spawn.h> | 99 #include <spawn.h> |
102 #include <signal.h> | 100 #include <signal.h> |
103 #include <stdlib.h> | 101 #include <stdlib.h> |
104 #include <string.h> | 102 #include <string.h> |
105 #include <unistd.h> | 103 #include <unistd.h> |
106 | 104 |
107 /* Only deal with a pointer to environ, to work around subtle bugs with shared | 105 /* Only deal with a pointer to environ, to work around subtle bugs with shared |
108 libraries and/or small data systems where the user declares his own | 106 libraries and/or small data systems where the user declares his own |
109 'environ'. */ | 107 'environ'. */ |
110 static char ***p_environ = &environ; | 108 static char ***p_environ = &environ; |
111 | 109 |
112 struct __posix_spawnattr { | |
113 short sa_flags; | |
114 pid_t sa_pgroup; | |
115 struct sched_param sa_schedparam; | |
116 int sa_schedpolicy; | |
117 sigset_t sa_sigdefault; | |
118 sigset_t sa_sigmask; | |
119 }; | |
120 | |
121 struct __posix_spawn_file_actions { | |
122 STAILQ_HEAD(, __posix_spawn_file_actions_entry) fa_list; | |
123 }; | |
124 | |
125 typedef struct __posix_spawn_file_actions_entry { | |
126 STAILQ_ENTRY(__posix_spawn_file_actions_entry) fae_list; | |
127 enum { FAE_OPEN, FAE_DUP2, FAE_CLOSE } fae_action; | |
128 | |
129 int fae_fildes; | |
130 union { | |
131 struct { | |
132 char *path; | |
133 #define fae_path fae_data.open.path | |
134 int oflag; | |
135 #define fae_oflag fae_data.open.oflag | |
136 mode_t mode; | |
137 #define fae_mode fae_data.open.mode | |
138 } open; | |
139 struct { | |
140 int newfildes; | |
141 #define fae_newfildes fae_data.dup2.newfildes | |
142 } dup2; | |
143 } fae_data; | |
144 } posix_spawn_file_actions_entry_t; | |
145 | |
146 /* | 110 /* |
147 * Spawn routines | 111 * Spawn routines |
148 */ | 112 */ |
149 | 113 |
150 static int | 114 static int |
151 process_spawnattr(_CONST posix_spawnattr_t sa) | 115 process_spawnattr(_CONST posix_spawnattr_t* sa) |
152 { | 116 { |
153 struct sigaction sigact = { .sa_flags = 0, .sa_handler = SIG_DFL }; | 117 struct sigaction sigact = { .sa_flags = 0, .sa_handler = SIG_DFL }; |
154 int i; | 118 int i; |
155 | 119 |
156 /* | 120 /* |
157 * POSIX doesn't really describe in which order everything | 121 * POSIX doesn't really describe in which order everything |
158 * should be set. We'll just set them in the order in which they | 122 * should be set. We'll just set them in the order in which they |
159 * are mentioned. | 123 * are mentioned. |
160 */ | 124 */ |
161 | 125 |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
234 break; | 198 break; |
235 case FAE_CLOSE: | 199 case FAE_CLOSE: |
236 /* Perform a close(), do not fail if already closed */ | 200 /* Perform a close(), do not fail if already closed */ |
237 (void)_close(fae->fae_fildes); | 201 (void)_close(fae->fae_fildes); |
238 break; | 202 break; |
239 } | 203 } |
240 return (0); | 204 return (0); |
241 } | 205 } |
242 | 206 |
243 static int | 207 static int |
244 process_file_actions(_CONST posix_spawn_file_actions_t fa) | 208 process_file_actions(_CONST posix_spawn_file_actions_t* fa) |
245 { | 209 { |
246 posix_spawn_file_actions_entry_t *fae; | 210 posix_spawn_file_actions_entry_t *fae; |
247 int error; | 211 int error; |
248 | 212 |
249 /* Replay all file descriptor modifications */ | 213 /* Replay all file descriptor modifications */ |
250 STAILQ_FOREACH(fae, &fa->fa_list, fae_list) { | 214 STAILQ_FOREACH(fae, &fa->fa_list, fae_list) { |
251 error = process_file_actions_entry(fae); | 215 error = process_file_actions_entry(fae); |
252 if (error) | 216 if (error) |
253 return (error); | 217 return (error); |
254 } | 218 } |
255 return (0); | 219 return (0); |
256 } | 220 } |
257 | 221 |
258 static int | 222 static int |
259 do_posix_spawn(pid_t *pid, _CONST char *path, | 223 do_posix_spawn(pid_t *pid, _CONST char *path, |
260 _CONST posix_spawn_file_actions_t *fa, | 224 _CONST posix_spawn_file_actions_t *fa, |
261 _CONST posix_spawnattr_t *sa, | 225 _CONST posix_spawnattr_t *sa, |
262 char * _CONST argv[], char * _CONST envp[], int use_env_path) | 226 char * _CONST argv[], char * _CONST envp[], int use_env_path) |
263 { | 227 { |
264 pid_t p; | 228 pid_t p; |
265 volatile int error = 0; | 229 volatile int error = 0; |
266 | 230 |
267 p = vfork(); | 231 p = vfork(); |
268 switch (p) { | 232 switch (p) { |
269 case -1: | 233 case -1: |
270 return (errno); | 234 return (errno); |
271 case 0: | 235 case 0: |
272 if (sa != NULL) { | 236 if (sa != NULL) { |
273 » » » error = process_spawnattr(*sa); | 237 » » » error = process_spawnattr(sa); |
274 if (error) | 238 if (error) |
275 _exit(127); | 239 _exit(127); |
276 } | 240 } |
277 if (fa != NULL) { | 241 if (fa != NULL) { |
278 » » » error = process_file_actions(*fa); | 242 » » » error = process_file_actions(fa); |
279 if (error) | 243 if (error) |
280 _exit(127); | 244 _exit(127); |
281 } | 245 } |
282 if (use_env_path) | 246 if (use_env_path) |
283 execvpe(path, argv, envp != NULL ? envp : *p_environ); | 247 execvpe(path, argv, envp != NULL ? envp : *p_environ); |
284 else | 248 else |
285 _execve(path, argv, envp != NULL ? envp : *p_environ); | 249 _execve(path, argv, envp != NULL ? envp : *p_environ); |
286 error = errno; | 250 error = errno; |
287 _exit(127); | 251 _exit(127); |
288 default: | 252 default: |
(...skipping 22 matching lines...) Expand all Loading... |
311 pid_t *pid _AND | 275 pid_t *pid _AND |
312 _CONST char *path _AND | 276 _CONST char *path _AND |
313 _CONST posix_spawn_file_actions_t *fa _AND | 277 _CONST posix_spawn_file_actions_t *fa _AND |
314 _CONST posix_spawnattr_t *sa _AND | 278 _CONST posix_spawnattr_t *sa _AND |
315 char * _CONST argv[] _AND | 279 char * _CONST argv[] _AND |
316 char * _CONST envp[]) | 280 char * _CONST envp[]) |
317 { | 281 { |
318 return do_posix_spawn(pid, path, fa, sa, argv, envp, 1); | 282 return do_posix_spawn(pid, path, fa, sa, argv, envp, 1); |
319 } | 283 } |
320 | 284 |
321 /* | |
322 * File descriptor actions | |
323 */ | |
324 | |
325 int | |
326 _DEFUN(posix_spawn_file_actions_init, (ret), | |
327 posix_spawn_file_actions_t *ret) | |
328 { | |
329 posix_spawn_file_actions_t fa; | |
330 | |
331 fa = malloc(sizeof(struct __posix_spawn_file_actions)); | |
332 if (fa == NULL) | |
333 return (-1); | |
334 | |
335 STAILQ_INIT(&fa->fa_list); | |
336 *ret = fa; | |
337 return (0); | |
338 } | |
339 | |
340 int | |
341 _DEFUN(posix_spawn_file_actions_destroy, (fa), | |
342 posix_spawn_file_actions_t *fa) | |
343 { | |
344 posix_spawn_file_actions_entry_t *fae; | |
345 | |
346 while ((fae = STAILQ_FIRST(&(*fa)->fa_list)) != NULL) { | |
347 /* Remove file action entry from the queue */ | |
348 STAILQ_REMOVE_HEAD(&(*fa)->fa_list, fae_list); | |
349 | |
350 /* Deallocate file action entry */ | |
351 if (fae->fae_action == FAE_OPEN) | |
352 free(fae->fae_path); | |
353 free(fae); | |
354 } | |
355 | |
356 free(*fa); | |
357 return (0); | |
358 } | |
359 | |
360 int | |
361 _DEFUN(posix_spawn_file_actions_addopen, (fa, fildes, path, oflag, mode), | |
362 posix_spawn_file_actions_t * __restrict fa _AND | |
363 int fildes _AND | |
364 _CONST char * __restrict path _AND | |
365 int oflag _AND | |
366 mode_t mode) | |
367 { | |
368 posix_spawn_file_actions_entry_t *fae; | |
369 int error; | |
370 | |
371 if (fildes < 0) | |
372 return (EBADF); | |
373 | |
374 /* Allocate object */ | |
375 fae = malloc(sizeof(posix_spawn_file_actions_entry_t)); | |
376 if (fae == NULL) | |
377 return (errno); | |
378 | |
379 /* Set values and store in queue */ | |
380 fae->fae_action = FAE_OPEN; | |
381 fae->fae_path = strdup(path); | |
382 if (fae->fae_path == NULL) { | |
383 error = errno; | |
384 free(fae); | |
385 return (error); | |
386 } | |
387 fae->fae_fildes = fildes; | |
388 fae->fae_oflag = oflag; | |
389 fae->fae_mode = mode; | |
390 | |
391 STAILQ_INSERT_TAIL(&(*fa)->fa_list, fae, fae_list); | |
392 return (0); | |
393 } | |
394 | |
395 int | |
396 _DEFUN(posix_spawn_file_actions_adddup2, (fa, fildes, newfildes), | |
397 posix_spawn_file_actions_t *fa _AND | |
398 int fildes _AND | |
399 int newfildes) | |
400 { | |
401 posix_spawn_file_actions_entry_t *fae; | |
402 | |
403 if (fildes < 0 || newfildes < 0) | |
404 return (EBADF); | |
405 | |
406 /* Allocate object */ | |
407 fae = malloc(sizeof(posix_spawn_file_actions_entry_t)); | |
408 if (fae == NULL) | |
409 return (errno); | |
410 | |
411 /* Set values and store in queue */ | |
412 fae->fae_action = FAE_DUP2; | |
413 fae->fae_fildes = fildes; | |
414 fae->fae_newfildes = newfildes; | |
415 | |
416 STAILQ_INSERT_TAIL(&(*fa)->fa_list, fae, fae_list); | |
417 return (0); | |
418 } | |
419 | |
420 int | |
421 _DEFUN(posix_spawn_file_actions_addclose, (fa, fildes), | |
422 posix_spawn_file_actions_t *fa _AND | |
423 int fildes) | |
424 { | |
425 posix_spawn_file_actions_entry_t *fae; | |
426 | |
427 if (fildes < 0) | |
428 return (EBADF); | |
429 | |
430 /* Allocate object */ | |
431 fae = malloc(sizeof(posix_spawn_file_actions_entry_t)); | |
432 if (fae == NULL) | |
433 return (errno); | |
434 | |
435 /* Set values and store in queue */ | |
436 fae->fae_action = FAE_CLOSE; | |
437 fae->fae_fildes = fildes; | |
438 | |
439 STAILQ_INSERT_TAIL(&(*fa)->fa_list, fae, fae_list); | |
440 return (0); | |
441 } | |
442 | |
443 /* | |
444 * Spawn attributes | |
445 */ | |
446 | |
447 int | |
448 _DEFUN(posix_spawnattr_init, (ret), | |
449 posix_spawnattr_t *ret) | |
450 { | |
451 posix_spawnattr_t sa; | |
452 | |
453 sa = calloc(1, sizeof(struct __posix_spawnattr)); | |
454 if (sa == NULL) | |
455 return (errno); | |
456 | |
457 /* Set defaults as specified by POSIX, cleared above */ | |
458 *ret = sa; | |
459 return (0); | |
460 } | |
461 | |
462 int | |
463 _DEFUN(posix_spawnattr_destroy, (sa), | |
464 posix_spawnattr_t *sa) | |
465 { | |
466 free(*sa); | |
467 return (0); | |
468 } | |
469 | |
470 int | |
471 _DEFUN(posix_spawnattr_getflags, (sa, flags), | |
472 _CONST posix_spawnattr_t * __restrict sa _AND | |
473 short * __restrict flags) | |
474 { | |
475 *flags = (*sa)->sa_flags; | |
476 return (0); | |
477 } | |
478 | |
479 int | |
480 _DEFUN(posix_spawnattr_getpgroup, (sa, pgroup), | |
481 _CONST posix_spawnattr_t * __restrict sa _AND | |
482 pid_t * __restrict pgroup) | |
483 { | |
484 *pgroup = (*sa)->sa_pgroup; | |
485 return (0); | |
486 } | |
487 | |
488 int | |
489 _DEFUN(posix_spawnattr_getschedparam, (sa, schedparam), | |
490 _CONST posix_spawnattr_t * __restrict sa _AND | |
491 struct sched_param * __restrict schedparam) | |
492 { | |
493 *schedparam = (*sa)->sa_schedparam; | |
494 return (0); | |
495 } | |
496 | |
497 int | |
498 _DEFUN(posix_spawnattr_getschedpolicy, (sa, schedpolicy), | |
499 _CONST posix_spawnattr_t * __restrict sa _AND | |
500 int * __restrict schedpolicy) | |
501 { | |
502 *schedpolicy = (*sa)->sa_schedpolicy; | |
503 return (0); | |
504 } | |
505 | |
506 int | |
507 _DEFUN(posix_spawnattr_getsigdefault, (sa, sigdefault), | |
508 _CONST posix_spawnattr_t * __restrict sa _AND | |
509 sigset_t * __restrict sigdefault) | |
510 { | |
511 *sigdefault = (*sa)->sa_sigdefault; | |
512 return (0); | |
513 } | |
514 | |
515 int | |
516 _DEFUN(posix_spawnattr_getsigmask, (sa, sigmask), | |
517 _CONST posix_spawnattr_t * __restrict sa _AND | |
518 sigset_t * __restrict sigmask) | |
519 { | |
520 *sigmask = (*sa)->sa_sigmask; | |
521 return (0); | |
522 } | |
523 | |
524 int | |
525 _DEFUN(posix_spawnattr_setflags, (sa, flags), | |
526 posix_spawnattr_t *sa _AND | |
527 short flags) | |
528 { | |
529 (*sa)->sa_flags = flags; | |
530 return (0); | |
531 } | |
532 | |
533 int | |
534 _DEFUN(posix_spawnattr_setpgroup, (sa, pgroup), | |
535 posix_spawnattr_t *sa _AND | |
536 pid_t pgroup) | |
537 { | |
538 (*sa)->sa_pgroup = pgroup; | |
539 return (0); | |
540 } | |
541 | |
542 int | |
543 _DEFUN(posix_spawnattr_setschedparam, (sa, schedparam), | |
544 posix_spawnattr_t * __restrict sa _AND | |
545 _CONST struct sched_param * __restrict schedparam) | |
546 { | |
547 (*sa)->sa_schedparam = *schedparam; | |
548 return (0); | |
549 } | |
550 | |
551 int | |
552 _DEFUN(posix_spawnattr_setschedpolicy, (sa, schedpolicy), | |
553 posix_spawnattr_t *sa _AND | |
554 int schedpolicy) | |
555 { | |
556 (*sa)->sa_schedpolicy = schedpolicy; | |
557 return (0); | |
558 } | |
559 | |
560 int | |
561 _DEFUN(posix_spawnattr_setsigdefault, (sa, sigdefault), | |
562 posix_spawnattr_t * __restrict sa _AND | |
563 _CONST sigset_t * __restrict sigdefault) | |
564 { | |
565 (*sa)->sa_sigdefault = *sigdefault; | |
566 return (0); | |
567 } | |
568 | |
569 int | |
570 _DEFUN(posix_spawnattr_setsigmask, (sa, sigmask), | |
571 posix_spawnattr_t * __restrict sa _AND | |
572 _CONST sigset_t * __restrict sigmask) | |
573 { | |
574 (*sa)->sa_sigmask = *sigmask; | |
575 return (0); | |
576 } | |
577 | |
578 #endif /* !_NO_POSIX_SPAWN */ | 285 #endif /* !_NO_POSIX_SPAWN */ |
OLD | NEW |