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