1 /* @(#)waitid.c	1.3 19/04/28 Copyright 2015-2018 J. Schilling */
2 /*
3  *	Emulate the waitid() syscall in case it is missing or disfunctional
4  *
5  *	Copyright (c) 2015-2018 J. Schilling
6  */
7 /*
8  * The contents of this file are subject to the terms of the
9  * Common Development and Distribution License, Version 1.0 only
10  * (the "License").  You may not use this file except in compliance
11  * with the License.
12  *
13  * See the file CDDL.Schily.txt in this distribution for details.
14  * A copy of the CDDL is also available via the Internet at
15  * http://www.opensource.org/licenses/cddl1.txt
16  *
17  * When distributing Covered Code, include this CDDL HEADER in each
18  * file and include the License file CDDL.Schily.txt from this distribution.
19  */
20 
21 #include	<schily/wait.h>
22 #include	<schily/schily.h>
23 
24 #ifndef	HAVE_WAITID
25 EXPORT int
waitid(idtype,id,infop,opts)26 waitid(idtype, id, infop, opts)
27 	idtype_t	idtype;
28 	id_t		id;
29 	siginfo_t	*infop;		/* Must be != NULL */
30 	int		opts;
31 {
32 	int		exstat;
33 	pid_t		pid;
34 #ifdef	__needed__
35 	struct tms	tms;
36 #endif
37 
38 	opts &= ~(WEXITED|WTRAPPED);	/* waitpid() doesn't understand them */
39 #if	WSTOPPED != WUNTRACED
40 	if (opts & WSTOPPED) {
41 		opts &= ~WSTOPPED;
42 		opts |= WUNTRACED;
43 	}
44 #endif
45 
46 	if (idtype == P_PID)
47 		pid = id;
48 	else if (idtype == P_PGID)
49 		pid = -id;
50 	else if (idtype == P_ALL)
51 		pid = -1;
52 	else
53 		pid = 0;
54 
55 #ifdef	__needed__
56 	/*
57 	 * We cannot clear infop->si_utime and infop->si_stime as they are
58 	 * missing on HP-UX-10.x.
59 	 */
60 	infop->si_utime = 0;
61 	infop->si_stime = 0;
62 	if (WNOWAIT == 0 || (opts & WNOWAIT) == 0) {
63 		times(&tms);
64 	}
65 #endif
66 	pid = waitpid(pid, &exstat, opts);
67 	infop->si_pid = pid;
68 	infop->si_code = 0;
69 	infop->si_status = 0;
70 
71 	if (pid == (pid_t)-1)
72 		return (-1);
73 
74 #ifdef	__needed__
75 	if (WNOWAIT == 0 || (opts & WNOWAIT) == 0) {
76 		infop->si_utime = tms.tms_cutime;
77 		infop->si_stime = tms.tms_cstime;
78 		times(&tms);
79 		infop->si_utime = tms.tms_cutime - infop->si_utime;
80 		infop->si_stime = tms.tms_cstime - infop->si_stime;
81 	}
82 #endif
83 
84 	if (WIFEXITED(exstat)) {
85 		infop->si_code = CLD_EXITED;
86 		infop->si_status = WEXITSTATUS(exstat);
87 	} else if (WIFSIGNALED(exstat)) {
88 		if (WCOREDUMP(exstat))
89 			infop->si_code = CLD_DUMPED;
90 		else
91 			infop->si_code = CLD_KILLED;
92 		infop->si_status = WTERMSIG(exstat);
93 	} else if (WIFSTOPPED(exstat)) {
94 #ifdef	SIGTRAP
95 		if (WSTOPSIG(exstat) == SIGTRAP)
96 			infop->si_code = CLD_TRAPPED;
97 		else
98 #endif
99 			infop->si_code = CLD_STOPPED;
100 		infop->si_status = WSTOPSIG(exstat);
101 	} else if (WIFCONTINUED(exstat)) {
102 		infop->si_code = CLD_CONTINUED;
103 #ifdef	SIGCONT
104 		infop->si_status = SIGCONT;
105 #else
106 		infop->si_status = 0;
107 #endif
108 	}
109 
110 	return (0);
111 }
112 #endif
113