vfs: check userland buffers before reading them.
[haiku.git] / src / system / libroot / posix / sys / wait.cpp
blobd8dd5b025c7832070691bfa5a9e2559a81fc0e5c
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 */
8 #include <sys/wait.h>
10 #include <errno.h>
11 #include <pthread.h>
13 #include <syscall_utils.h>
15 #include <errno_private.h>
16 #include <syscalls.h>
17 #include <thread_defs.h>
20 pid_t
21 wait(int* _status)
23 return waitpid(-1, _status, 0);
26 extern "C" pid_t
27 _waitpid(pid_t pid, int* _status, int options, team_usage_info *usage_info)
29 // wait
30 siginfo_t info;
31 pid_t child = _kern_wait_for_child(pid, options | WEXITED, &info,
32 usage_info);
34 pthread_testcancel();
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);
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;
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;
62 case CLD_CONTINUED:
63 // set flag for WIFCONTINUED()
64 status = 0x20000;
65 break;
67 case CLD_STOPPED:
68 // fill in signal for WIFSTOPPED() and WSTOPSIG()
69 status = (info.si_status << 16) & 0xff0000;
70 break;
72 case CLD_TRAPPED:
73 // we don't do that
74 default:
75 // should never get here -- assume exited
76 status = 0;
77 break;
80 *_status = status;
83 return child;
87 pid_t
88 waitpid(pid_t pid, int* _status, int options)
90 return _waitpid(pid, _status, options, NULL);
94 int
95 waitid(idtype_t idType, id_t id, siginfo_t* info, int options)
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;
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;
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;
117 default:
118 RETURN_AND_SET_ERRNO_TEST_CANCEL(EINVAL);
121 pid_t child = _kern_wait_for_child(id, options, info, NULL);
122 if (child >= 0 || child == B_WOULD_BLOCK)
123 return 0;
125 RETURN_AND_SET_ERRNO_TEST_CANCEL(child);