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