* Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de.
* Copyright 2004-2007, Axel DΓΆrfler, axeld@pinc-software.de.
* All rights reserved.
* Distributed under the terms of the MIT License.
*/
#include <sys/wait.h>
#include <errno.h>
#include <pthread.h>
#include <syscall_utils.h>
#include <errno_private.h>
#include <syscalls.h>
#include <thread_defs.h>
pid_t
wait(int* _status)
{
return waitpid(-1, _status, 0);
}
extern "C" pid_t
_waitpid(pid_t pid, int* _status, int options, team_usage_info *usage_info)
{
siginfo_t info;
pid_t child = _kern_wait_for_child(pid, options | WEXITED, &info,
usage_info);
pthread_testcancel();
if (child < 0) {
if (child == B_WOULD_BLOCK && (options & WNOHANG) != 0)
return 0;
RETURN_AND_SET_ERRNO(child);
}
if (_status != NULL) {
int status;
switch (info.si_code) {
case CLD_EXITED:
status = info.si_status & 0xff;
break;
case CLD_KILLED:
case CLD_DUMPED:
status = (info.si_status << 8) & 0xff00;
if (info.si_code == CLD_DUMPED)
status |= 0x10000;
break;
case CLD_CONTINUED:
status = 0x20000;
break;
case CLD_STOPPED:
status = (info.si_status << 16) & 0xff0000;
break;
case CLD_TRAPPED:
default:
status = 0;
break;
}
*_status = status;
}
return child;
}
pid_t
waitpid(pid_t pid, int* _status, int options)
{
return _waitpid(pid, _status, options, NULL);
}
int
waitid(idtype_t idType, id_t id, siginfo_t* info, int options)
{
switch (idType) {
case P_ALL:
id = -1;
break;
case P_PID:
if (id <= 0)
RETURN_AND_SET_ERRNO_TEST_CANCEL(EINVAL);
break;
case P_PGID:
if (id <= 1)
RETURN_AND_SET_ERRNO_TEST_CANCEL(EINVAL);
id = -id;
break;
default:
RETURN_AND_SET_ERRNO_TEST_CANCEL(EINVAL);
}
pid_t child = _kern_wait_for_child(id, options, info, NULL);
if (child >= 0 || child == B_WOULD_BLOCK)
return 0;
RETURN_AND_SET_ERRNO_TEST_CANCEL(child);
}