1 /*
2 * Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Copyright 2004-2007, Axel Dörfler, axeld@pinc-software.de.
4 * All rights reserved.
5 * Distributed under the terms of the MIT License.
6 */
7
8 #include <sys/wait.h>
9
10 #include <errno.h>
11 #include <pthread.h>
12
13 #include <syscall_utils.h>
14
15 #include <errno_private.h>
16 #include <syscalls.h>
17 #include <thread_defs.h>
18
19
20 pid_t
wait(int * _status)21 wait(int* _status)
22 {
23 return waitpid(-1, _status, 0);
24 }
25
26 extern "C" pid_t
_waitpid(pid_t pid,int * _status,int options,team_usage_info * usage_info)27 _waitpid(pid_t pid, int* _status, int options, team_usage_info *usage_info)
28 {
29 // wait
30 siginfo_t info;
31 pid_t child = _kern_wait_for_child(pid, options | WEXITED, &info,
32 usage_info);
33
34 pthread_testcancel();
35
36 if (child < 0) {
37 // When not getting a child status when WNOHANG was specified, don't
38 // fail.
39 if (child == B_WOULD_BLOCK && (options & WNOHANG) != 0)
40 return 0;
41 RETURN_AND_SET_ERRNO(child);
42 }
43
44 // prepare the status
45 if (_status != NULL) {
46 int status;
47 switch (info.si_code) {
48 case CLD_EXITED:
49 // fill in exit status for WIFEXITED() and WEXITSTATUS()
50 status = info.si_status & 0xff;
51 break;
52
53 case CLD_KILLED:
54 case CLD_DUMPED:
55 // fill in signal for WIFSIGNALED() and WTERMSIG()
56 status = (info.si_status << 8) & 0xff00;
57 // if core dumped, set flag for WIFCORED()
58 if (info.si_code == CLD_DUMPED)
59 status |= 0x10000;
60 break;
61
62 case CLD_CONTINUED:
63 // set flag for WIFCONTINUED()
64 status = 0x20000;
65 break;
66
67 case CLD_STOPPED:
68 // fill in signal for WIFSTOPPED() and WSTOPSIG()
69 status = (info.si_status << 16) & 0xff0000;
70 break;
71
72 case CLD_TRAPPED:
73 // we don't do that
74 default:
75 // should never get here -- assume exited
76 status = 0;
77 break;
78 }
79
80 *_status = status;
81 }
82
83 return child;
84 }
85
86
87 pid_t
waitpid(pid_t pid,int * _status,int options)88 waitpid(pid_t pid, int* _status, int options)
89 {
90 return _waitpid(pid, _status, options, NULL);
91 }
92
93
94 int
waitid(idtype_t idType,id_t id,siginfo_t * info,int options)95 waitid(idtype_t idType, id_t id, siginfo_t* info, int options)
96 {
97 // translate the idType, id pair to a waitpid() style ID
98 switch (idType) {
99 case P_ALL:
100 // any child
101 id = -1;
102 break;
103
104 case P_PID:
105 // the child with the given ID
106 if (id <= 0)
107 RETURN_AND_SET_ERRNO_TEST_CANCEL(EINVAL);
108 break;
109
110 case P_PGID:
111 // any child in the given process group
112 if (id <= 1)
113 RETURN_AND_SET_ERRNO_TEST_CANCEL(EINVAL);
114 id = -id;
115 break;
116
117 default:
118 RETURN_AND_SET_ERRNO_TEST_CANCEL(EINVAL);
119 }
120
121 pid_t child = _kern_wait_for_child(id, options, info, NULL);
122 if (child >= 0 || child == B_WOULD_BLOCK)
123 return 0;
124
125 RETURN_AND_SET_ERRNO_TEST_CANCEL(child);
126 }
127