xref: /illumos-gate/usr/src/cmd/nohup/nohup.c (revision 6dde88b51419b99fe0aab8e56184c693945826b8)
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, 0);
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, 0);
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 		    0);
304 	}
305 
306 	return (0);
307 
308 err:
309 	/*
310 	 * The victim couldn't open nohup.out so we'll have it try to reopen
311 	 * its terminal. If this fails, we are left with little recourse.
312 	 */
313 	tmpfd = pr_open(g_proc, "/dev/tty", O_RDWR, 0);
314 
315 	if (tmpfd != fd && tmpfd >= 0) {
316 		(void) pr_fcntl(g_proc, tmpfd, F_DUP2FD, (void *)(uintptr_t)fd,
317 		    0);
318 		(void) pr_close(g_proc, tmpfd);
319 	}
320 
321 	return (1);
322 }
323 
324 static int
325 lwp_restartable(short syscall)
326 {
327 	switch (syscall) {
328 	case SYS_read:
329 	case SYS_readv:
330 	case SYS_pread:
331 	case SYS_pread64:
332 	case SYS_write:
333 	case SYS_writev:
334 	case SYS_pwrite:
335 	case SYS_pwrite64:
336 	case SYS_ioctl:
337 	case SYS_fcntl:
338 	case SYS_getmsg:
339 	case SYS_getpmsg:
340 	case SYS_putmsg:
341 	case SYS_putpmsg:
342 	case SYS_recv:
343 	case SYS_recvmsg:
344 	case SYS_recvfrom:
345 	case SYS_send:
346 	case SYS_sendmsg:
347 	case SYS_sendto:
348 		return (1);
349 	}
350 
351 	return (0);
352 }
353 
354 /*ARGSUSED*/
355 static int
356 lwp_abort(void *data, const lwpstatus_t *lsp)
357 {
358 	struct ps_lwphandle *L;
359 	int err;
360 
361 	/*
362 	 * Continue if this lwp isn't asleep in a restartable syscall.
363 	 */
364 	if (!(lsp->pr_flags & PR_ASLEEP) || !lwp_restartable(lsp->pr_syscall))
365 		return (0);
366 
367 	L = Lgrab(g_proc, lsp->pr_lwpid, &err);
368 	(void) Lsetrun(L, 0, PRSABORT);
369 	Lfree(L);
370 
371 	/*
372 	 * Indicate that we have aborted a syscall.
373 	 */
374 	g_dirty = 1;
375 
376 	return (0);
377 }
378 
379 /*ARGSUSED*/
380 static int
381 lwp_restart(void *data, const lwpstatus_t *lsp)
382 {
383 	struct ps_lwphandle *L;
384 	int err;
385 
386 	/*
387 	 * If any lwp is still sleeping in a restartable syscall, it means
388 	 * the lwp is wedged and we've screwed up.
389 	 */
390 	if (lsp->pr_flags & PR_ASLEEP) {
391 		if (!lwp_restartable(lsp->pr_syscall))
392 			return (0);
393 		(void) fprintf(stderr, gettext("nohup: LWP %d failed "
394 		    "to abort syscall (%d) in process %d\n"),
395 		    lsp->pr_lwpid, lsp->pr_syscall, Pstatus(g_proc)->pr_pid);
396 		return (1);
397 	}
398 
399 	if (lsp->pr_why == PR_SYSEXIT && lsp->pr_errno == EINTR) {
400 		L = Lgrab(g_proc, lsp->pr_lwpid, &err);
401 		(void) Lputareg(L, R_R0, ERESTART);
402 		Lsync(L);
403 		Lfree(L);
404 	}
405 
406 	return (0);
407 }
408 
409 static int
410 do_pnohup(struct ps_prochandle *P)
411 {
412 	int sig = 0;
413 	struct sigaction sa;
414 	const pstatus_t *psp;
415 
416 	psp = Pstatus(P);
417 
418 	/*
419 	 * Make sure there's a pending procfs stop directive.
420 	 */
421 	(void) Pdstop(P);
422 
423 	if (Pcreate_agent(P) != 0) {
424 		(void) fprintf(stderr, gettext("nohup: cannot control "
425 		    "process %d\n"), psp->pr_pid);
426 		goto err_no_agent;
427 	}
428 
429 	/*
430 	 * Set the disposition of SIGHUP and SIGQUIT to SIG_IGN. If either
431 	 * signal is handled by the victim, only adjust the disposition if
432 	 * the -a flag is set.
433 	 */
434 	if (!opt_a && pr_sigaction(P, SIGHUP, NULL, &sa) != 0) {
435 		(void) fprintf(stderr, gettext("nohup: cannot read "
436 		    "disposition of SIGHUP for %d\n"), psp->pr_pid);
437 		goto no_sigs;
438 	}
439 
440 	if (!opt_a && sa.sa_handler != SIG_DFL && sa.sa_handler != SIG_IGN) {
441 		(void) fprintf(stderr, gettext("nohup: SIGHUP already handled "
442 		    "by %d; use -a to force process to ignore\n"), psp->pr_pid);
443 		goto no_sigs;
444 	}
445 
446 	if (!opt_a && pr_sigaction(P, SIGQUIT, NULL, &sa) != 0) {
447 		(void) fprintf(stderr, gettext("nohup: cannot read "
448 		    "disposition of SIGQUIT for %d\n"), psp->pr_pid);
449 		goto no_sigs;
450 	}
451 
452 	if (!opt_a && sa.sa_handler != SIG_DFL && sa.sa_handler != SIG_IGN) {
453 		(void) fprintf(stderr, gettext("nohup: SIGQUIT already handled "
454 		    "by %d; use -a to force process to ignore\n"), psp->pr_pid);
455 		goto no_sigs;
456 	}
457 
458 	sa.sa_handler = SIG_IGN;
459 
460 	if (pr_sigaction(P, SIGHUP, &sa, NULL) != 0) {
461 		(void) fprintf(stderr, gettext("nohup: cannot set "
462 		    "disposition of SIGHUP for %d\n"), psp->pr_pid);
463 		goto no_sigs;
464 	}
465 
466 	if (pr_sigaction(P, SIGQUIT, &sa, NULL) != 0) {
467 		(void) fprintf(stderr, gettext("nohup: cannot set "
468 		    "disposition of SIGQUIT for %d\n"), psp->pr_pid);
469 		goto no_sigs;
470 	}
471 
472 no_sigs:
473 	Pdestroy_agent(P);
474 
475 	/*
476 	 * We need to close and reassign some file descriptors, but we
477 	 * need to be careful about how we do it. If we send in the agent
478 	 * to close some fd and there's an lwp asleep in the kernel due to
479 	 * a syscall using that fd, then we have a problem. The normal
480 	 * sequence of events is the close syscall wakes up any threads
481 	 * that have the fd in question active (see kthread.t_activefd)
482 	 * and then waits for those threads to wake up and release the
483 	 * file descriptors (they then continue to user-land to return
484 	 * EBADF from the syscall). However, recall that if the agent lwp
485 	 * is present in a process, no other lwps can run, so if the agent
486 	 * lwp itself is making the call to close(2) (or something else
487 	 * like dup2 that involves a call to closeandsetf()) then we're in
488 	 * pretty bad shape. The solution is to abort and restart any lwp
489 	 * asleep in a syscall on the off chance that it may be using one
490 	 * of the file descriptors that we want to manipulate.
491 	 */
492 
493 	/*
494 	 * We may need to chase some lwps out of the kernel briefly, so we
495 	 * send SIGCONT to the process if it was previously stopped due to
496 	 * a job control signal, and save the current signal to repost it
497 	 * when we detatch from the victim. A process that is stopped due
498 	 * to job control will start running as soon as we send SIGCONT
499 	 * since there is no procfs stop command pending; we use Pdstop to
500 	 * post a procfs stop request (above).
501 	 */
502 	if ((psp->pr_lwp.pr_flags & PR_STOPPED) &&
503 	    psp->pr_lwp.pr_why == PR_JOBCONTROL) {
504 		sig = psp->pr_lwp.pr_what;
505 		(void) kill(psp->pr_pid, SIGCONT);
506 		(void) Pwait(P, 0);
507 	}
508 
509 	(void) Psysexit(P, 0, 1);
510 
511 	/*
512 	 * Abort each syscall; set g_dirty if any lwp was asleep.
513 	 */
514 	g_dirty = 0;
515 	g_proc = P;
516 	(void) Plwp_iter(P, lwp_abort, NULL);
517 
518 	if (g_dirty) {
519 		/*
520 		 * Block until each lwp that was asleep in a syscall has
521 		 * wandered back up to user-land.
522 		 */
523 		(void) Pwait(P, 0);
524 
525 		/*
526 		 * Make sure that each lwp has successfully aborted its
527 		 * syscall and that the syscall gets restarted when we
528 		 * detach later.
529 		 */
530 		if (Plwp_iter(P, lwp_restart, NULL) != 0)
531 			goto err_no_agent;
532 	}
533 
534 	(void) Psysexit(P, 0, 0);
535 
536 	if (Pcreate_agent(P) != 0) {
537 		(void) fprintf(stderr, gettext("nohup: cannot control "
538 		    "process %d\n"), psp->pr_pid);
539 		goto err_no_agent;
540 	}
541 
542 	/*
543 	 * See if the victim has access to the nohup.out file we created.
544 	 * If the user does something that would invalidate the result
545 	 * of this call from here until the call to pr_open, the process
546 	 * may be left in an inconsistent state -- we assume that the user
547 	 * is not intentionally trying to shoot himself in the foot.
548 	 */
549 	if (pr_access(P, nout, R_OK | W_OK) != 0) {
550 		(void) fprintf(stderr, gettext("nohup: process %d can not "
551 		    "access %s: %s\n"), psp->pr_pid, nout, strerror(errno));
552 		goto err_agent;
553 	}
554 
555 	/*
556 	 * Redirect output to the controlling tty to nohup.out and tty
557 	 * input to read from /dev/null.
558 	 */
559 
560 	g_wrfd = -1;
561 	g_rdfd = -1;
562 
563 	(void) Pfd_iter(P, fd_cb, NULL);
564 
565 	Pdestroy_agent(P);
566 	if (sig != 0)
567 		(void) kill(psp->pr_pid, sig);
568 
569 	return (0);
570 
571 err_agent:
572 	Pdestroy_agent(P);
573 err_no_agent:
574 	if (sig != 0)
575 		(void) kill(psp->pr_pid, sig);
576 	return (-1);
577 }
578 
579 /*ARGSUSED*/
580 static void
581 intr(int sig)
582 {
583 	g_interrupt = 1;
584 }
585 
586 static int
587 pnohup(int argc, char **argv)
588 {
589 	struct ps_prochandle *P;
590 	int i, j;
591 	int flag = 0;
592 	int gcode;
593 	int nh_fd = -1;
594 	char *fname;
595 	char *home;
596 	int nerrs = 0;
597 
598 	/*
599 	 * Catch signals from the terminal.
600 	 */
601 	if (sigset(SIGHUP, SIG_IGN) == SIG_DFL)
602 		(void) sigset(SIGHUP, intr);
603 	if (sigset(SIGINT, SIG_IGN) == SIG_DFL)
604 		(void) sigset(SIGINT, intr);
605 	if (sigset(SIGQUIT, SIG_IGN) == SIG_DFL)
606 		(void) sigset(SIGQUIT, intr);
607 	(void) sigset(SIGPIPE, intr);
608 	(void) sigset(SIGTERM, intr);
609 
610 	if (opt_F)
611 		flag |= PGRAB_FORCE;
612 
613 	/*
614 	 * Set nout to be the full path name of nohup.out and fname to be
615 	 * the simplified path name:
616 	 * nout = /cwd/nohup.out	fname = nohup.out
617 	 * nout = $HOME/nohup.out	fname = $HOME/nohup.out
618 	 */
619 	if (getcwd(nout, sizeof (nout) - strlen("/nohup.out") - 1) != NULL) {
620 		fname = &nout[strlen(nout)];
621 		(void) strcpy(fname, "/nohup.out");
622 		fname++;
623 
624 		nh_fd = open(nout, O_WRONLY | O_CREAT, NOHUP_PERM);
625 	}
626 
627 	if (nh_fd == -1 && (home = getenv("HOME")) != NULL) {
628 		if (snprintf(nout, sizeof (nout),
629 		    "%s/nohup.out", home) < sizeof (nout)) {
630 			nh_fd = open(nout, O_WRONLY | O_CREAT, NOHUP_PERM);
631 			fname = &nout[0];
632 		}
633 	}
634 
635 	if (nh_fd == -1) {
636 		(void) fprintf(stderr, gettext("nohup: cannot open/create "
637 		    "nohup.out: %s\n"), strerror(errno));
638 
639 		return (NOHUP_ERROR);
640 	}
641 
642 	if (opt_g) {
643 		pid_t *pgids;
644 		int npgids;
645 		int success;
646 
647 		/*
648 		 * Make nohup its own process group leader so that we
649 		 * don't accidently send SIGSTOP to this process.
650 		 */
651 		(void) setpgid(0, 0);
652 
653 		/*
654 		 * If a list of process group ids is specified, we want to
655 		 * first SIGSTOP the whole process group so that we can be
656 		 * sure not to miss any processes that belong to the group
657 		 * (it's harder to hit a moving target). We then iterate
658 		 * over all the processes on the system looking for
659 		 * members of the given process group to apply the
660 		 * do_pnohup function to. If the process was stopped due
661 		 * to our SIGSTOP, we send the process SIGCONT; if the
662 		 * process was already stopped, we leave it alone.
663 		 */
664 		pgids = calloc(argc, sizeof (pid_t));
665 		pgids[0] = getpid();
666 		npgids = 1;
667 
668 		for (i = 0; i < argc; i++) {
669 			dirent_t *dent;
670 			DIR *dirp;
671 			psinfo_t psinfo;
672 			const pstatus_t *psp;
673 			pid_t pgid;
674 			char *end;
675 			hrtime_t kill_time, stop_time;
676 
677 			if (isdigit(*argv[i])) {
678 				pgid = strtol(argv[i], &end, 10);
679 
680 				/*
681 				 * kill(2) with pid = 0 or -1 has a special
682 				 * meaning, so don't let pgid be 0 or 1.
683 				 */
684 				if (*end == '\0' && pgid > 1)
685 					goto pgid_ok;
686 			}
687 
688 			(void) fprintf(stderr, gettext("nohup: "
689 			    "bad process group %s\n"), argv[i]);
690 			nerrs++;
691 			continue;
692 
693 pgid_ok:
694 			/*
695 			 * We don't want to nohup a process group twice.
696 			 */
697 			for (j = 0; j < npgids; j++) {
698 				if (pgids[j] == pgid)
699 					break;
700 			}
701 
702 			if (j != npgids)
703 				continue;
704 
705 			pgids[npgids++] = pgid;
706 
707 			/*
708 			 * Have the kernel stop all members of the process
709 			 * group; record the time we stopped the process
710 			 * group so that we can tell if a member stopped
711 			 * because of this call to kill(2) or if it was
712 			 * already stopped when we got here. If the user
713 			 * job control stops the victim between the call
714 			 * to gethrtime(2) and kill(2), we may send
715 			 * SIGCONT when we really shouldn't -- we assume
716 			 * that the user is not trying to shoot himself in
717 			 * the foot.
718 			 */
719 			kill_time = gethrtime();
720 			if (kill(-pgid, SIGSTOP) == -1) {
721 				(void) fprintf(stderr, gettext("nohup: cannot "
722 				    "stop process group %d: %s\n"), pgid,
723 				    errno != ESRCH ? strerror(errno) :
724 				    gettext("No such process group"));
725 
726 				nerrs++;
727 				continue;
728 			}
729 
730 			dirp = opendir("/proc");
731 			success = 0;
732 			while ((dent = readdir(dirp)) != NULL && !g_interrupt) {
733 				if (dent->d_name[0] == '.')
734 					continue;
735 
736 				if (proc_arg_psinfo(dent->d_name,
737 				    PR_ARG_PIDS, &psinfo, &gcode) == -1)
738 					continue;
739 
740 				if (psinfo.pr_pgid != pgid)
741 					continue;
742 
743 				/*
744 				 * Ignore zombies.
745 				 */
746 				if (psinfo.pr_nlwp == 0)
747 					continue;
748 
749 				if ((P = proc_arg_grab(dent->d_name,
750 				    PR_ARG_PIDS, flag, &gcode)) == NULL) {
751 					(void) fprintf(stderr, gettext("nohup: "
752 					    "cannot examine %s: %s\n"),
753 					    dent->d_name, Pgrab_error(gcode));
754 
755 					(void) kill(psinfo.pr_pid, SIGCONT);
756 					continue;
757 				}
758 
759 				/*
760 				 * This implicitly restarts any process that
761 				 * was stopped via job control any time after
762 				 * the call to kill(2). This is the desired
763 				 * behavior since nohup is busy trying to
764 				 * disassociate a process from its controlling
765 				 * terminal.
766 				 */
767 				psp = Pstatus(P);
768 				if (psp->pr_lwp.pr_why == PR_JOBCONTROL) {
769 					stop_time =
770 					    psp->pr_lwp.pr_tstamp.tv_sec;
771 					stop_time *= (hrtime_t)NANOSEC;
772 					stop_time +=
773 					    psp->pr_lwp.pr_tstamp.tv_nsec;
774 				} else {
775 					stop_time = 0;
776 				}
777 
778 				if (do_pnohup(P) == 0)
779 					success = 1;
780 
781 				/*
782 				 * If the process was stopped because of
783 				 * our call to kill(2) (i.e. if it stopped
784 				 * some time after kill_time) then restart
785 				 * the process.
786 				 */
787 				if (kill_time <= stop_time)
788 					(void) kill(psinfo.pr_pid, SIGCONT);
789 
790 				Prelease(P, 0);
791 			}
792 
793 			/*
794 			 * If we didn't successfully nohup any member of the
795 			 * process group.
796 			 */
797 			if (!success)
798 				nerrs++;
799 
800 			(void) closedir(dirp);
801 		}
802 	} else {
803 		for (i = 0; i < argc && !g_interrupt; i++) {
804 			if ((P = proc_arg_grab(argv[i], PR_ARG_PIDS, flag,
805 			    &gcode)) == NULL) {
806 				(void) fprintf(stderr,
807 				    gettext("nohup: cannot examine %s: %s\n"),
808 				    argv[i], Pgrab_error(gcode));
809 
810 				nerrs++;
811 				continue;
812 			}
813 
814 			if (do_pnohup(P) != 0)
815 				nerrs++;
816 
817 			Prelease(P, 0);
818 		}
819 	}
820 
821 	(void) close(nh_fd);
822 
823 	if (argc == nerrs)
824 		return (NOHUP_ERROR);
825 
826 	(void) fprintf(stderr, gettext("Sending output to %s\n"), fname);
827 
828 	return (0);
829 }
830 
831 #endif /* !XPG4 */
832