1 /*********************************************************************** 2 * * 3 * This software is part of the ast package * 4 * Copyright (c) 1985-2008 AT&T Intellectual Property * 5 * and is licensed under the * 6 * Common Public License, Version 1.0 * 7 * by AT&T Intellectual Property * 8 * * 9 * A copy of the License is available at * 10 * http://www.opensource.org/licenses/cpl1.0.txt * 11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 12 * * 13 * Information and Software Systems Research * 14 * AT&T Research * 15 * Florham Park NJ * 16 * * 17 * Glenn Fowler <gsf@research.att.com> * 18 * David Korn <dgk@research.att.com> * 19 * Phong Vo <kpv@research.att.com> * 20 * * 21 ***********************************************************************/ 22 #pragma prototyped 23 /* 24 * Glenn Fowler 25 * AT&T Research 26 * 27 * common process execution support with 28 * proper sfio, signal and wait() syncronization 29 * 30 * _ contains the process path name and is 31 * placed at the top of the environment 32 */ 33 34 #include "proclib.h" 35 36 #include <ls.h> 37 38 /* 39 * not quite ready for _use_spawnveg 40 */ 41 42 #if _use_spawnveg && _lib_fork 43 #undef _use_spawnveg 44 #endif 45 46 #ifndef DEBUG_PROC 47 #define DEBUG_PROC 1 48 #endif 49 50 #if _lib_socketpair 51 #if _sys_socket 52 #include <sys/types.h> 53 #include <sys/socket.h> 54 #else 55 #undef _lib_socketpair 56 #endif 57 #endif 58 59 Proc_t proc_default = { -1 }; 60 61 #if DEBUG_PROC 62 63 #include <namval.h> 64 65 #define PROC_ENV_OPTIONS "PROC_OPTIONS" 66 67 #define PROC_OPT_ENVIRONMENT (1<<0) 68 #define PROC_OPT_EXEC (1<<1) 69 #define PROC_OPT_TRACE (1<<2) 70 #define PROC_OPT_VERBOSE (1<<3) 71 72 static const Namval_t options[] = 73 { 74 "debug", PROC_OPT_VERBOSE, 75 "environment", PROC_OPT_ENVIRONMENT, 76 "exec", PROC_OPT_EXEC, 77 "trace", PROC_OPT_TRACE, 78 "verbose", PROC_OPT_VERBOSE, 79 0, 0 80 }; 81 82 /* 83 * called by stropt() to set options 84 */ 85 86 static int 87 setopt(register void* a, register const void* p, register int n, const char* v) 88 { 89 NoP(v); 90 if (p) 91 { 92 if (n) 93 *((int*)a) |= ((Namval_t*)p)->value; 94 else 95 *((int*)a) &= ~((Namval_t*)p)->value; 96 } 97 return 0; 98 } 99 100 #endif 101 102 #if _use_spawnveg 103 104 typedef struct Fd_s 105 { 106 short fd; 107 short flag; 108 } Fd_t; 109 110 typedef struct Mod_s 111 { 112 struct Mod_s* next; 113 short op; 114 short save; 115 116 union 117 { 118 119 struct 120 { 121 Fd_t parent; 122 Fd_t child; 123 } fd; 124 125 Handler_t handler; 126 127 } arg; 128 129 } Modify_t; 130 131 #endif 132 133 #ifdef SIGPIPE 134 135 /* 136 * catch but ignore sig 137 * avoids SIG_IGN being passed to children 138 */ 139 140 static void 141 ignoresig(int sig) 142 { 143 signal(sig, ignoresig); 144 } 145 146 #endif 147 148 /* 149 * do modification op and save previous state for restore() 150 */ 151 152 static int 153 modify(Proc_t* proc, int forked, int op, long arg1, long arg2) 154 { 155 #if _lib_fork 156 if (forked) 157 { 158 switch (op) 159 { 160 case PROC_fd_dup: 161 case PROC_fd_dup|PROC_FD_PARENT: 162 case PROC_fd_dup|PROC_FD_CHILD: 163 case PROC_fd_dup|PROC_FD_PARENT|PROC_FD_CHILD: 164 if (arg1 != arg2) 165 { 166 if (arg2 != PROC_ARG_NULL) 167 { 168 close(arg2); 169 if (fcntl(arg1, F_DUPFD, arg2) != arg2) 170 return -1; 171 } 172 if (op & PROC_FD_CHILD) 173 close(arg1); 174 } 175 break; 176 case PROC_sig_dfl: 177 signal(arg1, SIG_DFL); 178 break; 179 case PROC_sig_ign: 180 signal(arg1, SIG_IGN); 181 break; 182 case PROC_sys_pgrp: 183 if (arg1 < 0) 184 setsid(); 185 else if (arg1 > 0) 186 { 187 if (arg1 == 1) 188 arg1 = 0; 189 if (setpgid(0, arg1) < 0 && arg1 && errno == EPERM) 190 setpgid(0, 0); 191 } 192 break; 193 case PROC_sys_umask: 194 umask(arg1); 195 break; 196 default: 197 return -1; 198 } 199 } 200 #if _use_spawnveg 201 else 202 #endif 203 #else 204 NoP(forked); 205 #endif 206 #if _use_spawnveg 207 { 208 register Modify_t* m; 209 210 if (!(m = newof(NiL, Modify_t, 1, 0))) 211 return -1; 212 m->next = proc->mods; 213 proc->mods = m; 214 switch (m->op = op) 215 { 216 case PROC_fd_dup: 217 case PROC_fd_dup|PROC_FD_PARENT: 218 case PROC_fd_dup|PROC_FD_CHILD: 219 case PROC_fd_dup|PROC_FD_PARENT|PROC_FD_CHILD: 220 m->arg.fd.parent.fd = (short)arg1; 221 m->arg.fd.parent.flag = fcntl(arg1, F_GETFD, 0); 222 if ((m->arg.fd.child.fd = (short)arg2) != arg1) 223 { 224 if (arg2 != PROC_ARG_NULL) 225 { 226 m->arg.fd.child.flag = fcntl(arg2, F_GETFD, 0); 227 if ((m->save = fcntl(arg2, F_DUPFD, 3)) < 0) 228 { 229 m->op = 0; 230 return -1; 231 } 232 fcntl(m->save, F_SETFD, FD_CLOEXEC); 233 close(arg2); 234 if (fcntl(arg1, F_DUPFD, arg2) != arg2) 235 return -1; 236 if (op & PROC_FD_CHILD) 237 close(arg1); 238 } 239 else if (op & PROC_FD_CHILD) 240 { 241 if (m->arg.fd.parent.flag) 242 break; 243 fcntl(arg1, F_SETFD, FD_CLOEXEC); 244 } 245 else if (!m->arg.fd.parent.flag) 246 break; 247 else 248 fcntl(arg1, F_SETFD, 0); 249 return 0; 250 } 251 break; 252 case PROC_sig_dfl: 253 if ((m->arg.handler = signal(arg1, SIG_DFL)) == SIG_DFL) 254 break; 255 m->save = (short)arg1; 256 return 0; 257 case PROC_sig_ign: 258 if ((m->arg.handler = signal(arg1, SIG_IGN)) == SIG_IGN) 259 break; 260 m->save = (short)arg1; 261 return 0; 262 case PROC_sys_pgrp: 263 proc->pgrp = arg1; 264 break; 265 case PROC_sys_umask: 266 if ((m->save = (short)umask(arg1)) == arg1) 267 break; 268 return 0; 269 default: 270 proc->mods = m->next; 271 free(m); 272 return -1; 273 } 274 proc->mods = m->next; 275 free(m); 276 } 277 #else 278 NoP(proc); 279 #endif 280 return 0; 281 } 282 283 #if _use_spawnveg 284 285 /* 286 * restore modifications 287 */ 288 289 static void 290 restore(Proc_t* proc) 291 { 292 register Modify_t* m; 293 register Modify_t* p; 294 int oerrno; 295 296 NoP(proc); 297 oerrno = errno; 298 m = proc->mods; 299 proc->mods = 0; 300 while (m) 301 { 302 switch (m->op) 303 { 304 case PROC_fd_dup: 305 case PROC_fd_dup|PROC_FD_PARENT: 306 case PROC_fd_dup|PROC_FD_CHILD: 307 case PROC_fd_dup|PROC_FD_PARENT|PROC_FD_CHILD: 308 if (m->op & PROC_FD_PARENT) 309 close(m->arg.fd.parent.fd); 310 if (m->arg.fd.child.fd != m->arg.fd.parent.fd && m->arg.fd.child.fd != PROC_ARG_NULL) 311 { 312 if (!(m->op & PROC_FD_PARENT)) 313 { 314 if (m->op & PROC_FD_CHILD) 315 { 316 close(m->arg.fd.parent.fd); 317 fcntl(m->arg.fd.child.fd, F_DUPFD, m->arg.fd.parent.fd); 318 } 319 fcntl(m->arg.fd.parent.fd, F_SETFD, m->arg.fd.parent.flag); 320 } 321 close(m->arg.fd.child.fd); 322 fcntl(m->save, F_DUPFD, m->arg.fd.child.fd); 323 close(m->save); 324 if (m->arg.fd.child.flag) 325 fcntl(m->arg.fd.child.fd, F_SETFD, FD_CLOEXEC); 326 } 327 else if ((m->op & (PROC_FD_PARENT|PROC_FD_CHILD)) == PROC_FD_CHILD) 328 fcntl(m->arg.fd.parent.fd, F_SETFD, 0); 329 break; 330 case PROC_sig_dfl: 331 case PROC_sig_ign: 332 signal(m->save, m->arg.handler); 333 break; 334 case PROC_sys_umask: 335 umask(m->save); 336 break; 337 } 338 p = m; 339 m = m->next; 340 free(p); 341 } 342 errno = oerrno; 343 } 344 345 #else 346 347 #define restore(p) 348 349 #endif 350 351 /* 352 * fork and exec or spawn proc(argv) and return a Proc_t handle 353 * 354 * pipe not used when PROC_READ|PROC_WRITE omitted 355 * argv==0 duplicates current process if possible 356 * cmd==0 names the current shell 357 * cmd=="" does error cleanup 358 * envv is the child environment 359 * modv is the child modification vector of PROC_*() ops 360 */ 361 362 Proc_t* 363 procopen(const char* cmd, char** argv, char** envv, long* modv, int flags) 364 { 365 register Proc_t* proc = 0; 366 register int procfd; 367 register char** p; 368 char** v; 369 int i; 370 int forked = 0; 371 int signalled = 0; 372 long n; 373 char path[PATH_MAX]; 374 char env[PATH_MAX + 2]; 375 int pio[2]; 376 #if !_pipe_rw && !_lib_socketpair 377 int poi[2]; 378 #endif 379 #if defined(SIGCHLD) && ( _lib_sigprocmask || _lib_sigsetmask ) 380 Sig_mask_t mask; 381 #endif 382 #if _use_spawnveg 383 int newenv = 0; 384 #endif 385 #if DEBUG_PROC 386 int debug = PROC_OPT_EXEC; 387 #endif 388 389 #if _lib_fork 390 if (!argv && (flags & PROC_OVERLAY)) 391 #else 392 if (!argv) 393 #endif 394 { 395 errno = ENOEXEC; 396 return 0; 397 } 398 pio[0] = pio[1] = -1; 399 #if !_pipe_rw && !_lib_socketpair 400 poi[0] = poi[1] = -1; 401 #endif 402 if (cmd && (!*cmd || !pathpath(path, cmd, NiL, PATH_REGULAR|PATH_EXECUTE))) 403 goto bad; 404 switch (flags & (PROC_READ|PROC_WRITE)) 405 { 406 case 0: 407 procfd = -1; 408 break; 409 case PROC_READ: 410 procfd = 1; 411 break; 412 case PROC_WRITE: 413 procfd = 0; 414 break; 415 case PROC_READ|PROC_WRITE: 416 procfd = 2; 417 break; 418 } 419 if (proc_default.pid == -1) 420 proc = &proc_default; 421 else if (!(proc = newof(0, Proc_t, 1, 0))) 422 goto bad; 423 proc->pid = -1; 424 proc->pgrp = 0; 425 proc->rfd = -1; 426 proc->wfd = -1; 427 proc->flags = flags; 428 sfsync(NiL); 429 if (environ && envv != (char**)environ && (envv || (flags & PROC_PARANOID) || argv && (environ[0][0] != '_' || environ[0][1] != '='))) 430 { 431 if (!setenviron(NiL)) 432 goto bad; 433 #if _use_spawnveg 434 newenv = 1; 435 #endif 436 } 437 if (procfd >= 0) 438 { 439 #if _pipe_rw 440 if (pipe(pio)) 441 goto bad; 442 #else 443 if (procfd > 1) 444 { 445 #if _lib_socketpair 446 if (socketpair(AF_UNIX, SOCK_STREAM, 0, pio)) 447 goto bad; 448 #else 449 if (pipe(pio) || pipe(poi)) 450 goto bad; 451 #endif 452 } 453 else if (pipe(pio)) 454 goto bad; 455 #endif 456 } 457 if (flags & PROC_OVERLAY) 458 { 459 proc->pid = 0; 460 forked = 1; 461 } 462 #if _use_spawnveg 463 else if (argv) 464 proc->pid = 0; 465 #endif 466 #if _lib_fork 467 else 468 { 469 if (!(flags & PROC_FOREGROUND)) 470 sigcritical(SIG_REG_EXEC|SIG_REG_PROC); 471 else 472 { 473 signalled = 1; 474 proc->sigint = signal(SIGINT, SIG_IGN); 475 proc->sigquit = signal(SIGQUIT, SIG_IGN); 476 #if defined(SIGCHLD) 477 #if _lib_sigprocmask 478 sigemptyset(&mask); 479 sigaddset(&mask, SIGCHLD); 480 sigprocmask(SIG_BLOCK, &mask, &proc->mask); 481 #else 482 #if _lib_sigsetmask 483 mask = sigmask(SIGCHLD); 484 proc->mask = sigblock(mask); 485 #else 486 proc->sigchld = signal(SIGCHLD, SIG_DFL); 487 #endif 488 #endif 489 #endif 490 } 491 proc->pid = fork(); 492 if (!(flags & PROC_FOREGROUND)) 493 sigcritical(0); 494 else if (!proc->pid) 495 { 496 if (proc->sigint != SIG_IGN) 497 { 498 proc->sigint = SIG_DFL; 499 signal(SIGINT, proc->sigint); 500 } 501 if (proc->sigquit != SIG_IGN) 502 { 503 proc->sigquit = SIG_DFL; 504 signal(SIGQUIT, proc->sigquit); 505 } 506 #if defined(SIGCHLD) 507 #if _lib_sigprocmask 508 sigprocmask(SIG_SETMASK, &proc->mask, NiL); 509 #else 510 #if _lib_sigsetmask 511 sigsetmask(proc->mask); 512 #else 513 if (proc->sigchld != SIG_IGN) 514 signal(SIGCHLD, SIG_DFL); 515 #endif 516 #endif 517 #endif 518 } 519 else if (proc->pid == -1) 520 goto bad; 521 forked = 1; 522 } 523 #endif 524 if (!proc->pid) 525 { 526 #if _use_spawnveg 527 char** oenviron = 0; 528 char* oenviron0 = 0; 529 530 v = 0; 531 #endif 532 #if DEBUG_PROC 533 stropt(getenv(PROC_ENV_OPTIONS), options, sizeof(*options), setopt, &debug); 534 #if _lib_fork 535 if (debug & PROC_OPT_TRACE) 536 { 537 if (!fork()) 538 { 539 sfsprintf(path, sizeof(path), "%d", getppid()); 540 execlp("trace", "trace", "-p", path, NiL); 541 _exit(EXIT_NOTFOUND); 542 } 543 sleep(2); 544 } 545 #endif 546 #endif 547 if (flags & PROC_DAEMON) 548 { 549 #ifdef SIGHUP 550 modify(proc, forked, PROC_sig_ign, SIGHUP, 0); 551 #endif 552 modify(proc, forked, PROC_sig_dfl, SIGTERM, 0); 553 #ifdef SIGTSTP 554 modify(proc, forked, PROC_sig_ign, SIGTSTP, 0); 555 #endif 556 #ifdef SIGTTIN 557 modify(proc, forked, PROC_sig_ign, SIGTTIN, 0); 558 #endif 559 #ifdef SIGTTOU 560 modify(proc, forked, PROC_sig_ign, SIGTTOU, 0); 561 #endif 562 } 563 if (flags & (PROC_BACKGROUND|PROC_DAEMON)) 564 { 565 modify(proc, forked, PROC_sig_ign, SIGINT, 0); 566 #ifdef SIGQUIT 567 modify(proc, forked, PROC_sig_ign, SIGQUIT, 0); 568 #endif 569 } 570 if (flags & (PROC_DAEMON|PROC_SESSION)) 571 modify(proc, forked, PROC_sys_pgrp, -1, 0); 572 if (forked || (flags & PROC_OVERLAY)) 573 { 574 if ((flags & PROC_PRIVELEGED) && !geteuid()) 575 { 576 setuid(geteuid()); 577 setgid(getegid()); 578 } 579 if (flags & (PROC_PARANOID|PROC_GID)) 580 setgid(getgid()); 581 if (flags & (PROC_PARANOID|PROC_UID)) 582 setuid(getuid()); 583 } 584 if (procfd > 1) 585 { 586 if (modify(proc, forked, PROC_fd_dup|PROC_FD_CHILD, pio[0], PROC_ARG_NULL)) 587 goto cleanup; 588 if (modify(proc, forked, PROC_fd_dup|PROC_FD_CHILD, pio[1], 1)) 589 goto cleanup; 590 #if _pipe_rw || _lib_socketpair 591 if (modify(proc, forked, PROC_fd_dup, 1, 0)) 592 goto cleanup; 593 #else 594 if (modify(proc, forked, PROC_fd_dup|PROC_FD_CHILD, poi[0], 0)) 595 goto cleanup; 596 if (poi[1] != 0 && modify(proc, forked, PROC_fd_dup|PROC_FD_CHILD, poi[1], PROC_ARG_NULL)) 597 goto cleanup; 598 #endif 599 } 600 else if (procfd >= 0) 601 { 602 if (modify(proc, forked, PROC_fd_dup|PROC_FD_CHILD, pio[!!procfd], !!procfd)) 603 goto cleanup; 604 if (pio[!procfd] != !!procfd && modify(proc, forked, PROC_fd_dup|PROC_FD_CHILD, pio[!procfd], PROC_ARG_NULL)) 605 goto cleanup; 606 } 607 if (modv) 608 for (i = 0; n = modv[i]; i++) 609 switch (PROC_OP(n)) 610 { 611 case PROC_fd_dup: 612 case PROC_fd_dup|PROC_FD_PARENT: 613 case PROC_fd_dup|PROC_FD_CHILD: 614 case PROC_fd_dup|PROC_FD_PARENT|PROC_FD_CHILD: 615 if (modify(proc, forked, PROC_OP(n), PROC_ARG(n, 1), PROC_ARG(n, 2))) 616 goto cleanup; 617 break; 618 default: 619 if (modify(proc, forked, PROC_OP(n), PROC_ARG(n, 1), 0)) 620 goto cleanup; 621 break; 622 } 623 #if _lib_fork 624 if (forked && (flags & PROC_ENVCLEAR)) 625 environ = 0; 626 #if _use_spawnveg 627 else 628 #endif 629 #endif 630 #if _use_spawnveg 631 if (newenv) 632 { 633 p = environ; 634 while (*p++); 635 if (!(oenviron = (char**)memdup(environ, (p - environ) * sizeof(char*)))) 636 goto cleanup; 637 } 638 #endif 639 if (argv && envv != (char**)environ) 640 { 641 #if _use_spawnveg 642 if (!newenv && environ[0][0] == '_' && environ[0][1] == '=') 643 oenviron0 = environ[0]; 644 #endif 645 env[0] = '_'; 646 env[1] = '='; 647 env[2] = 0; 648 if (!setenviron(env)) 649 goto cleanup; 650 } 651 if ((flags & PROC_PARANOID) && setenv("PATH", astconf("PATH", NiL, NiL), 1)) 652 goto cleanup; 653 if ((p = envv) && p != (char**)environ) 654 while (*p) 655 if (!setenviron(*p++)) 656 goto cleanup; 657 p = argv; 658 #if _lib_fork 659 if (forked && !p) 660 return proc; 661 #endif 662 #if DEBUG_PROC 663 if (!(debug & PROC_OPT_EXEC) || (debug & PROC_OPT_VERBOSE)) 664 { 665 if ((debug & PROC_OPT_ENVIRONMENT) && (p = environ)) 666 while (*p) 667 sfprintf(sfstderr, "%s\n", *p++); 668 sfprintf(sfstderr, "+ %s", cmd ? path : "sh"); 669 if ((p = argv) && *p) 670 while (*++p) 671 sfprintf(sfstderr, " %s", *p); 672 sfprintf(sfstderr, "\n"); 673 sfsync(sfstderr); 674 if (!(debug & PROC_OPT_EXEC)) 675 _exit(0); 676 p = argv; 677 } 678 #endif 679 if (cmd) 680 { 681 strcpy(env + 2, path); 682 if (forked || (flags & PROC_OVERLAY)) 683 execve(path, p, environ); 684 #if _use_spawnveg 685 else if ((proc->pid = spawnveg(path, p, environ, proc->pgrp)) != -1) 686 goto cleanup; 687 #endif 688 if (errno != ENOEXEC) 689 goto cleanup; 690 691 /* 692 * try cmd as a shell script 693 */ 694 695 if (!(flags & PROC_ARGMOD)) 696 { 697 while (*p++); 698 if (!(v = newof(0, char*, p - argv + 2, 0))) 699 goto cleanup; 700 p = v + 2; 701 if (*argv) 702 argv++; 703 while (*p++ = *argv++); 704 p = v + 1; 705 } 706 *p = path; 707 *--p = "sh"; 708 } 709 strcpy(env + 2, (flags & PROC_PARANOID) ? astconf("SH", NiL, NiL) : pathshell()); 710 if (forked || (flags & PROC_OVERLAY)) 711 execve(env + 2, p, environ); 712 #if _use_spawnveg 713 else 714 proc->pid = spawnveg(env + 2, p, environ, proc->pgrp); 715 #endif 716 cleanup: 717 if (forked) 718 { 719 if (!(flags & PROC_OVERLAY)) 720 _exit(errno == ENOENT ? EXIT_NOTFOUND : EXIT_NOEXEC); 721 goto bad; 722 } 723 #if _use_spawnveg 724 if (v) 725 free(v); 726 if (p = oenviron) 727 { 728 environ = 0; 729 while (*p) 730 if (!setenviron(*p++)) 731 goto bad; 732 free(oenviron); 733 } 734 else if (oenviron0) 735 environ[0] = oenviron0; 736 restore(proc); 737 if (flags & PROC_OVERLAY) 738 exit(0); 739 #endif 740 } 741 if (proc->pid != -1) 742 { 743 if (!forked) 744 { 745 if (flags & PROC_FOREGROUND) 746 { 747 signalled = 1; 748 proc->sigint = signal(SIGINT, SIG_IGN); 749 proc->sigquit = signal(SIGQUIT, SIG_IGN); 750 #if defined(SIGCHLD) 751 #if _lib_sigprocmask 752 sigemptyset(&mask); 753 sigaddset(&mask, SIGCHLD); 754 sigprocmask(SIG_BLOCK, &mask, &proc->mask); 755 #else 756 #if _lib_sigsetmask 757 mask = sigmask(SIGCHLD); 758 proc->mask = sigblock(mask); 759 #else 760 proc->sigchld = signal(SIGCHLD, SIG_DFL); 761 #endif 762 #endif 763 #endif 764 } 765 } 766 else if (modv) 767 for (i = 0; n = modv[i]; i++) 768 switch (PROC_OP(n)) 769 { 770 case PROC_fd_dup|PROC_FD_PARENT: 771 case PROC_fd_dup|PROC_FD_PARENT|PROC_FD_CHILD: 772 close(PROC_ARG(n, 1)); 773 break; 774 case PROC_sys_pgrp: 775 if (proc->pgrp < 0) 776 proc->pgrp = proc->pid; 777 else if (proc->pgrp > 0) 778 { 779 if (proc->pgrp == 1) 780 proc->pgrp = proc->pid; 781 if (setpgid(proc->pid, proc->pgrp) < 0 && proc->pid != proc->pgrp && errno == EPERM) 782 setpgid(proc->pid, proc->pid); 783 } 784 break; 785 } 786 if (procfd >= 0) 787 { 788 #ifdef SIGPIPE 789 if ((flags & (PROC_WRITE|PROC_IGNORE)) == (PROC_WRITE|PROC_IGNORE)) 790 { 791 Handler_t handler; 792 793 if ((handler = signal(SIGPIPE, ignoresig)) != SIG_DFL && handler != ignoresig) 794 signal(SIGPIPE, handler); 795 } 796 #endif 797 switch (procfd) 798 { 799 case 0: 800 proc->wfd = pio[1]; 801 close(pio[0]); 802 break; 803 default: 804 #if _pipe_rw || _lib_socketpair 805 proc->wfd = pio[0]; 806 #else 807 proc->wfd = poi[1]; 808 close(poi[0]); 809 #endif 810 /*FALLTHROUGH*/ 811 case 1: 812 proc->rfd = pio[0]; 813 close(pio[1]); 814 break; 815 } 816 if (proc->rfd > 2) 817 fcntl(proc->rfd, F_SETFD, FD_CLOEXEC); 818 if (proc->wfd > 2) 819 fcntl(proc->wfd, F_SETFD, FD_CLOEXEC); 820 } 821 if (!proc->pid) 822 proc->pid = getpid(); 823 return proc; 824 } 825 bad: 826 if (signalled) 827 { 828 if (proc->sigint != SIG_IGN) 829 signal(SIGINT, proc->sigint); 830 if (proc->sigquit != SIG_IGN) 831 signal(SIGQUIT, proc->sigquit); 832 #if defined(SIGCHLD) 833 #if _lib_sigprocmask 834 sigprocmask(SIG_SETMASK, &proc->mask, NiL); 835 #else 836 #if _lib_sigsetmask 837 sigsetmask(proc->mask); 838 #else 839 if (proc->sigchld != SIG_DFL) 840 signal(SIGCHLD, proc->sigchld); 841 #endif 842 #endif 843 #endif 844 } 845 if ((flags & PROC_CLEANUP) && modv) 846 for (i = 0; n = modv[i]; i++) 847 switch (PROC_OP(n)) 848 { 849 case PROC_fd_dup: 850 case PROC_fd_dup|PROC_FD_PARENT: 851 case PROC_fd_dup|PROC_FD_CHILD: 852 case PROC_fd_dup|PROC_FD_PARENT|PROC_FD_CHILD: 853 if (PROC_ARG(n, 2) != PROC_ARG_NULL) 854 close(PROC_ARG(n, 1)); 855 break; 856 } 857 if (pio[0] >= 0) 858 close(pio[0]); 859 if (pio[1] >= 0) 860 close(pio[1]); 861 #if !_pipe_rw && !_lib_socketpair 862 if (poi[0] >= 0) 863 close(poi[0]); 864 if (poi[1] >= 0) 865 close(poi[1]); 866 #endif 867 procfree(proc); 868 return 0; 869 } 870