1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28 /* All Rights Reserved */ 29 30 #include <stdio.h> 31 #include <stdlib.h> 32 #include <nl_types.h> 33 #include <locale.h> 34 #include <signal.h> 35 #include <string.h> 36 #include <limits.h> 37 #include <errno.h> 38 #include <unistd.h> 39 #include <sys/types.h> 40 #include <sys/stat.h> 41 #include <libproc.h> 42 #include <dirent.h> 43 #include <ctype.h> 44 #include <sys/time.h> 45 46 #define NOHUP_PERM (S_IRUSR | S_IWUSR) 47 48 #define NOHUP_NOEXEC 126 49 #define NOHUP_ERROR 127 50 51 #ifdef XPG4 52 #define OPTSTR "" 53 #else 54 #define OPTSTR "pFag" 55 56 static int pnohup(int, char **); 57 58 static struct ps_prochandle *g_proc; 59 static int g_wrfd; 60 static int g_rdfd; 61 62 static int g_dirty; 63 static volatile int g_interrupt = 0; 64 #endif 65 66 static int opt_p = 0; 67 static int opt_g = 0; 68 static int opt_a = 0; 69 static int opt_F = 0; 70 71 static char *pname; 72 73 static char nout[PATH_MAX] = "nohup.out"; 74 75 static int 76 open_file(void) 77 { 78 char *home; 79 int fd; 80 int flags = O_CREAT | O_WRONLY | O_APPEND; 81 82 if ((fd = open(nout, flags, NOHUP_PERM)) < 0) { 83 if ((home = getenv("HOME")) == NULL) 84 return (-1); 85 86 if ((snprintf(nout, sizeof (nout), 87 "%s/nohup.out", home) >= sizeof (nout)) || 88 (fd = open(nout, flags, NOHUP_PERM)) < 0) { 89 return (-1); 90 } 91 92 } 93 94 (void) fprintf(stderr, gettext("Sending output to %s\n"), nout); 95 96 return (fd); 97 } 98 99 int 100 main(int argc, char **argv) 101 { 102 int fd = -1; 103 int opt; 104 int err; 105 106 if ((pname = strrchr(argv[0], '/')) == NULL) 107 pname = argv[0]; 108 else 109 argv[0] = ++pname; /* for getopt */ 110 111 (void) setlocale(LC_ALL, ""); 112 113 #ifndef TEXT_DOMAIN 114 #define TEXT_DOMAIN "SYS_TEST" 115 #endif 116 117 (void) textdomain(TEXT_DOMAIN); 118 119 while ((opt = getopt(argc, argv, OPTSTR)) != EOF) { 120 switch (opt) { 121 case 'p': 122 opt_p = 1; 123 break; 124 case 'F': 125 opt_F = 1; 126 break; 127 case 'a': 128 opt_a = 1; 129 break; 130 case 'g': 131 opt_g = 1; 132 break; 133 default: 134 goto usage; 135 } 136 } 137 138 argc -= optind; 139 argv += optind; 140 141 if (argc == 0) 142 goto usage; /* need at least one argument */ 143 144 #ifndef XPG4 145 if (opt_p && opt_g) 146 goto usage; 147 148 if (opt_p || opt_g) 149 return (pnohup(argc, argv)); 150 151 if (opt_a || opt_F) 152 goto usage; /* only valid with -p or -g */ 153 #endif 154 155 argv[argc] = NULL; 156 157 (void) signal(SIGHUP, SIG_IGN); /* POSIX.2 only SIGHUP */ 158 #ifndef XPG4 159 (void) signal(SIGQUIT, SIG_IGN); /* Solaris compatibility */ 160 #endif 161 162 if (isatty(STDOUT_FILENO)) { 163 if ((fd = open_file()) < 0) 164 goto err; 165 166 (void) dup2(fd, STDOUT_FILENO); 167 } 168 169 if (isatty(STDERR_FILENO)) { 170 if (fd < 0 && (fd = open_file()) < 0) 171 goto err; 172 173 (void) dup2(fd, STDERR_FILENO); 174 } 175 176 if (fd >= 0) 177 (void) close(fd); 178 179 (void) execvp(argv[0], argv); 180 err = errno; 181 182 (void) freopen("/dev/tty", "w", stderr); 183 (void) fprintf(stderr, gettext("nohup: %s: %s\n"), argv[0], 184 strerror(err)); 185 186 return (err == ENOENT ? NOHUP_ERROR : NOHUP_NOEXEC); 187 188 err: 189 (void) fprintf(stderr, gettext("nohup: cannot open/create " 190 "nohup.out: %s\n"), strerror(errno)); 191 return (NOHUP_ERROR); 192 193 usage: 194 #ifdef XPG4 195 (void) fprintf(stderr, 196 gettext("usage: nohup command [argument ...]\n")); 197 #else 198 (void) fprintf(stderr, gettext("usage:\n" 199 "\tnohup command [argument ...]\n" 200 "\tnohup -p [-Fa] pid [pid ...]\n" 201 "\tnohup -g [-Fa] pgid [pgid ...]\n")); 202 #endif 203 return (NOHUP_ERROR); 204 } 205 206 #ifndef XPG4 207 208 /* 209 * File descriptor iteration interface. 210 */ 211 typedef int proc_fd_iter_f(void *, int); 212 213 static int 214 Pfd_iter(struct ps_prochandle *P, proc_fd_iter_f *cb, void *data) 215 { 216 char file[64]; 217 dirent_t *dentp; 218 DIR *dirp; 219 int ret = 0; 220 221 if (Pstate(P) == PS_DEAD) 222 return (-1); 223 224 (void) sprintf(file, "/proc/%d/fd", (int)Pstatus(P)->pr_pid); 225 if ((dirp = opendir(file)) == NULL) 226 return (-1); 227 228 while ((dentp = readdir(dirp)) != NULL) { 229 if (dentp->d_name[0] == '.') 230 continue; 231 232 if ((ret = cb(data, atoi(dentp->d_name))) != 0) 233 break; 234 } 235 236 (void) closedir(dirp); 237 238 return (ret); 239 } 240 241 /*ARGSUSED*/ 242 static int 243 fd_cb(void *data, int fd) 244 { 245 struct stat64 sbuf; 246 int flags; 247 int *fdp; 248 int oflags; 249 char *file; 250 int tmpfd; 251 252 /* 253 * See if this fd refers to the controlling tty. 254 */ 255 if (pr_fstat64(g_proc, fd, &sbuf) == -1 || 256 sbuf.st_rdev != Ppsinfo(g_proc)->pr_ttydev) 257 return (0); 258 259 /* 260 * tty's opened for input are usually O_RDWR so that the program 261 * can change terminal settings. We assume that if there's a 262 * controlling tty in the STDIN_FILENO file descriptor that is 263 * effectively used only for input. If standard in gets dup'ed to 264 * other file descriptors, then we're out of luck unless the 265 * program is nice enough to fcntl it to be O_RDONLY. We close the 266 * file descriptor before we call open to handle the case that 267 * there are no available file descriptors left in the victim. If 268 * our call to pr_open fails, we try to reopen the controlling tty. 269 */ 270 flags = pr_fcntl(g_proc, fd, F_GETFL, NULL); 271 if ((flags & O_ACCMODE) == O_RDONLY || fd == STDIN_FILENO) { 272 fdp = &g_rdfd; 273 oflags = O_RDONLY; 274 file = "/dev/null"; 275 } else { 276 fdp = &g_wrfd; 277 oflags = O_RDWR | O_APPEND; 278 file = &nout[0]; 279 } 280 281 if (*fdp < 0) { 282 (void) pr_close(g_proc, fd); 283 284 tmpfd = pr_open(g_proc, file, oflags, 0); 285 286 if (tmpfd < 0) { 287 (void) fprintf(stderr, 288 gettext("nohup: process %d cannot open %s: %s\n"), 289 Pstatus(g_proc)->pr_pid, file, strerror(errno)); 290 291 goto err; 292 } 293 294 if (tmpfd != fd) { 295 (void) pr_fcntl(g_proc, tmpfd, F_DUP2FD, 296 (void *)(uintptr_t)fd); 297 (void) pr_close(g_proc, tmpfd); 298 } 299 300 *fdp = fd; 301 } else { 302 (void) pr_fcntl(g_proc, *fdp, F_DUP2FD, (void *)(uintptr_t)fd); 303 } 304 305 return (0); 306 307 err: 308 /* 309 * The victim couldn't open nohup.out so we'll have it try to reopen 310 * its terminal. If this fails, we are left with little recourse. 311 */ 312 tmpfd = pr_open(g_proc, "/dev/tty", O_RDWR, 0); 313 314 if (tmpfd != fd && tmpfd >= 0) { 315 (void) pr_fcntl(g_proc, tmpfd, F_DUP2FD, (void *)(uintptr_t)fd); 316 (void) pr_close(g_proc, tmpfd); 317 } 318 319 return (1); 320 } 321 322 static int 323 lwp_restartable(short syscall) 324 { 325 switch (syscall) { 326 case SYS_read: 327 case SYS_readv: 328 case SYS_pread: 329 case SYS_pread64: 330 case SYS_write: 331 case SYS_writev: 332 case SYS_pwrite: 333 case SYS_pwrite64: 334 case SYS_ioctl: 335 case SYS_fcntl: 336 case SYS_getmsg: 337 case SYS_getpmsg: 338 case SYS_putmsg: 339 case SYS_putpmsg: 340 case SYS_recv: 341 case SYS_recvmsg: 342 case SYS_recvfrom: 343 case SYS_send: 344 case SYS_sendmsg: 345 case SYS_sendto: 346 return (1); 347 } 348 349 return (0); 350 } 351 352 /*ARGSUSED*/ 353 static int 354 lwp_abort(void *data, const lwpstatus_t *lsp) 355 { 356 struct ps_lwphandle *L; 357 int err; 358 359 /* 360 * Continue if this lwp isn't asleep in a restartable syscall. 361 */ 362 if (!(lsp->pr_flags & PR_ASLEEP) || !lwp_restartable(lsp->pr_syscall)) 363 return (0); 364 365 L = Lgrab(g_proc, lsp->pr_lwpid, &err); 366 (void) Lsetrun(L, 0, PRSABORT); 367 Lfree(L); 368 369 /* 370 * Indicate that we have aborted a syscall. 371 */ 372 g_dirty = 1; 373 374 return (0); 375 } 376 377 /*ARGSUSED*/ 378 static int 379 lwp_restart(void *data, const lwpstatus_t *lsp) 380 { 381 struct ps_lwphandle *L; 382 int err; 383 384 /* 385 * If any lwp is still sleeping in a restartable syscall, it means 386 * the lwp is wedged and we've screwed up. 387 */ 388 if (lsp->pr_flags & PR_ASLEEP) { 389 if (!lwp_restartable(lsp->pr_syscall)) 390 return (0); 391 (void) fprintf(stderr, gettext("nohup: LWP %d failed " 392 "to abort syscall (%d) in process %d\n"), 393 lsp->pr_lwpid, lsp->pr_syscall, Pstatus(g_proc)->pr_pid); 394 return (1); 395 } 396 397 if (lsp->pr_why == PR_SYSEXIT && lsp->pr_errno == EINTR) { 398 L = Lgrab(g_proc, lsp->pr_lwpid, &err); 399 (void) Lputareg(L, R_R0, ERESTART); 400 Lsync(L); 401 Lfree(L); 402 } 403 404 return (0); 405 } 406 407 static int 408 do_pnohup(struct ps_prochandle *P) 409 { 410 int sig = 0; 411 struct sigaction sa; 412 const pstatus_t *psp; 413 414 psp = Pstatus(P); 415 416 /* 417 * Make sure there's a pending procfs stop directive. 418 */ 419 (void) Pdstop(P); 420 421 if (Pcreate_agent(P) != 0) { 422 (void) fprintf(stderr, gettext("nohup: cannot control " 423 "process %d\n"), psp->pr_pid); 424 goto err_no_agent; 425 } 426 427 /* 428 * Set the disposition of SIGHUP and SIGQUIT to SIG_IGN. If either 429 * signal is handled by the victim, only adjust the disposition if 430 * the -a flag is set. 431 */ 432 if (!opt_a && pr_sigaction(P, SIGHUP, NULL, &sa) != 0) { 433 (void) fprintf(stderr, gettext("nohup: cannot read " 434 "disposition of SIGHUP for %d\n"), psp->pr_pid); 435 goto no_sigs; 436 } 437 438 if (!opt_a && sa.sa_handler != SIG_DFL && sa.sa_handler != SIG_IGN) { 439 (void) fprintf(stderr, gettext("nohup: SIGHUP already handled " 440 "by %d; use -a to force process to ignore\n"), psp->pr_pid); 441 goto no_sigs; 442 } 443 444 if (!opt_a && pr_sigaction(P, SIGQUIT, NULL, &sa) != 0) { 445 (void) fprintf(stderr, gettext("nohup: cannot read " 446 "disposition of SIGQUIT for %d\n"), psp->pr_pid); 447 goto no_sigs; 448 } 449 450 if (!opt_a && sa.sa_handler != SIG_DFL && sa.sa_handler != SIG_IGN) { 451 (void) fprintf(stderr, gettext("nohup: SIGQUIT already handled " 452 "by %d; use -a to force process to ignore\n"), psp->pr_pid); 453 goto no_sigs; 454 } 455 456 sa.sa_handler = SIG_IGN; 457 458 if (pr_sigaction(P, SIGHUP, &sa, NULL) != 0) { 459 (void) fprintf(stderr, gettext("nohup: cannot set " 460 "disposition of SIGHUP for %d\n"), psp->pr_pid); 461 goto no_sigs; 462 } 463 464 if (pr_sigaction(P, SIGQUIT, &sa, NULL) != 0) { 465 (void) fprintf(stderr, gettext("nohup: cannot set " 466 "disposition of SIGQUIT for %d\n"), psp->pr_pid); 467 goto no_sigs; 468 } 469 470 no_sigs: 471 Pdestroy_agent(P); 472 473 /* 474 * We need to close and reassign some file descriptors, but we 475 * need to be careful about how we do it. If we send in the agent 476 * to close some fd and there's an lwp asleep in the kernel due to 477 * a syscall using that fd, then we have a problem. The normal 478 * sequence of events is the close syscall wakes up any threads 479 * that have the fd in question active (see kthread.t_activefd) 480 * and then waits for those threads to wake up and release the 481 * file descriptors (they then continue to user-land to return 482 * EBADF from the syscall). However, recall that if the agent lwp 483 * is present in a process, no other lwps can run, so if the agent 484 * lwp itself is making the call to close(2) (or something else 485 * like dup2 that involves a call to closeandsetf()) then we're in 486 * pretty bad shape. The solution is to abort and restart any lwp 487 * asleep in a syscall on the off chance that it may be using one 488 * of the file descriptors that we want to manipulate. 489 */ 490 491 /* 492 * We may need to chase some lwps out of the kernel briefly, so we 493 * send SIGCONT to the process if it was previously stopped due to 494 * a job control signal, and save the current signal to repost it 495 * when we detatch from the victim. A process that is stopped due 496 * to job control will start running as soon as we send SIGCONT 497 * since there is no procfs stop command pending; we use Pdstop to 498 * post a procfs stop request (above). 499 */ 500 if ((psp->pr_lwp.pr_flags & PR_STOPPED) && 501 psp->pr_lwp.pr_why == PR_JOBCONTROL) { 502 sig = psp->pr_lwp.pr_what; 503 (void) kill(psp->pr_pid, SIGCONT); 504 (void) Pwait(P, 0); 505 } 506 507 (void) Psysexit(P, 0, 1); 508 509 /* 510 * Abort each syscall; set g_dirty if any lwp was asleep. 511 */ 512 g_dirty = 0; 513 g_proc = P; 514 (void) Plwp_iter(P, lwp_abort, NULL); 515 516 if (g_dirty) { 517 /* 518 * Block until each lwp that was asleep in a syscall has 519 * wandered back up to user-land. 520 */ 521 (void) Pwait(P, 0); 522 523 /* 524 * Make sure that each lwp has successfully aborted its 525 * syscall and that the syscall gets restarted when we 526 * detach later. 527 */ 528 if (Plwp_iter(P, lwp_restart, NULL) != 0) 529 goto err_no_agent; 530 } 531 532 (void) Psysexit(P, 0, 0); 533 534 if (Pcreate_agent(P) != 0) { 535 (void) fprintf(stderr, gettext("nohup: cannot control " 536 "process %d\n"), psp->pr_pid); 537 goto err_no_agent; 538 } 539 540 /* 541 * See if the victim has access to the nohup.out file we created. 542 * If the user does something that would invalidate the result 543 * of this call from here until the call to pr_open, the process 544 * may be left in an inconsistent state -- we assume that the user 545 * is not intentionally trying to shoot himself in the foot. 546 */ 547 if (pr_access(P, nout, R_OK | W_OK) != 0) { 548 (void) fprintf(stderr, gettext("nohup: process %d can not " 549 "access %s: %s\n"), psp->pr_pid, nout, strerror(errno)); 550 goto err_agent; 551 } 552 553 /* 554 * Redirect output to the controlling tty to nohup.out and tty 555 * input to read from /dev/null. 556 */ 557 558 g_wrfd = -1; 559 g_rdfd = -1; 560 561 (void) Pfd_iter(P, fd_cb, NULL); 562 563 Pdestroy_agent(P); 564 if (sig != 0) 565 (void) kill(psp->pr_pid, sig); 566 567 return (0); 568 569 err_agent: 570 Pdestroy_agent(P); 571 err_no_agent: 572 if (sig != 0) 573 (void) kill(psp->pr_pid, sig); 574 return (-1); 575 } 576 577 /*ARGSUSED*/ 578 static void 579 intr(int sig) 580 { 581 g_interrupt = 1; 582 } 583 584 static int 585 pnohup(int argc, char **argv) 586 { 587 struct ps_prochandle *P; 588 int i, j; 589 int flag = 0; 590 int gcode; 591 int nh_fd = -1; 592 char *fname; 593 char *home; 594 int nerrs = 0; 595 596 /* 597 * Catch signals from the terminal. 598 */ 599 if (sigset(SIGHUP, SIG_IGN) == SIG_DFL) 600 (void) sigset(SIGHUP, intr); 601 if (sigset(SIGINT, SIG_IGN) == SIG_DFL) 602 (void) sigset(SIGINT, intr); 603 if (sigset(SIGQUIT, SIG_IGN) == SIG_DFL) 604 (void) sigset(SIGQUIT, intr); 605 (void) sigset(SIGPIPE, intr); 606 (void) sigset(SIGTERM, intr); 607 608 if (opt_F) 609 flag |= PGRAB_FORCE; 610 611 /* 612 * Set nout to be the full path name of nohup.out and fname to be 613 * the simplified path name: 614 * nout = /cwd/nohup.out fname = nohup.out 615 * nout = $HOME/nohup.out fname = $HOME/nohup.out 616 */ 617 if (getcwd(nout, sizeof (nout) - strlen("/nohup.out") - 1) != NULL) { 618 fname = &nout[strlen(nout)]; 619 (void) strcpy(fname, "/nohup.out"); 620 fname++; 621 622 nh_fd = open(nout, O_WRONLY | O_CREAT, NOHUP_PERM); 623 } 624 625 if (nh_fd == -1 && (home = getenv("HOME")) != NULL) { 626 if (snprintf(nout, sizeof (nout), 627 "%s/nohup.out", home) < sizeof (nout)) { 628 nh_fd = open(nout, O_WRONLY | O_CREAT, NOHUP_PERM); 629 fname = &nout[0]; 630 } 631 } 632 633 if (nh_fd == -1) { 634 (void) fprintf(stderr, gettext("nohup: cannot open/create " 635 "nohup.out: %s\n"), strerror(errno)); 636 637 return (NOHUP_ERROR); 638 } 639 640 if (opt_g) { 641 pid_t *pgids; 642 int npgids; 643 int success; 644 645 /* 646 * Make nohup its own process group leader so that we 647 * don't accidently send SIGSTOP to this process. 648 */ 649 (void) setpgid(0, 0); 650 651 /* 652 * If a list of process group ids is specified, we want to 653 * first SIGSTOP the whole process group so that we can be 654 * sure not to miss any processes that belong to the group 655 * (it's harder to hit a moving target). We then iterate 656 * over all the processes on the system looking for 657 * members of the given process group to apply the 658 * do_pnohup function to. If the process was stopped due 659 * to our SIGSTOP, we send the process SIGCONT; if the 660 * process was already stopped, we leave it alone. 661 */ 662 pgids = calloc(argc, sizeof (pid_t)); 663 pgids[0] = getpid(); 664 npgids = 1; 665 666 for (i = 0; i < argc; i++) { 667 dirent_t *dent; 668 DIR *dirp; 669 psinfo_t psinfo; 670 const pstatus_t *psp; 671 pid_t pgid; 672 char *end; 673 hrtime_t kill_time, stop_time; 674 675 if (isdigit(*argv[i])) { 676 pgid = strtol(argv[i], &end, 10); 677 678 /* 679 * kill(2) with pid = 0 or -1 has a special 680 * meaning, so don't let pgid be 0 or 1. 681 */ 682 if (*end == '\0' && pgid > 1) 683 goto pgid_ok; 684 } 685 686 (void) fprintf(stderr, gettext("nohup: " 687 "bad process group %s\n"), argv[i]); 688 nerrs++; 689 continue; 690 691 pgid_ok: 692 /* 693 * We don't want to nohup a process group twice. 694 */ 695 for (j = 0; j < npgids; j++) { 696 if (pgids[j] == pgid) 697 break; 698 } 699 700 if (j != npgids) 701 continue; 702 703 pgids[npgids++] = pgid; 704 705 /* 706 * Have the kernel stop all members of the process 707 * group; record the time we stopped the process 708 * group so that we can tell if a member stopped 709 * because of this call to kill(2) or if it was 710 * already stopped when we got here. If the user 711 * job control stops the victim between the call 712 * to gethrtime(2) and kill(2), we may send 713 * SIGCONT when we really shouldn't -- we assume 714 * that the user is not trying to shoot himself in 715 * the foot. 716 */ 717 kill_time = gethrtime(); 718 if (kill(-pgid, SIGSTOP) == -1) { 719 (void) fprintf(stderr, gettext("nohup: cannot " 720 "stop process group %d: %s\n"), pgid, 721 errno != ESRCH ? strerror(errno) : 722 gettext("No such process group")); 723 724 nerrs++; 725 continue; 726 } 727 728 dirp = opendir("/proc"); 729 success = 0; 730 while ((dent = readdir(dirp)) != NULL && !g_interrupt) { 731 if (dent->d_name[0] == '.') 732 continue; 733 734 if (proc_arg_psinfo(dent->d_name, 735 PR_ARG_PIDS, &psinfo, &gcode) == -1) 736 continue; 737 738 if (psinfo.pr_pgid != pgid) 739 continue; 740 741 /* 742 * Ignore zombies. 743 */ 744 if (psinfo.pr_nlwp == 0) 745 continue; 746 747 if ((P = proc_arg_grab(dent->d_name, 748 PR_ARG_PIDS, flag, &gcode)) == NULL) { 749 (void) fprintf(stderr, gettext("nohup: " 750 "cannot examine %s: %s\n"), 751 dent->d_name, Pgrab_error(gcode)); 752 753 (void) kill(psinfo.pr_pid, SIGCONT); 754 continue; 755 } 756 757 /* 758 * This implicitly restarts any process that 759 * was stopped via job control any time after 760 * the call to kill(2). This is the desired 761 * behavior since nohup is busy trying to 762 * disassociate a process from its controlling 763 * terminal. 764 */ 765 psp = Pstatus(P); 766 if (psp->pr_lwp.pr_why == PR_JOBCONTROL) { 767 stop_time = 768 psp->pr_lwp.pr_tstamp.tv_sec; 769 stop_time *= (hrtime_t)NANOSEC; 770 stop_time += 771 psp->pr_lwp.pr_tstamp.tv_nsec; 772 } else { 773 stop_time = 0; 774 } 775 776 if (do_pnohup(P) == 0) 777 success = 1; 778 779 /* 780 * If the process was stopped because of 781 * our call to kill(2) (i.e. if it stopped 782 * some time after kill_time) then restart 783 * the process. 784 */ 785 if (kill_time <= stop_time) 786 (void) kill(psinfo.pr_pid, SIGCONT); 787 788 Prelease(P, 0); 789 } 790 791 /* 792 * If we didn't successfully nohup any member of the 793 * process group. 794 */ 795 if (!success) 796 nerrs++; 797 798 (void) closedir(dirp); 799 } 800 } else { 801 for (i = 0; i < argc && !g_interrupt; i++) { 802 if ((P = proc_arg_grab(argv[i], PR_ARG_PIDS, flag, 803 &gcode)) == NULL) { 804 (void) fprintf(stderr, 805 gettext("nohup: cannot examine %s: %s\n"), 806 argv[i], Pgrab_error(gcode)); 807 808 nerrs++; 809 continue; 810 } 811 812 if (do_pnohup(P) != 0) 813 nerrs++; 814 815 Prelease(P, 0); 816 } 817 } 818 819 (void) close(nh_fd); 820 821 if (argc == nerrs) 822 return (NOHUP_ERROR); 823 824 (void) fprintf(stderr, gettext("Sending output to %s\n"), fname); 825 826 return (0); 827 } 828 829 #endif /* !XPG4 */ 830