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  * A copy of the CDDL is also available via the Internet at
11  * http://www.opensource.org/licenses/cddl1.txt
12  * See the License for the specific language governing permissions
13  * and limitations under the License.
14  *
15  * When distributing Covered Code, include this CDDL HEADER in each
16  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
17  * If applicable, add the following below this CDDL HEADER, with the
18  * fields enclosed by brackets "[]" replaced with your own identifying
19  * information: Portions Copyright [yyyy] [name of copyright owner]
20  *
21  * CDDL HEADER END
22  */
23 
24 /*
25  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
26  * Use is subject to license terms.
27  */
28 
29 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
30 /*	  All Rights Reserved  	*/
31 
32 #if defined(sun)
33 #pragma ident	"@(#)jobs.c	1.28	07/05/14 SMI"
34 #endif
35 
36 #include "defs.h"
37 #include "jobs.h"
38 
39 /*
40  * Copyright 2008-2021 J. Schilling
41  *
42  * @(#)jobs.c	1.123 21/07/13 2008-2021 J. Schilling
43  */
44 #ifndef lint
45 static	UConst char sccsid[] =
46 	"@(#)jobs.c	1.123 21/07/13 2008-2021 J. Schilling";
47 #endif
48 
49 /*
50  * Job control for UNIX Shell
51  */
52 
53 #ifdef	SCHILY_INCLUDES
54 #include	<schily/ioctl.h>	/* Must be before termios.h BSD botch */
55 #include	<schily/termios.h>
56 #include	<schily/types.h>
57 #include	<schily/wait.h>
58 #include	<schily/param.h>
59 #include	<schily/fcntl.h>
60 #include	<schily/errno.h>
61 #include	<schily/times.h>
62 #include	<schily/resource.h>
63 #else
64 #include	<sys/termio.h>
65 #include	<sys/types.h>
66 #include	<sys/wait.h>
67 #include	<sys/param.h>
68 #include	<fcntl.h>
69 #include	<errno.h>
70 #include	<sys/resource.h>
71 #endif
72 
73 #ifndef	WCONTINUED
74 #define	WCONTINUED	0		/* BSD from wait3() and POSIX */
75 #define	WIFCONTINUED(s)	0		/* Can't be there without WCONTINUED */
76 #endif
77 #ifndef	WIFCONTINUED
78 #define	WIFCONTINUED(s)	0		/* May be missing separately */
79 #endif
80 #ifndef	WNOWAIT
81 #define	WNOWAIT		0		/* SVr4 / SunOS / POSIX */
82 #endif
83 #ifndef	WEXITED
84 #define	WEXITED		0		/* SVr4 / SunOS / POSIX */
85 #endif
86 #ifndef	WTRAPPED
87 #define	WTRAPPED	0		/* SVr4 / SunOS / POSIX */
88 #endif
89 #ifndef	WSTOPPED			/* Prefer POSIX name */
90 #ifdef	WUNTRACED
91 #define	WSTOPPED	WUNTRACED	/* SVr4 / SunOS / POSIX */
92 #else
93 #define	WSTOPPED	0
94 #endif
95 #endif
96 
97 #ifdef	FORCE_WAITID		/* Allow to enforce using waitid() to test */
98 #define	HAVE_WAITID		/* platforms where waitid() was considered */
99 #endif				/* unasable by "configure" .		   */
100 #ifdef	NO_WAITID
101 #undef	HAVE_WAITID
102 #endif
103 
104 /*
105  * The following larger block contains definitions that are needed when either
106  * waitid() is missing (e.g. SunOS-4.x) or defective (e.g. Linux, AIX, HP-UX
107  * Mac OS X).
108  */
109 #ifndef	HAVE_WAITID		/* Need to define everything for waitid() */
110 /*
111  * This is used to emulate waitid() via waitpid(), so we need to take
112  * care about things that don't work and things that are missing.
113  *
114  * AIX, Linux and Mac OS X, NetBSD return EINVAL if WNOWAIT is used
115  * with waitpid().
116  * XXX: We need to verify whether this is true as well with waitid().
117  */
118 #ifndef	HAVE_WNOWAIT_WAITPID
119 #undef	WNOWAIT
120 #define	WNOWAIT		0
121 #endif
122 
123 /*
124  * Minimal structure to emulate waitid() via waitpid().
125  * In case of a waitid() emulation, we mainly get a reduced si_status range.
126  */
127 #undef	si_code
128 #undef	si_pid
129 #undef	si_status
130 #undef	si_utime
131 #undef	si_stime
132 
133 typedef struct {
134 	int	si_code;	/* Child status code */
135 	pid_t	si_pid;		/* Child pid */
136 	int	si_status;	/* Child exit code or signal number */
137 	clock_t	si_utime;
138 	clock_t	si_stime;
139 } my_siginfo_t;
140 
141 #define	siginfo_t	my_siginfo_t
142 #undef	waitid
143 #define	waitid		my_waitid
144 #undef	id_t
145 #define	id_t		pid_t
146 
147 /*
148  * End of definitions needed for waitid() emulation.
149  */
150 #endif	/* HAVE_WAITID */
151 
152 #ifdef	DO_DOT_SH_PARAMS
153 static struct codename {
154 	int	c_code;		/* The si_code value */
155 	char	*c_name;	/* The name for si_code */
156 } _codename[] = {
157 	{ CLD_EXITED,	"EXITED" },	/* Child normal exit() */
158 	{ CLD_KILLED,	"KILLED" },	/* Child was killed by signal */
159 	{ CLD_DUMPED,	"DUMPED" },	/* Killed child dumped core */
160 	{ CLD_TRAPPED,	"TRAPPED" },	/* Traced child has stopped */
161 	{ CLD_STOPPED,	"STOPPED" },	/* Child has stopped on signal */
162 	{ CLD_CONTINUED, "CONTINUED" },	/* Stopped child was continued */
163 	{ C_NOEXEC,	"NOEXEC" },	/* No exec permissions on file */
164 	{ C_NOTFOUND,	"NOTFOUND" }	/* File not found */
165 };
166 #define	CODENAMESIZE	(sizeof (_codename) / sizeof (_codename[0]))
167 #endif
168 
169 
170 /*
171  * options to the printjob() function defined below
172  */
173 #define	PR_CUR		00001	/* print job currency ('+', '-', or ' ') */
174 #define	PR_JID		00002	/* print job ID				 */
175 #define	PR_PGID		00004	/* print job's process group ID		 */
176 #define	PR_STAT		00010	/* print status obtained from wait	 */
177 #define	PR_CMD		00020	/* print cmd that invoked job		 */
178 #define	PR_AMP		00040	/* print a '&' if in the background	 */
179 #define	PR_PWD		00100	/* print jobs present working directory	 */
180 
181 #define	PR_DFL		(PR_CUR|PR_JID|PR_STAT|PR_CMD) /* default options */
182 #define	PR_LONG		(PR_DFL|PR_PGID|PR_PWD)	/* long options */
183 
184 static struct termios	mystty;	 /* default termio settings		 */
185 static int		eofflg,
186 			jobcnt,	 /* number of active jobs		 */
187 			jobdone, /* number of active but finished jobs	 */
188 			jobnote; /* jobs requiring notification		 */
189 static int		jobfd;	 /* fd where stdin was moved during job	 */
190 #ifdef	DO_PIPE_PARENT
191 static int		jobsfd;	 /* saved topfd when jobfd > 0		 */
192 #endif
193 static pid_t		svpgid,	 /* saved process group ID		 */
194 			svtgid;	 /* saved foreground process group ID	 */
195 static struct job	*jobcur, /* active jobs listed in currency order */
196 			**nextjob,
197 			*thisjob,
198 			*lastthisjob,
199 			*joblst; /* active jobs listed in job ID order	 */
200 
201 /*
202  * IRIX has waitjob() in libc.
203  */
204 #define	waitjob	sh_waitjob
205 
206 static struct job *pgid2job	__PR((pid_t pgid));
207 static struct job *str2job	__PR((char *cmdp, char *job, int mustbejob));
208 	char	*code2str	__PR((int code));
209 static void	freejob		__PR((struct job *jp));
210 	void	collect_fg_job	__PR((void));
211 static int	statjob		__PR((struct job *jp,
212 					siginfo_t *si, pid_t fg, int rc));
213 static void	collectjobs	__PR((int wnohang));
214 	void	freejobs	__PR((void));
215 static void	waitjob		__PR((struct job *jp));
216 	int	settgid		__PR((pid_t new, pid_t expexted));
217 static void	restartjob	__PR((struct job *jp, int fg));
218 static void	printjob	__PR((struct job *jp, int propts));
219 	void	startjobs	__PR((void));
220 	int	endjobs		__PR((int check_if));
221 	void	deallocjob	__PR((struct job *jp));
222 	pid_t	curpgid		__PR((void));
223 	void	setjobpgid	__PR((pid_t pgid));
224 	void	resetjobfd	__PR((void));
225 	void	setjobfd	__PR((int fd, int sfd));
226 	void	allocjob	__PR((char *cmdp,
227 					unsigned char *cwdp, int monitor));
228 	void	clearjobs	__PR((void));
229 	void	makejob		__PR((int monitor, int fg));
230 	struct job *
231 		postjob		__PR((pid_t pid, int fg, int blt));
232 	void	sysjobs		__PR((int argc, unsigned char *argv[]));
233 	void	sysfgbg		__PR((int argc, char *argv[]));
234 	void	syswait		__PR((int argc, char *argv[]));
235 #define	F_KILL		1
236 #define	F_KILLPG	2
237 #define	F_PGRP		3
238 #define	F_SUSPEND	4
239 static void	sigv		__PR((char *cmdp, int sig, int f, char *args));
240 	void	sysstop		__PR((int argc, char *argv[]));
241 static void	listsigs	__PR((void));
242 #if	defined(DO_KILL_L_SIG) || defined(DO_GETOPT_UTILS)
243 static void	namesigs	__PR((char *argv[]));
244 #endif
245 	void	syskill		__PR((int argc, char *argv[]));
246 	void	syssusp		__PR((int argc, char *argv[]));
247 #ifdef	DO_SYSPGRP
248 static void	pr_pgrp		__PR((pid_t pid, pid_t pgrp, pid_t sgrp));
249 	void	syspgrp		__PR((int argc, char *argv[]));
250 #endif
251 	pid_t	wait_status	__PR((pid_t id,
252 					int *codep, int *statusp, int opts));
253 #ifdef	DO_TIME
254 	void	prtime		__PR((struct job *jp));
255 	void	ruget		__PR((struct rusage *rup));
256 static	void	ruadd		__PR((struct rusage *ru, struct rusage *ru2));
257 #endif
258 #ifndef	HAVE_GETRUSAGE
259 	int	getrusage	__PR((int who, struct rusage *r_usage));
260 #endif
261 #ifndef	HAVE_WAITID
262 static	int	waitid		__PR((idtype_t idtype, id_t id,
263 					siginfo_t *infop, int opts));
264 #endif
265 #ifdef	DO_TRAP_FROM_WAITID
266 static int	didsignal	__PR((siginfo_t	*infop));
267 static void	checksigs	__PR((siginfo_t	*infop));
268 #endif
269 
270 #if	!defined(HAVE_TCGETPGRP) && defined(TIOCGPGRP)
271 pid_t
tcgetpgrp(fd)272 tcgetpgrp(fd)
273 	int	fd;
274 {
275 	pid_t pgid;
276 	if (ioctl(fd, TIOCGPGRP, &pgid) == 0)
277 		return (pgid);
278 	return ((pid_t)-1);
279 }
280 #endif
281 
282 #if	!defined(HAVE_TCSETPGRP) && defined(TIOCSPGRP)
283 int
tcsetpgrp(fd,pgid)284 tcsetpgrp(fd, pgid)
285 	int	fd;
286 	pid_t	pgid;
287 {
288 	return (ioctl(fd, TIOCSPGRP, &pgid));
289 }
290 #endif
291 
292 #ifdef	PROTOTYPES
293 static struct job *
pgid2job(pid_t pgid)294 pgid2job(pid_t pgid)
295 #else
296 static struct job *
297 pgid2job(pgid)
298 	pid_t	pgid;
299 #endif
300 {
301 	struct job *jp;
302 
303 	for (jp = joblst; jp != 0 && jp->j_pid != pgid; jp = jp->j_nxtp)
304 		/* LINTED */
305 		;
306 
307 	return (jp);
308 }
309 
310 static struct job *
str2job(cmdp,job,mustbejob)311 str2job(cmdp, job, mustbejob)
312 	char	*cmdp;
313 	char	*job;
314 	int	mustbejob;
315 {
316 	struct job *jp, *njp;
317 	int i;
318 
319 	if (*job != '%')
320 		jp = pgid2job(stoi((unsigned char *)job));
321 	else if (*++job == 0 || *job == '+' || *job == '%' || *job == '-') {
322 		jp = jobcur;
323 		if (*job == '-' && jp)
324 			jp = jp->j_curp;
325 	} else if (*job >= '0' && *job <= '9') {
326 		i = stoi((unsigned char *)job);
327 		for (jp = joblst; jp && jp->j_jid != i; jp = jp->j_nxtp)
328 			/* LINTED */
329 			;
330 	} else if (*job == '?') {
331 		int j;
332 		char *p;
333 		i = strlen(++job);
334 		jp = 0;
335 		for (njp = jobcur; njp; njp = njp->j_curp) {
336 			if (njp->j_jid == 0)
337 				continue;
338 			for (p = njp->j_cmd, j = strlen(p); j >= i; p++, j--) {
339 				if (strncmp(job, p, i) == 0) {
340 					if (jp != 0) {
341 						Failure((unsigned char *)cmdp,
342 						    ambiguous);
343 						return ((struct job *)0);
344 					}
345 					jp = njp;
346 					break;
347 				}
348 			}
349 		}
350 	} else {
351 		i = strlen(job);
352 		jp = 0;
353 		for (njp = jobcur; njp; njp = njp->j_curp) {
354 			if (njp->j_jid == 0)
355 				continue;
356 			if (strncmp(job, njp->j_cmd, i) == 0) {
357 				if (jp != 0) {
358 					Failure((unsigned char *)cmdp,
359 							ambiguous);
360 					return ((struct job *)0);
361 				}
362 				jp = njp;
363 			}
364 		}
365 	}
366 
367 	if (mustbejob && (jp == 0 || jp->j_jid == 0)) {
368 		Failure((unsigned char *)cmdp, nosuchjob);
369 		return ((struct job *)0);
370 	}
371 	return (jp);
372 }
373 
374 #ifdef	DO_DOT_SH_PARAMS
375 char *
code2str(code)376 code2str(code)
377 	int	code;
378 {
379 	int	i;
380 
381 	for (i = 0; i < CODENAMESIZE; i++) {
382 		if (code == _codename[i].c_code)
383 			return (_codename[i].c_name);
384 	}
385 	return ("UNKNOWN");
386 }
387 #endif
388 
389 static void
freejob(jp)390 freejob(jp)
391 	struct job	*jp;
392 {
393 	struct job **njp;
394 	struct job **cjp;
395 
396 	for (njp = &joblst; *njp && *njp != jp; njp = &(*njp)->j_nxtp)
397 		/* LINTED */
398 		;
399 
400 	for (cjp = &jobcur; *cjp && *cjp != jp; cjp = &(*cjp)->j_curp)
401 		/* LINTED */
402 		;
403 
404 	*njp = jp->j_nxtp;
405 	*cjp = jp->j_curp;
406 	free(jp);
407 	if (jp == thisjob)
408 		thisjob = NULL;
409 	jobcnt--;
410 	jobdone--;
411 }
412 
413 /*
414  * Collect the foreground job.
415  * Used in the case where the subshell wants
416  * to exit, but needs to wait until the fg job
417  * is done.
418  */
419 void
collect_fg_job()420 collect_fg_job()
421 {
422 	struct job	*jp;
423 	int		err;
424 	siginfo_t	si;
425 
426 	for (jp = joblst; jp; jp = jp->j_nxtp)
427 		if (jp->j_flag & J_FOREGND)
428 			break;
429 
430 	if (!jp)
431 		/* no foreground job */
432 		return;
433 
434 	/*
435 	 * Wait on fg job until wait succeeds
436 	 * or it fails due to no waitable children.
437 	 */
438 
439 	/* CONSTCOND */
440 	while (1) {
441 		errno = 0;
442 		si.si_pid = 0;
443 		err = waitid(P_PID, jp->j_pid, &si, (WEXITED|WTRAPPED));
444 #ifdef	DO_TRAP_FROM_WAITID
445 		checksigs(&si);			/* fault() with jobcontrol */
446 #endif
447 		if (si.si_pid == jp->j_pid || (err == -1 && errno == ECHILD))
448 			break;
449 	}
450 }
451 
452 /*
453  * analyze the status of a job
454  *
455  * On platforms with an incomplete and buggy waitid()/waitpid() implementation
456  * like Linux, we pass the process group id of the process, we did wait for in
457  * the parameter "fg". This value has been obtained before waitid() was called.
458  * Since WNOWAIT does not work and as a result, the related process no longer
459  * exists, we cannot call getpgid() here anymore.
460  */
461 static int
statjob(jp,si,fg,rc)462 statjob(jp, si, fg, rc)
463 	struct job	*jp;	/* Job pointer for this job	    */
464 	siginfo_t	*si;	/* Siginfo for the child to stat    */
465 	pid_t		fg;	/* Whether this is a foreground job */
466 	int		rc;	/* Whether to set "exitcode"	    */
467 {
468 	int	code = si->si_code;
469 	pid_t tgid;
470 	int jdone = 0;
471 
472 	jp->j_xcode = code;
473 	if (code == CLD_CONTINUED) {
474 		if (jp->j_flag & J_STOPPED) {
475 			jp->j_flag &= ~(J_STOPPED|J_SIGNALED|J_SAVETTY);
476 			jp->j_flag |= J_RUNNING;
477 			if (!fg && jp->j_jid) {
478 				jp->j_flag |= J_NOTIFY;
479 				jobnote++;
480 			}
481 		}
482 	} else if (code == CLD_STOPPED || code == CLD_TRAPPED) {
483 		jp->j_xval = si->si_status;		/* Stopsig */
484 		jp->j_flag &= ~J_RUNNING;
485 		jp->j_flag |= (J_SIGNALED|J_STOPPED);
486 		jp->j_pgid = getpgid(jp->j_pid);
487 		jp->j_tgid = jp->j_pgid;
488 		if (fg) {
489 			if ((tgid = settgid(mypgid, jp->j_pgid)) != 0)
490 				jp->j_tgid = tgid;
491 			else {
492 				int	fd = STDIN_FILENO;
493 
494 				jp->j_flag |= J_SAVETTY;
495 				if (tcgetattr(fd, &jp->j_stty) < 0 &&
496 				    jobfd > 0 && !isatty(fd)) {
497 					tcgetattr(fd = jobfd, &jp->j_stty);
498 				}
499 				(void) tcsetattr(fd, TCSANOW, &mystty);
500 			}
501 		}
502 		if (jp->j_jid) {
503 			jp->j_flag |= J_NOTIFY;
504 			jobnote++;
505 		}
506 	} else {
507 		jp->j_flag &= ~J_RUNNING;
508 		jp->j_flag |= J_DONE;
509 		jdone++;
510 		jobdone++;
511 		if (code == CLD_KILLED || code == CLD_DUMPED) {
512 			jp->j_xval = si->si_status;	/* Termsig */
513 			jp->j_flag |= J_SIGNALED;
514 			if (code == CLD_DUMPED)
515 				jp->j_flag |= J_DUMPED;
516 			if (!fg || jp->j_xval != SIGINT) {
517 				jp->j_flag |= J_NOTIFY;
518 				jobnote++;
519 			}
520 		} else { /* CLD_EXITED */
521 			jp->j_xval = si->si_status;	/* Exit status */
522 			jp->j_flag &= ~J_SIGNALED;
523 			if (!fg && jp->j_jid) {
524 				jp->j_flag |= J_NOTIFY;
525 				jobnote++;
526 			}
527 #ifdef	DO_DOL_SLASH
528 			if (jp->j_xval == ERR_NOTFOUND &&
529 			    *excausep == C_NOTFOUND) {
530 				jp->j_xcode = C_NOTFOUND;
531 				*excausep = 0;
532 			}
533 			if (jp->j_xval == ERR_NOEXEC &&
534 			    *excausep == C_NOEXEC) {
535 				jp->j_xcode = C_NOEXEC;
536 				*excausep = 0;
537 			}
538 #endif
539 		}
540 		if (fg) {
541 			pid_t	jgid = getpgid(jp->j_pid);
542 
543 #if	WNOWAIT == 0	/* Hack for Linux et al */
544 			if (jgid == (pid_t)-1 && fg != (pid_t)-1)
545 				jgid = fg;
546 #endif
547 			/*
548 			 * The previous hack was to use "svpgid" in case that
549 			 * "jgid" was -1. This turned out to give problems with
550 			 *   dosh 'nroff -u1 -Tlp -man $@ | col -x' | more
551 			 * but it turned out that "mypgid" was a better
552 			 * approximation. Since we now get the value from "fg",
553 			 * we go back to the original implementation for the
554 			 * second settgid() call.
555 			 */
556 			if (!settgid(mypgid, jp->j_pgid) ||
557 			    !settgid(mypgid, jgid)) {
558 				int	fd = STDIN_FILENO;
559 
560 				if (tcgetattr(fd, &mystty) < 0 &&
561 				    jobfd > 0 && !isatty(fd))
562 					tcgetattr(jobfd, &mystty);
563 			}
564 		}
565 	}
566 	if (rc) {
567 		/*
568 		 * First check whether we have a prefilled exit code
569 		 * from a previous vfork()d child that matches this child.
570 		 */
571 		if (ex.ex_code < C_NOEXEC || ex.ex_pid != si->si_pid) {
572 			ex.ex_status = exitval = jp->j_xval;
573 			ex.ex_code = jp->j_xcode;
574 			ex.ex_pid = si->si_pid;
575 		}
576 #ifdef	SIGCHLD
577 		ex.ex_signo = SIGCHLD;
578 #else
579 		ex.ex_signo = 1000;	/* Need to distinct this from builtin */
580 #endif
581 		jp->j_xsig = ex.ex_signo;
582 
583 		if ((flags2 & fullexitcodeflg) == 0)
584 			exitval &= 0xFF; /* As dumb as with historic wait */
585 		if (jp->j_flag & J_SIGNALED)
586 			exitval |= SIGFLG;
587 #ifdef	DO_EXIT_MODFIX
588 		else if (ex.ex_status != 0 && exitval == 0)
589 			exitval = SIGFLG; /* Use special value 128 */
590 #endif
591 		exitset();		/* Set retval from exitval for $? */
592 	}
593 	if (jdone && !(jp->j_flag & J_NOTIFY))
594 		freejob(jp);
595 	return (jdone);
596 }
597 
598 /*
599  * collect the status of jobs that have recently exited or stopped -
600  * if wnohang == WNOHANG, wait until error, or all jobs are accounted for;
601  *
602  * called after each command is executed, with wnohang == 0, and as part
603  * of "wait" builtin with wnohang == WNOHANG
604  *
605  * We do not need to call chktrap here if waitpid(2) is called with
606  * wnohang == 0, because that only happens from syswait() which is called
607  * from builtin() where chktrap() is already called.
608  */
609 static void
collectjobs(wnohang)610 collectjobs(wnohang)
611 	int		wnohang;
612 {
613 	pid_t		pid;
614 	struct job	*jp;
615 	int		n;
616 	siginfo_t	si;
617 	int		wflags;
618 
619 	if ((flags & (monitorflg|jcflg|jcoff)) == (monitorflg|jcflg))
620 		wflags = WSTOPPED|WCONTINUED;
621 	else
622 		wflags = 0;
623 	wflags |= (WEXITED|WTRAPPED);	/* Needed for waitid() */
624 
625 	for (n = jobcnt - jobdone; n > 0; n--) {
626 		if (waitid(P_ALL, 0, &si, wnohang|wflags) < 0)
627 			break;
628 #ifdef	DO_TRAP_FROM_WAITID
629 		checksigs(&si);			/* fault() with jobcontrol */
630 #endif
631 		pid = si.si_pid;
632 		if (pid == 0)
633 			break;
634 		if ((jp = pgid2job(pid)) != NULL)
635 			(void) statjob(jp, &si, 0, 0);
636 	}
637 }
638 
639 void
freejobs()640 freejobs()
641 {
642 	struct job *jp;
643 
644 	collectjobs(WNOHANG);
645 
646 	if (jobnote) {
647 		int save_fd = setb(STDERR_FILENO);
648 		for (jp = joblst; jp; jp = jp->j_nxtp) {
649 			if (jp->j_flag & J_NOTIFY) {
650 				if (jp->j_jid)
651 					printjob(jp, PR_DFL);
652 				else if (jp->j_flag & J_FOREGND)
653 					printjob(jp, PR_STAT);
654 				else
655 					printjob(jp, PR_STAT|PR_PGID);
656 			}
657 		}
658 		(void) setb(save_fd);
659 	}
660 
661 	if (jobdone) {
662 		struct job *sjp;
663 
664 		for (jp = joblst; jp; jp = sjp) {
665 			sjp = jp->j_nxtp;
666 #ifdef	DO_POSIX_WAIT
667 			if ((jp->j_flag & (J_DONE|J_REPORTED)) ==
668 			    (J_DONE|J_REPORTED))
669 				freejob(jp);
670 #else
671 			if (jp->j_flag & J_DONE)
672 				freejob(jp);
673 #endif
674 		}
675 	}
676 }
677 
678 /*
679  * Always called for a foreground job.
680  */
681 static void
waitjob(jp)682 waitjob(jp)
683 	struct job	*jp;
684 {
685 	siginfo_t	si;
686 	int		jdone;
687 	pid_t		pid = jp->j_pid;
688 	int		wflags;
689 	int		ret = 0;
690 	int		err = 0;
691 #ifdef	DO_TIME
692 	struct job	j;
693 #endif
694 #if	WNOWAIT == 0	/* This is AIX, Linux, Mac OS X or NetBSD.	*/
695 	pid_t   jgid;	/* Needed because waitid() always reaps child	*/
696 #endif			/* on the incomplete implementation there.	*/
697 
698 #ifdef	DO_TIME
699 	ruget(&jp->j_rustart);
700 #endif
701 
702 	if ((flags & (monitorflg|jcflg|jcoff)) == (monitorflg|jcflg))
703 		wflags = WSTOPPED;
704 	else
705 		wflags = 0;
706 	wflags |= (WEXITED|WTRAPPED);	/* Needed for waitid() */
707 #if	WNOWAIT == 0
708 	jgid = getpgid(pid);		/* Get it now, we can't do it later */
709 #endif
710 	do {
711 		errno = 0;
712 		ret = waitid(P_PID, pid, &si, wflags|WNOWAIT);
713 		err = errno;
714 		if (ret == -1 && err == ECHILD) { /* No children */
715 			si.si_status = 0;
716 			si.si_code = 0;
717 			si.si_pid = 0;
718 			break;
719 		}
720 		/*
721 		 * si.si_pid == 0: no status is available for pid
722 		 */
723 
724 #ifdef	DO_TRAP_FROM_WAITID
725 		checksigs(&si);			/* fault() with jobcontrol */
726 #endif
727 	} while (si.si_pid != pid);
728 
729 #if	WNOWAIT != 0
730 	/*
731 	 * On a complete waitid() implementation, we have WNOWAIT and thus are
732 	 * able to get the real process group for pid as the process still
733 	 * exists. Other systems may not have set the final process group of
734 	 * this pid before we start to waid and after the wait, the process
735 	 * cannot be retrieved anymore as it was already removed.
736 	 * To be always able to retrieve the progcess group for pid, we need
737 	 * to call statjob() here.
738 	 */
739 #ifdef	DO_TIME
740 	j = *jp;
741 #endif
742 	jdone = statjob(jp, &si, 1, 1);		/* Sets exitval, see below */
743 	/*
744 	 * Avoid hang on FreeBSD, so wait/reap here only for died children.
745 	 */
746 	if (si.si_code != CLD_STOPPED && si.si_code != CLD_TRAPPED) {
747 		siginfo_t	si2;
748 
749 		waitid(P_PID, pid, &si2, wflags);
750 #ifdef	__needed__				/* Only on real SVr4 */
751 						/* or on our emulation */
752 						/* FreeBSD misses si_utime */
753 		si.si_utime = si2.si_utime;
754 		si.si_stime = si2.si_stime;
755 #endif
756 	}
757 #else	/* WNOWAIT == 0 */
758 	/*
759 	 * Inclomplete waitid() implementation (e.g. Linux). We may fail
760 	 * to get the right process group for pid and fail to restore
761 	 * our process group in the terninal.
762 	 */
763 #ifdef	DO_TIME
764 	j = *jp;
765 #endif
766 	jdone = statjob(jp, &si, jgid, 1);	/* Sets exitval, see below */
767 #endif	/* WNOWAIT != 0 */
768 
769 #ifdef	DO_PIPE_PARENT
770 	/*
771 	 * This is a hack for now as long as we don't have a node for every
772 	 * process created by the main shell. We currently don't know whether
773 	 * we may call waitid() without WNOHANG. Currently we may miss a
774 	 * process for every pipeline we create and catch it only with the
775 	 * next foreground command.
776 	 */
777 	/* CONSTCOND */
778 	while (1) {
779 		errno = 0;
780 		si.si_pid = 0;
781 		err = waitid(P_ALL, 0, &si, wflags|WCONTINUED|WNOHANG);
782 		if (si.si_pid == 0 || (err == -1 && errno == ECHILD))
783 			break;
784 #ifdef	DO_TRAP_FROM_WAITID
785 		checksigs(&si);			/* fault() with jobcontrol */
786 #endif
787 		if ((jp = pgid2job(si.si_pid)) != NULL)
788 			(void) statjob(jp, &si, 0, 0);
789 	}
790 #endif
791 
792 #ifdef	DO_TIME
793 	/*
794 	 * Currently, jp is free()d by statjob() and we need to use a copy.
795 	 * This may change once we introduce an own process node for every
796 	 * process from a pipe created with DO_PIPE_PARENT.
797 	 */
798 	if ((flags2 & (timeflg | systime)) == timeflg)
799 		prtime(&j);
800 #endif
801 
802 	if (jdone && exitval && (flags & errflg))
803 		exitsh(exitval);
804 	flags |= eflag;
805 }
806 
807 /*
808  * modify the foreground process group to *new* only if the
809  * current foreground process group is equal to *expected*
810  */
811 int
settgid(new,expected)812 settgid(new, expected)
813 	pid_t	new;
814 	pid_t	expected;
815 {
816 	int	fd = STDIN_FILENO;
817 	pid_t	current = tcgetpgrp(fd);
818 
819 #ifdef	JOB_DEBUG
820 	fprintf(stderr, "settgid(new %ld, expected %ld) current %ld\n",
821 		(long)new, (long)expected, (long)current);
822 #endif
823 	/*
824 	 * "current" may be -1 in case that STDIN_FILENO was a renamed pipe,
825 	 * and errno in this case will be ENOTTY or EINVAL.
826 	 * Try to use the moved stdin in this case.
827 	 */
828 	if (current == (pid_t)-1 && jobfd > 0 && !isatty(fd))
829 		current = tcgetpgrp(fd = jobfd);
830 
831 	/*
832 	 * Another case is when tcgetpgrp() worked but returned a different id
833 	 * than expected. Do not try to call tcsetpgrp() in any of the cases.
834 	 */
835 	if (current != expected) {
836 		/*
837 		 * POSIX says: tcgetpgrp() returns a nonexisting process group
838 		 * id when no foreground process group was set up.
839 		 *
840 		 * Some older Linux versions (e.g. 2.6.18) return a nonexisting
841 		 * pgrp in case no process from the expected process group
842 		 * exists anymore. If no process with the returned process group
843 		 * exists, pretend success - otherwise return (current).
844 		 */
845 		errno = 0;
846 		if (current == (pid_t)-1 ||
847 		    kill(-current, 0) >= 0 || errno != ESRCH)
848 			return (current);
849 	}
850 
851 	if (new != current)
852 		tcsetpgrp(fd, new);
853 
854 	return (0);
855 }
856 
857 static void
restartjob(jp,fg)858 restartjob(jp, fg)
859 	struct job	*jp;
860 	int		fg;
861 {
862 	if (jp == NULL)
863 		return;
864 	if (jp != jobcur) {
865 		struct job *t;
866 		for (t = jobcur; t->j_curp != jp; t = t->j_curp)
867 			/* LINTED */
868 			;
869 		t->j_curp = jp->j_curp;
870 		jp->j_curp = jobcur;
871 		jobcur = jp;
872 	}
873 	if (fg) {
874 		if (jp->j_flag & J_SAVETTY) {
875 			jp->j_stty.c_lflag &= ~TOSTOP;
876 			jp->j_stty.c_lflag |= (mystty.c_lflag&TOSTOP);
877 			jp->j_stty.c_cc[VSUSP] = mystty.c_cc[VSUSP];
878 #ifdef	VDSUSP
879 			jp->j_stty.c_cc[VDSUSP] = mystty.c_cc[VDSUSP];
880 #endif
881 			(void) tcsetattr(STDIN_FILENO, TCSADRAIN, &jp->j_stty);
882 		}
883 		(void) settgid(jp->j_tgid, mypgid);
884 	}
885 	/*
886 	 * First explicitly continue the foreground process as we otherwise may
887 	 * get a CLD_STOPPED message from waitid() in case of a longer pipeline
888 	 * where it may take some time to wakeup all processes from a group.
889 	 */
890 #ifdef	SIGCONT
891 #ifdef	DO_POSIX_WAIT
892 	if (lastthisjob)
893 		(void) kill(lastthisjob->j_pid, SIGCONT);
894 	else if (thisjob)
895 #endif
896 		(void) kill(thisjob->j_pid, SIGCONT);
897 	(void) kill(-(jp->j_pgid), SIGCONT);
898 	if (jp->j_tgid != jp->j_pgid)
899 		(void) kill(-(jp->j_tgid), SIGCONT);
900 #endif
901 	jp->j_flag &= ~(J_STOPPED|J_SIGNALED|J_SAVETTY);
902 	jp->j_flag |= J_RUNNING;
903 	if (fg)  {
904 		jp->j_flag |= J_FOREGND;
905 		printjob(jp, PR_JID|PR_CMD);
906 		waitjob(jp);
907 	} else {
908 		jp->j_flag &= ~J_FOREGND;
909 		printjob(jp, PR_JID|PR_CMD|PR_AMP);
910 	}
911 }
912 
913 static void
printjob(jp,propts)914 printjob(jp, propts)
915 	struct job	*jp;
916 	int		propts;
917 {
918 	int sp = 0;
919 
920 	if (jp == NULL)
921 		return;
922 	if (jp->j_flag & J_NOTIFY) {
923 		jobnote--;
924 		jp->j_flag &= ~J_NOTIFY;
925 	}
926 
927 	if (propts & PR_JID) {
928 		prc_buff('[');
929 		prn_buff(jp->j_jid);
930 		prc_buff(']');
931 		sp = 1;
932 	}
933 
934 	if (propts & PR_CUR) {
935 		while (sp-- > 0)
936 			prc_buff(SPACE);
937 		sp = 1;
938 		if (jobcur == jp)
939 			prc_buff('+');
940 		else if (jobcur != 0 && jobcur->j_curp == jp)
941 			prc_buff('-');
942 		else
943 			sp++;
944 	}
945 
946 	if (propts & PR_PGID) {
947 		while (sp-- > 0)
948 			prc_buff(SPACE);
949 		prn_buff(jp->j_pgid);
950 		sp = 1;
951 	}
952 
953 	if (propts & PR_STAT) {
954 		const char	*gmsg;
955 		while (sp-- > 0)
956 			prc_buff(SPACE);
957 		sp = 28;
958 		if (jp->j_flag & J_SIGNALED) {
959 			const char	*sigstr;
960 
961 			if ((sigstr = strsignal(jp->j_xval)) != NULL) {
962 				sp -= strlen(sigstr);
963 				prs_buff((unsigned char *)sigstr);
964 			} else {
965 				sitos(jp->j_xval);
966 				gmsg = gettext(signalnum);
967 				sp -= strlen((char *)numbuf) + strlen(gmsg);
968 				prs_buff((unsigned char *)gmsg);
969 				prs_buff(numbuf);
970 			}
971 			if (jp->j_flag & J_DUMPED) {
972 				gmsg = gettext(coredump);
973 				sp -= strlen(gmsg);
974 				prs_buff((unsigned char *)gmsg);
975 			}
976 		} else if (jp->j_flag & J_DONE) {
977 			sitos(jp->j_xval);
978 			gmsg = gettext(exited);
979 			sp -= strlen(gmsg) + strlen((char *)numbuf) + 2;
980 			prs_buff((unsigned char *)gmsg);
981 			prc_buff('(');
982 			sitos(jp->j_xval);
983 			prs_buff(numbuf);
984 			prc_buff(')');
985 		} else {
986 			gmsg = gettext(running);
987 			sp -= strlen(gmsg);
988 			prs_buff((unsigned char *)gmsg);
989 		}
990 		if (sp < 1)
991 			sp = 1;
992 	}
993 
994 	if (propts & PR_CMD) {
995 		while (sp-- > 0)
996 			prc_buff(SPACE);
997 		prs_buff((unsigned char *)jp->j_cmd);
998 		sp = 1;
999 	}
1000 
1001 	if (propts & PR_AMP) {
1002 		while (sp-- > 0)
1003 			prc_buff(SPACE);
1004 		prc_buff('&');
1005 		sp = 1;
1006 	}
1007 
1008 	if (propts & PR_PWD) {
1009 		while (sp-- > 0)
1010 			prc_buff(SPACE);
1011 		prs_buff((unsigned char *)"(wd: ");
1012 		prs_buff((unsigned char *)jp->j_pwd);
1013 		prc_buff(')');
1014 	}
1015 
1016 	prc_buff(NL);
1017 	flushb();
1018 }
1019 
1020 /*
1021  * called to initialize job control for each new input file to the shell,
1022  * and after the "exec" builtin
1023  */
1024 void
startjobs()1025 startjobs()
1026 {
1027 	svpgid = mypgid;
1028 
1029 	if (tcgetattr(STDIN_FILENO, &mystty) == -1 ||
1030 	    (svtgid = tcgetpgrp(STDIN_FILENO)) == -1) {
1031 		flags &= ~jcflg;
1032 		return;
1033 	}
1034 
1035 	flags |= jcflg;
1036 
1037 #ifdef	SIGTTOU
1038 	handle(SIGTTOU, SIG_IGN);
1039 #endif
1040 #ifdef	SIGTSTP
1041 	handle(SIGTSTP, SIG_DFL);
1042 #endif
1043 
1044 	if (mysid != mypgid) {
1045 		setpgid(0, 0);		/* Make me a process group leader */
1046 		mypgid = mypid;		/* and remember my new pgid	  */
1047 		(void) settgid(mypgid, svpgid);	/* and set up my tty pgrp */
1048 	}
1049 }
1050 
1051 int
endjobs(check_if)1052 endjobs(check_if)
1053 	int	check_if;
1054 {
1055 	if ((flags & (jcoff|jcflg)) != jcflg)
1056 		return (1);
1057 
1058 	if (check_if && jobcnt && eofflg++ == 0) {
1059 		struct job *jp;
1060 		if (check_if & JOB_STOPPED) {
1061 			for (jp = joblst; jp; jp = jp->j_nxtp) {
1062 				if (jp->j_jid && (jp->j_flag & J_STOPPED)) {
1063 					prs(_gettext(jobsstopped));
1064 					prc(NL);
1065 					return (0);
1066 				}
1067 			}
1068 		}
1069 		if (check_if & JOB_RUNNING) {
1070 			for (jp = joblst; jp; jp = jp->j_nxtp) {
1071 				if (jp->j_jid && (jp->j_flag & J_RUNNING)) {
1072 					prs(_gettext(jobsrunning));
1073 					prc(NL);
1074 					return (0);
1075 				}
1076 			}
1077 		}
1078 	}
1079 
1080 	if (svpgid != mypgid) {
1081 		(void) settgid(svtgid, mypgid);
1082 		setpgid(0, svpgid);
1083 	}
1084 
1085 	return (1);
1086 }
1087 
1088 /*
1089  * Called by the shell to destroy a job slot from allocjob() if spawn failed.
1090  * We need to check whether we really need to have the jp parameter for
1091  * timing of builtin commands.
1092  */
1093 void
deallocjob(jp)1094 deallocjob(jp)
1095 	struct job	*jp;
1096 {
1097 	if (jp == NULL)
1098 		jp = thisjob;
1099 	free(jp);
1100 	if (jp == thisjob)
1101 		thisjob = NULL;
1102 	jobcnt--;
1103 }
1104 
1105 void
clearcurjob()1106 clearcurjob()
1107 {
1108 #ifdef	DO_POSIX_WAIT
1109 	lastthisjob = thisjob;		/* remember this for fg(1) command */
1110 	thisjob = NULL;
1111 #endif
1112 }
1113 
1114 #ifdef	DO_PIPE_PARENT
1115 void *
curjob()1116 curjob()
1117 {
1118 	return (thisjob);
1119 }
1120 
1121 /*
1122  * Return current process group id.
1123  */
1124 pid_t
curpgid()1125 curpgid()
1126 {
1127 	if (!thisjob)
1128 		return (0);
1129 	return (thisjob->j_pgid);
1130 }
1131 
1132 /*
1133  * Set up "pgid" as process group id in case this has not been done already.
1134  */
1135 void
setjobpgid(pgid)1136 setjobpgid(pgid)
1137 	pid_t	pgid;
1138 {
1139 	if (!thisjob)
1140 		return;
1141 	if (thisjob->j_jid) {
1142 		thisjob->j_pgid = pgid;
1143 	} else {
1144 		thisjob->j_pgid = mypgid;
1145 	}
1146 }
1147 
1148 void
setjobfd(fd,sfd)1149 setjobfd(fd, sfd)
1150 	int	fd;
1151 	int	sfd;
1152 {
1153 	jobfd = fd;
1154 	jobsfd = sfd;
1155 }
1156 
1157 void
resetjobfd()1158 resetjobfd()
1159 {
1160 	/*
1161 	 * Restore stdin in case it was moved away.
1162 	 */
1163 	if (jobfd > 0) {
1164 		restore(jobsfd);
1165 		jobsfd = jobfd = 0;
1166 	}
1167 }
1168 #endif	/* DO_PIPE_PARENT */
1169 
1170 /*
1171  * Called by the shell to reserve a job slot for a job about to be spawned.
1172  * Resulting job slot is in "thisjob".
1173  */
1174 void
allocjob(cmdp,cwdp,monitor)1175 allocjob(cmdp, cwdp, monitor)
1176 	char		*cmdp;
1177 	unsigned char	*cwdp;
1178 	int		monitor;
1179 {
1180 	struct job *jp, **jpp;
1181 	int jid, cmdlen, cwdlen;
1182 
1183 	cmdlen = strlen(cmdp) + 1;
1184 	if (cmdlen > 1 && cmdp[cmdlen-2] == '&') {
1185 		cmdp[cmdlen-3] = 0;
1186 		cmdlen -= 2;
1187 	}
1188 	cwdlen = strlen((char *)cwdp) + 1;
1189 	jp = (struct job *) alloc(sizeof (struct job) + cmdlen + cwdlen);
1190 	if (jp == 0)
1191 		error(nostack);
1192 	jobcnt++;
1193 	jp->j_cmd = ((char *)jp) + sizeof (struct job);
1194 	strcpy(jp->j_cmd, cmdp);
1195 	jp->j_pwd = jp->j_cmd + cmdlen;
1196 	strcpy(jp->j_pwd, (char *)cwdp);
1197 	jp->j_nxtp = jp->j_curp = NULL;
1198 	jp->j_flag = 0;
1199 	jp->j_pid = jp->j_pgid = jp->j_tgid = 0;
1200 	jp->j_xval = 0;
1201 	jp->j_xcode = 0;
1202 	jp->j_xsig = 0;
1203 
1204 	jpp = &joblst;
1205 
1206 	if (monitor) {
1207 		/*
1208 		 * First skip all jobs without job id.
1209 		 */
1210 		for (; *jpp; jpp = &(*jpp)->j_nxtp)
1211 			if ((*jpp)->j_jid != 0)
1212 				break;
1213 		/*
1214 		 * Now find the end of the job list or the first
1215 		 * location where the job numbers are no longer
1216 		 * contiguous.
1217 		 */
1218 		for (jid = 1; *jpp; jpp = &(*jpp)->j_nxtp, jid++)
1219 			if ((*jpp)->j_jid != jid)
1220 				break;
1221 	} else
1222 		jid = 0;
1223 
1224 	jp->j_jid = jid;
1225 	nextjob = jpp;	/* Remember where to insert this job via postjob() */
1226 	thisjob = jp;	/* This job is going to be inserted by postjob()   */
1227 }
1228 
1229 void
clearjobs()1230 clearjobs()
1231 {
1232 	struct job *jp, *sjp;
1233 
1234 	for (jp = joblst; jp; jp = sjp) {
1235 		sjp = jp->j_nxtp;
1236 #ifdef	DO_POSIX_WAIT
1237 		if ((jp->j_flag & (J_DONE|J_REPORTED)) ==
1238 		    (J_DONE|J_REPORTED))
1239 #endif
1240 			free(jp);
1241 	}
1242 	joblst = NULL;
1243 	jobcnt = 0;
1244 	jobnote = 0;
1245 	jobdone = 0;
1246 }
1247 
1248 void
makejob(monitor,fg)1249 makejob(monitor, fg)
1250 	int	monitor;
1251 	int	fg;
1252 {
1253 	if (monitor) {
1254 #ifndef	DO_PIPE_PARENT
1255 		mypgid = mypid;
1256 		setpgid(0, 0);
1257 		if (fg)
1258 			tcsetpgrp(STDIN_FILENO, mypid);
1259 #endif
1260 #ifdef	SIGTTOU
1261 		handle(SIGTTOU, SIG_DFL);
1262 #endif
1263 #ifdef	SIGTSTP
1264 		handle(SIGTSTP, SIG_DFL);
1265 #endif
1266 	} else if (!fg) {
1267 #ifdef	HAVE_NICE
1268 #ifdef	DO_BGNICE
1269 		if (flags2 & bgniceflg)
1270 			nice(5);
1271 #else
1272 #ifdef NICE
1273 		nice(NICE);
1274 #endif
1275 #endif
1276 #endif
1277 #ifdef	SIGTTIN
1278 		handle(SIGTTIN, SIG_IGN);
1279 #endif
1280 		handle(SIGINT,  SIG_IGN);
1281 		handle(SIGQUIT, SIG_IGN);
1282 		if (!ioset)
1283 			renamef(chkopen((unsigned char *)devnull, O_RDONLY),
1284 					STDIN_FILENO);
1285 	}
1286 }
1287 
1288 /*
1289  * called by the shell after job has been spawned, to fill in the
1290  * job slot, and wait for the job if in the foreground
1291  */
1292 struct job *
postjob(pid,fg,blt)1293 postjob(pid, fg, blt)
1294 	pid_t	pid;	/* The pid of the new job			*/
1295 	int	fg;	/* Whether this is a foreground job		*/
1296 	int	blt;	/* Whether this is a temp slot for a builtin	*/
1297 {
1298 	int propts;
1299 
1300 	if (!blt) {	/* Do not connect slots for builtin commands	*/
1301 		if (*nextjob != joblst)		/* Avoid joblst loop */
1302 			thisjob->j_nxtp = *nextjob;
1303 		*nextjob = thisjob;
1304 		thisjob->j_curp = jobcur;
1305 		jobcur = thisjob;
1306 	}
1307 
1308 	/*
1309 	 * In case of the historic pipe setup, the rightmost program in a pipe
1310 	 * was the process group leader and it's pid was equal to j_pgid.
1311 	 * With the new optimized pipe setup where the shell is the parent
1312 	 * of all pipe processes, the process group leader is the leftmost
1313 	 * program in a pipe. postjob() hoewver is called for the rightmost
1314 	 * program as we wait for it.
1315 	 * We thus are not allowed to overwrite j_pgid in the latter case after
1316 	 * it has been set up for the process group leader via setjobpgid().
1317 	 */
1318 	if (thisjob->j_jid) {
1319 		if (thisjob->j_pgid == 0)
1320 			thisjob->j_pgid = pid;
1321 		propts = PR_JID|PR_PGID;
1322 	} else {
1323 		if (thisjob->j_pgid == 0)
1324 			thisjob->j_pgid = mypgid;
1325 		propts = PR_PGID;
1326 	}
1327 
1328 #ifdef	DO_TIME
1329 	gettimeofday(&thisjob->j_start, NULL);
1330 #endif
1331 	thisjob->j_flag = J_RUNNING;
1332 	thisjob->j_tgid = thisjob->j_pgid;
1333 	thisjob->j_pid = pid;
1334 	eofflg = 0;
1335 
1336 	if (fg) {
1337 		thisjob->j_flag |= J_FOREGND;
1338 		if (blt) {
1339 			thisjob->j_flag |= J_BLTIN;
1340 #ifdef	DO_TIME
1341 			ruget(&thisjob->j_rustart);
1342 #endif
1343 		} else {
1344 			waitjob(thisjob);
1345 		}
1346 	} else  {
1347 		if (flags & ttyflg)
1348 			printjob(thisjob, propts);
1349 		assnum(&pcsadr, (long)pid);
1350 	}
1351 	return (thisjob);
1352 }
1353 
1354 /*
1355  * the builtin "jobs" command
1356  */
1357 void
sysjobs(argc,argv)1358 sysjobs(argc, argv)
1359 	int		argc;
1360 	unsigned char	*argv[];
1361 {
1362 	unsigned char *cmdp = *argv;
1363 	struct job *jp;
1364 	int propts, c;
1365 	struct optv optv;
1366 
1367 	optinit(&optv);
1368 	propts = 0;
1369 
1370 	if ((flags & jcflg) == 0) {
1371 		Failure((unsigned char *)cmdp, nojc);
1372 		return;
1373 	}
1374 	while ((c = optget(argc, argv, &optv, "lpx")) != -1) {
1375 		if (propts) {
1376 			gfailure((unsigned char *)usage, jobsuse);
1377 			return;
1378 		}
1379 		switch (c) {
1380 			case 'x':
1381 				propts = -1;
1382 				break;
1383 			case 'p':
1384 				propts = PR_PGID;
1385 				break;
1386 			case 'l':
1387 				propts = PR_LONG;
1388 				break;
1389 			case '?':
1390 				gfailure((unsigned char *)usage, jobsuse);
1391 				return;
1392 		}
1393 	}
1394 
1395 	if (propts == -1) {
1396 		unsigned char *bp;
1397 		unsigned char *cp;
1398 		unsigned char *savebp;
1399 		for (savebp = bp = locstak(); optv.optind < argc;
1400 							optv.optind++) {
1401 			cp = argv[optv.optind];
1402 			if (*cp == '%') {
1403 				jp = str2job((char *)cmdp, (char *)cp, 1);
1404 				if (jp == NULL)
1405 					return;
1406 				itos(jp->j_pid);
1407 				cp = numbuf;
1408 			}
1409 			while (*cp) {
1410 				GROWSTAK(bp);
1411 				*bp++ = *cp++;
1412 			}
1413 			GROWSTAK(bp);
1414 			*bp++ = SPACE;
1415 		}
1416 		savebp = endstak(bp);
1417 		execexp(savebp, (Intptr_t)0, 0);
1418 		return;
1419 	}
1420 
1421 	collectjobs(WNOHANG);
1422 
1423 	if (propts == 0)
1424 		propts = PR_DFL;
1425 
1426 	if (optv.optind == argc) {
1427 		for (jp = joblst; jp; jp = jp->j_nxtp) {
1428 			if (jp->j_jid)
1429 				printjob(jp, propts);
1430 		}
1431 	} else do {
1432 		printjob(str2job(C cmdp, C argv[optv.optind++], 1), propts);
1433 	} while (optv.optind < argc);
1434 }
1435 
1436 /*
1437  * the builtin "fg" and "bg" commands
1438  */
1439 /* ARGSUSED */
1440 void
sysfgbg(argc,argv)1441 sysfgbg(argc, argv)
1442 	int	argc;
1443 	char	*argv[];
1444 {
1445 	char	*cmdp = *argv;
1446 	int	fg = eq("fg", cmdp);
1447 #ifdef	DO_GETOPT_UTILS
1448 	/*
1449 	 * optskip() is sufficient, even ksh93 only supports "fg -- -1234".
1450 	 * Bourne Shell did not need "--", nor support -1234.
1451 	 */
1452 	int	ind = optskip(argc, UCP argv, fg?"fg [job ...]":"bg [job ...]");
1453 
1454 	if (ind-- < 0)
1455 		return;
1456 	argc -= ind;
1457 	argv += ind;
1458 #endif
1459 	if ((flags & jcflg) == 0) {
1460 		Failure((unsigned char *)cmdp, nojc);
1461 		return;
1462 	}
1463 
1464 	if (*++argv == 0) {
1465 		struct job *jp;
1466 		for (jp = jobcur; ; jp = jp->j_curp) {
1467 			if (jp == 0) {
1468 				Failure((unsigned char *)cmdp, nocurjob);
1469 				return;
1470 			}
1471 			if (jp->j_jid)
1472 				break;
1473 		}
1474 		restartjob(jp, fg);
1475 	} else {
1476 		do {
1477 			restartjob(str2job(cmdp, *argv, 1), fg);
1478 		} while (*++argv);
1479 	}
1480 }
1481 
1482 /*
1483  * the builtin "wait" commands
1484  */
1485 void
syswait(argc,argv)1486 syswait(argc, argv)
1487 	int	argc;
1488 	char	*argv[];
1489 {
1490 	char		*cmdp = *argv;
1491 	struct job	*jp;
1492 	int		wflags;
1493 	siginfo_t	si;
1494 #ifdef	DO_GETOPT_UTILS
1495 	/*
1496 	 * optskip() is sufficient, even ksh93 only supports "wait -- -1234".
1497 	 * Bourne Shell did not need "--", nor support -1234.
1498 	 */
1499 	int	ind = optskip(argc, UCP argv, "wait [job ...]");
1500 
1501 	if (ind-- < 0)
1502 		return;
1503 	argc -= ind;
1504 	argv += ind;
1505 #endif
1506 
1507 	if ((flags & (monitorflg|jcflg|jcoff)) == (monitorflg|jcflg))
1508 		wflags = WSTOPPED;
1509 	else
1510 		wflags = 0;
1511 	wflags |= (WEXITED|WTRAPPED);	/* Needed for waitid() */
1512 
1513 	if (argc == 1) {
1514 		struct job *sjp;
1515 
1516 		collectjobs(0);
1517 
1518 		for (jp = joblst; jp; jp = sjp) {
1519 			sjp = jp->j_nxtp;
1520 
1521 			if (jp->j_flag & J_DONE)
1522 				jp->j_flag |= J_REPORTED;
1523 		}
1524 	} else while (--argc) {
1525 		if ((jp = str2job(cmdp, *++argv, 0)) == 0) {
1526 #ifdef	DO_POSIX_WAIT
1527 			exitval =
1528 			ex.ex_status =
1529 			ex.ex_code = ERR_NOTFOUND;
1530 			exitset();	/* Set retval from exitval for $? */
1531 #endif
1532 			continue;
1533 		}
1534 #ifdef	DO_POSIX_WAIT
1535 		if ((jp->j_flag & J_REPORTED))
1536 			continue;
1537 		if ((jp->j_flag & J_DONE)) {
1538 			ex.ex_status = exitval = jp->j_xval;
1539 			ex.ex_code = jp->j_xcode;
1540 			ex.ex_pid = jp->j_pid;
1541 			ex.ex_signo = jp->j_xsig;
1542 
1543 			if ((flags2 & fullexitcodeflg) == 0)
1544 				exitval &= 0xFF; /* As dumb as historic wait */
1545 			if (jp->j_flag & J_SIGNALED)
1546 				exitval |= SIGFLG;
1547 #ifdef	DO_EXIT_MODFIX
1548 			else if (ex.ex_status != 0 && exitval == 0)
1549 				exitval = SIGFLG; /* Use special value 128 */
1550 #endif
1551 			exitset();	/* Set retval from exitval for $? */
1552 
1553 			jp->j_flag |= J_REPORTED;
1554 			continue;
1555 		}
1556 #endif
1557 		if (!(jp->j_flag & J_RUNNING))
1558 			continue;
1559 		if (waitid(P_PID, jp->j_pid, &si, wflags) < 0)
1560 			break;
1561 #ifdef	DO_TRAP_FROM_WAITID
1562 		checksigs(&si);		/* fault() with jobcontrol */
1563 #endif
1564 		(void) statjob(jp, &si, 0, 1);
1565 		jp->j_flag |= J_REPORTED;
1566 	}
1567 }
1568 
1569 /*
1570  * Convert a job spec in "args" into a process id and send "sig".
1571  * A leading '%' marks job specifiers.
1572  * A leading '-' names a process group id instead of a pricess id.
1573  */
1574 static void
sigv(cmdp,sig,f,args)1575 sigv(cmdp, sig, f, args)
1576 	char	*cmdp;
1577 	int	sig;
1578 	int	f;
1579 	char	*args;
1580 {
1581 	int pgrp = 0;
1582 	int stopme = 0;
1583 	pid_t id;
1584 
1585 	if (*args == '%') {
1586 		struct job *jp;
1587 		jp = str2job(cmdp, args, 1);
1588 		if (jp == NULL)
1589 			return;
1590 		id = jp->j_pgid;
1591 		pgrp++;
1592 	} else {
1593 		if (*args == '-') {
1594 			pgrp++;
1595 			args++;
1596 		}
1597 		id = 0;
1598 		do {
1599 			if (*args < '0' || *args > '9') {
1600 				failure((unsigned char *)cmdp, badid);
1601 				return;
1602 			}
1603 			id = (id * 10) + (*args - '0');
1604 		} while (*++args);
1605 		if (id == 0) {
1606 			id = mypgid;
1607 			pgrp++;
1608 		}
1609 	}
1610 
1611 #ifdef	DO_SYSPGRP
1612 	if (f == F_PGRP) {
1613 		pid_t	pgid = getpgid(id);
1614 
1615 		if (pgid == (pid_t)-1) {
1616 			flushb();
1617 			failure((unsigned char *)cmdp, "cannot get pgid");
1618 		} else {
1619 			pid_t	sgrp = (pid_t)-1;
1620 
1621 #ifdef	HAVE_GETSID
1622 			sgrp = getsid(id);
1623 #endif
1624 			pr_pgrp(id, pgid, sgrp);
1625 		}
1626 		return;
1627 	}
1628 #endif
1629 
1630 #ifdef	SIGSTOP
1631 	if (sig == SIGSTOP) {
1632 		/*
1633 		 * If the id equals our session group id, this is the id
1634 		 * of the session group leader and thus the login shell.
1635 		 *
1636 		 * If the id equals our process id and our process group id
1637 		 * equals our session group id, we are the login shell.
1638 		 */
1639 		if (id == mysid || (id == mypid && mypgid == mysid)) {
1640 			failure((unsigned char *)cmdp, loginsh);
1641 			return;
1642 		}
1643 
1644 		/*
1645 		 * If the id equals our process group id and our process group
1646 		 * id differs from our saved process group id, we are not the
1647 		 * login shell, but need to restore the previous process
1648 		 * group id first.
1649 		 */
1650 		if (id == mypgid && mypgid != svpgid) {
1651 			(void) settgid(svtgid, mypgid);
1652 			setpgid(0, svpgid);
1653 			stopme++;
1654 			if (f == F_SUSPEND)	/* Called by the suspend cmd */
1655 				id = svpgid;	/* Stop our caller as well */
1656 		}
1657 	}
1658 #endif
1659 
1660 	if (pgrp || f == F_KILLPG) {
1661 		pgrp++;
1662 		id = -id;
1663 	}
1664 
1665 	if (kill(id, sig) < 0) {
1666 
1667 		switch (errno) {
1668 			case EPERM:
1669 				failure((unsigned char *)cmdp, eacces);
1670 				break;
1671 
1672 			case EINVAL:
1673 				failure((unsigned char *)cmdp, badsig);
1674 				break;
1675 
1676 			default:
1677 				if (pgrp) {
1678 					failure((unsigned char *)cmdp,
1679 							nosuchpgid);
1680 				} else {
1681 					failure((unsigned char *)cmdp,
1682 							nosuchpid);
1683 				}
1684 				break;
1685 		}
1686 
1687 #ifdef	SIGCONT
1688 	} else if (sig == SIGTERM && pgrp) {
1689 		(void) kill(id, SIGCONT);
1690 #endif
1691 	}
1692 
1693 	if (stopme) {
1694 		setpgid(0, mypgid);
1695 		(void) settgid(mypgid, svpgid);
1696 	}
1697 }
1698 
1699 void
sysstop(argc,argv)1700 sysstop(argc, argv)
1701 	int	argc;
1702 	char	*argv[];
1703 {
1704 	char *cmdp = *argv;
1705 #ifdef	DO_GETOPT_UTILS
1706 	int	ind = optskip(argc, UCP argv, stopuse);
1707 
1708 	if (ind-- < 0)
1709 		return;
1710 	argc -= ind;
1711 	argv += ind;
1712 #endif
1713 	if (argc <= 1) {
1714 		gfailure((unsigned char *)usage, stopuse);
1715 		return;
1716 	}
1717 #ifdef	SIGSTOP
1718 	while (*++argv)
1719 		sigv(cmdp, SIGSTOP, F_KILL, *argv);
1720 #endif
1721 }
1722 
1723 /*
1724  * List all signals on this platform
1725  */
1726 static void
listsigs()1727 listsigs()
1728 {
1729 	int i;
1730 	int maxtrap = MAX_SIG;	/* MAXTRAP includes traps like ERR */
1731 	int cnt = 0;
1732 	char sep = 0;
1733 #if	SIG2STR_MAX < 22
1734 #define	SIG_BLEN	22	/* Enough for 64 bits */
1735 #else
1736 #define	SIG_BLEN	SIG2STR_MAX
1737 #endif
1738 	char buf[SIG_BLEN]; /* Large enough for SIG* names, enough for num */
1739 
1740 #ifdef	SIGRTMAX
1741 	i = SIGRTMAX + 1;
1742 	if (i > maxtrap)
1743 		maxtrap = i;
1744 #endif
1745 	for (i = 1; i < maxtrap; i++) {
1746 		if (sig2str(i, buf) < 0) {
1747 			/*
1748 			 * The original code was just:
1749 			 *	continue;
1750 			 * but we would not realize that there may be gaps in
1751 			 * the list. So print the number, usable as kill arg.
1752 			 */
1753 			itos(i);
1754 			strcpy(buf, C numbuf);
1755 		}
1756 		if (sep)
1757 			prc_buff(sep);
1758 		prs_buff((unsigned char *)buf);
1759 		if ((flags & ttyflg) && (++cnt % 10))
1760 			sep = TAB;
1761 		else
1762 			sep = NL;
1763 	}
1764 	prc_buff(NL);
1765 }
1766 
1767 #if	defined(DO_KILL_L_SIG) || defined(DO_GETOPT_UTILS)
1768 static void
namesigs(argv)1769 namesigs(argv)
1770 	char	*argv[];
1771 {
1772 	int sig;
1773 	char buf[SIG2STR_MAX];
1774 
1775 	while (*++argv) {
1776 		sig = stoi((unsigned char *)*argv) & 0x7F;
1777 		if (sig2str(sig, buf) < 0) {
1778 			failure((unsigned char *)*argv, badsig);
1779 			return;
1780 		}
1781 		prs_buff((unsigned char *)buf);
1782 		prc_buff(NL);
1783 	}
1784 }
1785 #endif
1786 
1787 void
syskill(argc,argv)1788 syskill(argc, argv)
1789 	int	argc;
1790 	char	*argv[];
1791 {
1792 	char *cmdp = *argv;
1793 	int sig = SIGTERM;
1794 	int	pg = eq("killpg", cmdp);
1795 #ifdef	DO_GETOPT_UTILS
1796 	struct optv	optv;
1797 	int		c;
1798 	int		lfl = 0;
1799 	int		sfl = 0;
1800 
1801 	optinit(&optv);
1802 	optv.optflag |= OPT_NOFAIL;
1803 	/*
1804 	 * Even ksh93 only supports "kill -- -1234".
1805 	 * With the SVr4 Bourne Shell, "--" was not needed nor supported,
1806 	 * but "kill -1234" used "-1234" as signal number and thus failed.
1807 	 */
1808 	while ((c = optnext(argc, UCP argv, &optv, ":ls:", killuse)) != -1) {
1809 		switch (c) {
1810 		case 0:		return;	/* --help */
1811 
1812 		case 'l':	lfl = 1;
1813 				break;
1814 		case 's':
1815 				if (str2sig(optv.optarg, &sig)) {
1816 					failure((unsigned char *)cmdp, badsig);
1817 					return;
1818 				}
1819 				sfl = 1;
1820 				break;
1821 		case '?':
1822 				if (!sfl) {
1823 					if (str2sig(&argv[optv.ooptind][1],
1824 					    &sig) == 0) {
1825 						optv.optind = optv.ooptind + 1;
1826 						goto optdone;
1827 					}
1828 				}
1829 				/* FALLTHROUGH */
1830 		case ':':
1831 				optbad(argc, UCP argv, &optv);
1832 				gfailure((unsigned char *)usage, killuse);
1833 				return;
1834 		}
1835 	}
1836 optdone:
1837 	if (lfl + sfl > 1) {
1838 		gfailure((unsigned char *)usage, killuse);
1839 		return;
1840 	}
1841 	argc -= --optv.optind;
1842 	argv += optv.optind;
1843 	if (lfl) {
1844 		if (argc > 1)
1845 			namesigs(argv);
1846 		else
1847 			listsigs();
1848 		return;
1849 	}
1850 #endif
1851 	if (argc == 1) {
1852 		gfailure((unsigned char *)usage, killuse);
1853 		return;
1854 	}
1855 
1856 #ifndef	DO_GETOPT_UTILS
1857 	if (argv[1][0] == '-') {
1858 
1859 		if (argc == 2) {
1860 			if (!eq(argv[1], "-l")) {
1861 				gfailure((unsigned char *)usage, killuse);
1862 				return;
1863 			}
1864 			listsigs();
1865 			return;
1866 #ifdef	DO_KILL_L_SIG
1867 		} else if (eq(argv[1], "-l")) {
1868 			namesigs(++argv);
1869 			return;
1870 #endif
1871 		}
1872 		if (str2sig(&argv[1][1], &sig)) {
1873 			failure((unsigned char *)cmdp, badsig);
1874 			return;
1875 		}
1876 		argv++;
1877 	}
1878 #endif
1879 
1880 	while (*++argv)
1881 		sigv(cmdp, sig, pg ? F_KILLPG : F_KILL, *argv);
1882 }
1883 
1884 void
syssusp(argc,argv)1885 syssusp(argc, argv)
1886 	int	argc;
1887 	char	*argv[];
1888 {
1889 	char *cmdp = *argv;
1890 #ifdef	DO_GETOPT_UTILS
1891 	int	ind = optskip(argc, UCP argv, "suspend");
1892 
1893 	if (ind-- < 0)
1894 		return;
1895 	argc -= ind;
1896 	argv += ind;
1897 #endif
1898 
1899 	if (argc != 1) {
1900 		Failure((unsigned char *)cmdp, badopt);
1901 		return;
1902 	}
1903 #ifdef	SIGSTOP
1904 	sigv(cmdp, SIGSTOP, F_SUSPEND, "0");
1905 #endif
1906 }
1907 
1908 #ifdef	DO_SYSPGRP
1909 static void
pr_pgrp(pid,pgrp,sgrp)1910 pr_pgrp(pid, pgrp, sgrp)
1911 	pid_t	pid;
1912 	pid_t	pgrp;
1913 	pid_t	sgrp;
1914 {
1915 	prs_buff(UC "pid: ");
1916 	prs_buff(&numbuf[ltos((long)pid)]);
1917 	prs_buff(UC " processgroup: ");
1918 	prs_buff(&numbuf[ltos((long)pgrp)]);
1919 	if (sgrp != (pid_t)-1) {
1920 		prs_buff(UC " sessiongroup: ");
1921 		prs_buff(&numbuf[ltos((long)sgrp)]);
1922 	}
1923 	prc_buff(NL);
1924 }
1925 
1926 void
syspgrp(argc,argv)1927 syspgrp(argc, argv)
1928 	int	argc;
1929 	char	*argv[];
1930 {
1931 	char *cmdp = *argv;
1932 #ifdef	DO_GETOPT_UTILS
1933 	int	ind = optskip(argc, UCP argv, "pgrp [job ...]");
1934 
1935 	if (ind-- < 0)
1936 		return;
1937 	argc -= ind;
1938 	argv += ind;
1939 #endif
1940 
1941 	if (argc == 1) {
1942 		pid_t	pgrp;
1943 		pid_t	sgrp;
1944 
1945 #ifdef	TIOCGPGRP
1946 		/*
1947 		 * Prefer the ioctl() as the POSIX function tcgetpgrp() limits
1948 		 * access in a way that we cannot accept.
1949 		 */
1950 		if (ioctl(STDIN_FILENO, TIOCGPGRP, (char *)&pgrp) < 0)
1951 			pgrp = -1;
1952 #else
1953 		pgrp = tcgetpgrp(STDIN_FILENO);
1954 #endif
1955 #if	defined(HAVE_GETSID) && defined(HAVE_TCGETSID)
1956 #ifdef	TIOCGSID
1957 		/*
1958 		 * Prefer the ioctl() as the POSIX function tcgetsid() limits
1959 		 * access in a way that we cannot accept.
1960 		 */
1961 		if (ioctl(STDIN_FILENO, TIOCGSID, (char *)&sgrp) < 0)
1962 			sgrp = -1;
1963 #else
1964 		sgrp = tcgetsid(STDIN_FILENO);
1965 #endif
1966 #endif
1967 
1968 		prs_buff(UC "ttyprocessgroup: ");
1969 		prs_buff(&numbuf[sltos((long)pgrp)]);
1970 #if	defined(HAVE_GETSID) && defined(HAVE_TCGETSID)
1971 		prs_buff(UC " ttysessiongroup: ");
1972 		prs_buff(&numbuf[sltos((long)sgrp)]);
1973 #endif
1974 		prc_buff(NL);
1975 		sgrp = (pid_t)-1;
1976 #ifdef	HAVE_GETSID
1977 		sgrp = getsid(0);
1978 #endif
1979 		pr_pgrp(mypid, mypgid, sgrp);
1980 		return;
1981 	}
1982 #if	!defined(HAVE_GETPGID) && !defined(HAVE_BSD_GETPGRP)
1983 	failure((unsigned char *)cmdp, unimplemented);
1984 #else
1985 	while (*++argv)
1986 		sigv(cmdp, 0, F_PGRP, *argv);
1987 #endif
1988 }
1989 #endif
1990 
1991 void
hupforegnd()1992 hupforegnd()
1993 {
1994 	struct job *jp;
1995 #ifdef	SIGCHLD
1996 	sigset_t set, oset;
1997 
1998 	/*
1999 	 * add SIGCHLD to mask
2000 	 */
2001 	sigemptyset(&set);
2002 	sigaddset(&set, SIGCHLD);
2003 	sigprocmask(SIG_BLOCK, &set, &oset);
2004 #endif
2005 	for (jp = joblst; jp != NULL; jp = jp->j_nxtp) {
2006 		if (jp->j_flag & J_FOREGND) {
2007 			(void) kill(jp->j_pid, SIGHUP);
2008 			break;
2009 		}
2010 	}
2011 #ifdef	SIGCHLD
2012 	sigprocmask(SIG_SETMASK, &oset, 0);
2013 #endif
2014 }
2015 
2016 /*
2017  * Simple interface to waitid() that avoids the need to use our internal
2018  * siginfo_t emulation and our internal idtype_t emulation in case the
2019  * platform does not offer waitid().
2020  * It still allows to return more than the low 8 bits from exit().
2021  */
2022 pid_t
wait_status(pid,codep,statusp,opts)2023 wait_status(pid, codep, statusp, opts)
2024 	pid_t		pid;
2025 	int		*codep;
2026 	int		*statusp;
2027 	int		opts;
2028 {
2029 	siginfo_t	si;
2030 	pid_t		ret;
2031 	idtype_t	idtype;
2032 	pid_t		id;
2033 
2034 	if (pid > 0) {
2035 		idtype = P_PID;
2036 		id = pid;
2037 	} else if (pid < -1) {
2038 		idtype = P_PGID;
2039 		id = -pid;
2040 	} else if (pid == -1) {
2041 		idtype = P_ALL;
2042 		id = 0;
2043 	} else {
2044 		idtype = P_PGID;
2045 		id = getpgid(0);
2046 	}
2047 	ret = waitid(idtype, id, &si, opts);
2048 	if (ret == (pid_t)-1)
2049 		return ((pid_t)-1);
2050 	if (codep)
2051 		*codep = si.si_code;
2052 	if (statusp)
2053 		*statusp = si.si_status;
2054 	return (si.si_pid);
2055 }
2056 
2057 #ifdef	DO_TIME
2058 void
prtime(jp)2059 prtime(jp)
2060 	struct job	*jp;
2061 {
2062 	struct timeval	stop;
2063 	struct rusage	rustop;
2064 	UIntmax_t	cpu;
2065 	UIntmax_t	per;
2066 	unsigned char	*fmt;
2067 	unsigned char	*ofmt;
2068 	unsigned char	c;
2069 	int		save_fd = setb(STDERR_FILENO);
2070 
2071 	fmt = timefmtnod.namval;
2072 	if (fmt == NULL) {
2073 		fmt = flags2 & systime ?
2074 			UC "\nreal   %6:E\nuser   %6U\nsys    %6S" :
2075 			UC "%:E real %U user %S sys %P%% cpu";
2076 	}
2077 	ofmt = fmt;
2078 
2079 	gettimeofday(&stop, NULL);
2080 	ruget(&rustop);
2081 
2082 	timersub(&stop, &jp->j_start);
2083 	timersub(&rustop.ru_utime, &jp->j_rustart.ru_utime);
2084 	timersub(&rustop.ru_stime, &jp->j_rustart.ru_stime);
2085 
2086 #ifdef	USE_LONGLONG	/* 64 bits result in 584942 years with usec res. */
2087 	/*
2088 	 * Note that rustop.ru_utime.tv_sec is a long, so we need to cast
2089 	 * 1000000 in order to get a long long result from the multiplication.
2090 	 */
2091 	cpu =  rustop.ru_utime.tv_sec * (UIntmax_t)1000000 +
2092 		rustop.ru_utime.tv_usec;
2093 	cpu += rustop.ru_stime.tv_sec * (UIntmax_t)1000000 +
2094 		rustop.ru_stime.tv_usec;
2095 	per = stop.tv_sec * (UIntmax_t)1000000 +
2096 		stop.tv_usec;
2097 	if (per < 1)
2098 		per = 1;
2099 	per = 100 * cpu / per;
2100 	cpu /= 1000000;
2101 #else			/* 32 bits result in 49 days with msec resolution */
2102 	cpu =  rustop.ru_utime.tv_sec*1000 + rustop.ru_utime.tv_usec/1000;
2103 	cpu += rustop.ru_stime.tv_sec*1000 + rustop.ru_stime.tv_usec/1000;
2104 	per = stop.tv_sec*1000 + stop.tv_usec/1000;
2105 	if (per < 1)
2106 		per = 1;
2107 	if (cpu > (UINT32_MAX / 100))
2108 		per = cpu / (per / 100);
2109 	else
2110 		per = 100 * cpu / per;
2111 	cpu /= 1000;
2112 #endif
2113 
2114 	while ((c = *fmt++) != '\0') {
2115 		if (c == '%') {
2116 			int	dig = -1;
2117 			int	longopt = FALSE;
2118 
2119 			if ((c = *fmt++) == '\0')
2120 				break;
2121 			if (c >= '0' && c <= '9') {
2122 				dig = c - '0';
2123 				if ((c = *fmt++) == '\0')
2124 					break;
2125 			}
2126 			if (c == 'l' || c == 'L' || c == ':') {
2127 				longopt = c;
2128 				if ((c = *fmt++) == '\0')
2129 					break;
2130 			}
2131 			switch (c) {
2132 			case 'T':
2133 				if ((flags2 & systime) == 0 && dig > cpu) {
2134 					fmt -= 3;
2135 					goto out;
2136 				}
2137 				break;
2138 			case 'J':
2139 				prs_buff((unsigned char *)jp->j_cmd);
2140 				break;
2141 			case 'P':
2142 				prull_buff(per);
2143 				break;
2144 			case 'E':
2145 				prtv(&stop, dig, longopt);
2146 				break;
2147 			case 'S':
2148 				prtv(&rustop.ru_stime, dig, longopt);
2149 				break;
2150 			case 'U':
2151 				prtv(&rustop.ru_utime, dig, longopt);
2152 				break;
2153 
2154 #if !defined(__BEOS__) && !defined(__HAIKU__) && \
2155     !defined(OS390) && !defined(__MVS__)
2156 			/* XXX dirty hack */
2157 			case 'W':
2158 				prl_buff(rustop.ru_nswap -
2159 					jp->j_rustart.ru_nswap);
2160 				break;
2161 #ifdef	__future__
2162 			case 'X':	/* shared */
2163 				ru_ixrss * pagesize()/1024 / tics
2164 				break;
2165 			case 'D':	/* unshared data */
2166 				ru_idrss * pagesize()/1024 / tics
2167 				break;
2168 			case 'K':	/* unshared stack */
2169 				ru_isrss * pagesize()/1024 / tics
2170 				break;
2171 			case 'M':
2172 				ru_maxrss * pagesize()/1024(/2 ?)
2173 				break;
2174 #else
2175 			case 'X':
2176 			case 'D':
2177 			case 'K':
2178 			case 'M':
2179 				prc_buff('0');
2180 				break;
2181 #endif
2182 			case 'F':
2183 				prl_buff(rustop.ru_majflt -
2184 					jp->j_rustart.ru_majflt);
2185 				break;
2186 			case 'R':
2187 				prl_buff(rustop.ru_minflt -
2188 					jp->j_rustart.ru_minflt);
2189 				break;
2190 			case 'I':
2191 				prl_buff(rustop.ru_inblock -
2192 					jp->j_rustart.ru_inblock);
2193 				break;
2194 			case 'O':
2195 				prl_buff(rustop.ru_oublock -
2196 					jp->j_rustart.ru_oublock);
2197 				break;
2198 			case 'r':
2199 				prl_buff(rustop.ru_msgrcv -
2200 					jp->j_rustart.ru_msgrcv);
2201 				break;
2202 			case 's':
2203 				prl_buff(rustop.ru_msgsnd -
2204 					jp->j_rustart.ru_msgsnd);
2205 				break;
2206 			case 'k':
2207 				prl_buff(rustop.ru_nsignals -
2208 					jp->j_rustart.ru_nsignals);
2209 				break;
2210 			case 'w':
2211 				prl_buff(rustop.ru_nvcsw -
2212 					jp->j_rustart.ru_nvcsw);
2213 				break;
2214 			case 'c':
2215 				prl_buff(rustop.ru_nivcsw -
2216 					jp->j_rustart.ru_nivcsw);
2217 				break;
2218 #endif
2219 			default:
2220 				prc_buff(c);
2221 			}
2222 		} else {
2223 			prc_buff(c);
2224 		}
2225 	}
2226 out:
2227 	if ((fmt - ofmt) > 0)
2228 		prc_buff(NL);
2229 	flushb();
2230 
2231 	(void) setb(save_fd);
2232 }
2233 
2234 void
ruget(rup)2235 ruget(rup)
2236 	struct rusage	*rup;
2237 {
2238 	struct rusage	ruc;
2239 
2240 	getrusage(RUSAGE_SELF, rup);
2241 	getrusage(RUSAGE_CHILDREN, &ruc);
2242 	ruadd(rup, &ruc);
2243 }
2244 
2245 static void
ruadd(ru,ru2)2246 ruadd(ru, ru2)
2247 	struct rusage	*ru;
2248 	struct rusage	*ru2;
2249 {
2250 	timeradd(&ru->ru_utime, &ru2->ru_utime);
2251 	timeradd(&ru->ru_stime, &ru2->ru_stime);
2252 
2253 #if !defined(__BEOS__) && !defined(__HAIKU__) && \
2254     !defined(OS390) && !defined(__MVS__)
2255 #ifdef	__future__
2256 	if (ru2->ru_maxrss > ru->ru_maxrss)
2257 		ru->ru_maxrss =	ru2->ru_maxrss;
2258 
2259 	ru->ru_ixrss += ru2->ru_ixrss;
2260 	ru->ru_idrss += ru2->ru_idrss;
2261 	ru->ru_isrss += ru2->ru_isrss;
2262 #endif
2263 	ru->ru_minflt += ru2->ru_minflt;
2264 	ru->ru_majflt += ru2->ru_majflt;
2265 	ru->ru_nswap += ru2->ru_nswap;
2266 	ru->ru_inblock += ru2->ru_inblock;
2267 	ru->ru_oublock += ru2->ru_oublock;
2268 	ru->ru_msgsnd += ru2->ru_msgsnd;
2269 	ru->ru_msgrcv += ru2->ru_msgrcv;
2270 	ru->ru_nsignals += ru2->ru_nsignals;
2271 	ru->ru_nvcsw += ru2->ru_nvcsw;
2272 	ru->ru_nivcsw += ru2->ru_nivcsw;
2273 #endif /* !defined(__BEOS__) && !defined(__HAIKU__) */
2274 }
2275 #endif	/* DO_TIME */
2276 
2277 #ifndef	HAVE_GETRUSAGE
2278 int
getrusage(who,r_usage)2279 getrusage(who, r_usage)
2280 	int		who;
2281 	struct rusage	*r_usage;
2282 {
2283 	int		ret = -1;
2284 #ifdef	HAVE_TIMES
2285 	struct tms	tms;
2286 
2287 	times(&tms);
2288 #endif
2289 	memset(r_usage, 0, sizeof (*r_usage));
2290 #ifdef	HAVE_TIMES
2291 	if (who == RUSAGE_SELF) {
2292 		clock2tv(tms.tms_utime, &r_usage->ru_utime);
2293 		clock2tv(tms.tms_stime, &r_usage->ru_stime);
2294 	} else if (who == RUSAGE_CHILDREN) {
2295 		clock2tv(tms.tms_cutime, &r_usage->ru_utime);
2296 		clock2tv(tms.tms_cstime, &r_usage->ru_stime);
2297 	}
2298 #endif
2299 	return (ret);
2300 }
2301 #endif	/* HAVE_GETRUSAGE */
2302 
2303 #ifndef	HAVE_WAITID
2304 static int
waitid(idtype,id,infop,opts)2305 waitid(idtype, id, infop, opts)
2306 	idtype_t	idtype;
2307 	id_t		id;
2308 	siginfo_t	*infop;		/* Must be != NULL */
2309 	int		opts;
2310 {
2311 	int		exstat;
2312 	pid_t		pid;
2313 #ifdef	__needed__
2314 	struct tms	tms;
2315 #endif
2316 
2317 	opts &= ~(WEXITED|WTRAPPED);	/* waitpid() doesn't understand them */
2318 #if	WSTOPPED != WUNTRACED
2319 	if (opts & WSTOPPED) {
2320 		opts &= ~WSTOPPED;
2321 		opts |= WUNTRACED;
2322 	}
2323 #endif
2324 
2325 	if (idtype == P_PID)
2326 		pid = id;
2327 	else if (idtype == P_PGID)
2328 		pid = -id;
2329 	else if (idtype == P_ALL)
2330 		pid = -1;
2331 	else
2332 		pid = 0;
2333 
2334 	infop->si_utime = 0;
2335 	infop->si_stime = 0;
2336 #ifdef	__needed__
2337 	if (WNOWAIT == 0 || (opts & WNOWAIT) == 0) {
2338 		times(&tms);
2339 	}
2340 #endif
2341 	pid = waitpid(pid, &exstat, opts);
2342 	infop->si_pid = pid;
2343 	infop->si_code = 0;
2344 	infop->si_status = 0;
2345 
2346 	if (pid == (pid_t)-1)
2347 		return (-1);
2348 
2349 #ifdef	__needed__
2350 	if (WNOWAIT == 0 || (opts & WNOWAIT) == 0) {
2351 		infop->si_utime = tms.tms_cutime;
2352 		infop->si_stime = tms.tms_cstime;
2353 		times(&tms);
2354 		infop->si_utime = tms.tms_cutime - infop->si_utime;
2355 		infop->si_stime = tms.tms_cstime - infop->si_stime;
2356 	}
2357 #endif
2358 
2359 	if (WIFEXITED(exstat)) {
2360 		infop->si_code = CLD_EXITED;
2361 		infop->si_status = WEXITSTATUS(exstat);
2362 	} else if (WIFSIGNALED(exstat)) {
2363 		if (WCOREDUMP(exstat))
2364 			infop->si_code = CLD_DUMPED;
2365 		else
2366 			infop->si_code = CLD_KILLED;
2367 		infop->si_status = WTERMSIG(exstat);
2368 	} else if (WIFSTOPPED(exstat)) {
2369 #ifdef	SIGTRAP
2370 		if (WSTOPSIG(exstat) == SIGTRAP)
2371 			infop->si_code = CLD_TRAPPED;
2372 		else
2373 #endif
2374 			infop->si_code = CLD_STOPPED;
2375 		infop->si_status = WSTOPSIG(exstat);
2376 	} else if (WIFCONTINUED(exstat)) {
2377 		infop->si_code = CLD_CONTINUED;
2378 #ifdef	SIGCONT
2379 		infop->si_status = SIGCONT;
2380 #else
2381 		infop->si_status = 0;
2382 #endif
2383 	}
2384 
2385 	return (0);
2386 }
2387 #endif
2388 
2389 #ifdef	DO_TRAP_FROM_WAITID
2390 static int
didsignal(infop)2391 didsignal(infop)
2392 	siginfo_t	*infop;
2393 {
2394 	if (infop->si_pid == 0)
2395 		return (FALSE);
2396 
2397 	switch (infop->si_code) {
2398 
2399 #ifdef	CLD_KILLED
2400 	case CLD_KILLED:
2401 #endif
2402 #ifdef	CLD_DUMPED
2403 	case CLD_DUMPED:
2404 #endif
2405 #ifdef	CLD_TRAPPED
2406 	case CLD_TRAPPED:
2407 #endif
2408 #ifdef	CLD_STOPPED
2409 	case CLD_STOPPED:
2410 #endif
2411 #ifdef	CLD_CONTINUED
2412 	case CLD_CONTINUED:
2413 #endif
2414 		return (TRUE);
2415 
2416 	default:
2417 		return (FALSE);
2418 	}
2419 }
2420 
2421 static void
checksigs(infop)2422 checksigs(infop)
2423 	siginfo_t	*infop;
2424 {
2425 	if ((flags & (monitorflg|jcflg|jcoff)) == (monitorflg|jcflg)) {
2426 		if (didsignal(infop) && infop->si_status) {
2427 			fault(infop->si_status);
2428 		}
2429 	}
2430 }
2431 #endif
2432 
2433 #ifdef	DO_DOL_SLASH
2434 
2435 #ifdef	HAVE_SMMAP
2436 #include <schily/mman.h>
2437 
2438 void
shmcreate()2439 shmcreate()
2440 {
2441 	int	f;
2442 	char	*addr;
2443 #ifdef	_SC_PAGESIZE
2444 	int	size = (int)sysconf(_SC_PAGESIZE);
2445 #else
2446 	int	size = getpagesize();
2447 #endif
2448 static	int	myint;
2449 
2450 #ifdef	MAP_ANONYMOUS	/* HP/UX */
2451 	f = -1;
2452 	addr = mmap(0, mmap_sizeparm(size), PROT_READ|PROT_WRITE,
2453 					MAP_SHARED|MAP_ANONYMOUS, f, 0);
2454 #else
2455 	if ((f = open("/dev/zero", O_RDWR)) < 0)
2456 		goto err;
2457 	addr = mmap(0, mmap_sizeparm(size), PROT_READ|PROT_WRITE,
2458 					MAP_SHARED, f, 0);
2459 	close(f);
2460 #endif
2461 	if (addr == (char *)-1)
2462 		goto err;
2463 
2464 	excausep = (int *)addr;
2465 	return;
2466 err:
2467 	/*
2468 	 * mmap() did not work, try to be silent...
2469 	 */
2470 	excausep = &myint;
2471 }
2472 #else	/* !HAVE_SMMAP */
2473 void
shmcreate()2474 shmcreate()
2475 {
2476 static	int	myint;
2477 
2478 	excausep = &myint;
2479 }
2480 #endif	/* HAVE_SMMAP */
2481 
2482 #endif	/* DO_DOL_SLASH */
2483