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 <syscalls.h> 16 #include <thread_defs.h> 17 18 19 pid_t 20 wait(int* _status) 21 { 22 return waitpid(-1, _status, 0); 23 } 24 25 26 pid_t 27 waitpid(pid_t pid, int* _status, int options) 28 { 29 // wait 30 siginfo_t info; 31 pid_t child = _kern_wait_for_child(pid, options, &info); 32 33 pthread_testcancel(); 34 35 if (child < 0) 36 RETURN_AND_SET_ERRNO(child); 37 38 // prepare the status 39 if (_status != NULL) { 40 int status; 41 switch (info.si_code) { 42 case CLD_EXITED: 43 // fill in exit status for WIFEXITED() and WEXITSTATUS() 44 status = info.si_status & 0xff; 45 break; 46 47 case CLD_KILLED: 48 case CLD_DUMPED: 49 // fill in signal for WIFSIGNALED() and WTERMSIG() 50 status = (info.si_status << 8) & 0xff00; 51 // if core dumped, set flag for WIFCORED() 52 if (info.si_code == CLD_DUMPED) 53 status |= 0x10000; 54 break; 55 56 case CLD_CONTINUED: 57 // set flag for WIFCONTINUED() 58 status = 0x20000; 59 break; 60 61 case CLD_STOPPED: 62 // fill in signal for WIFSTOPPED() and WSTOPSIG() 63 status = (info.si_status << 16) & 0xff0000; 64 break; 65 66 case CLD_TRAPPED: 67 // we don't do that 68 default: 69 // should never get here -- assume exited 70 status = 0; 71 break; 72 } 73 74 *_status = status; 75 } 76 77 return child; 78 } 79 80 81 int 82 waitid(idtype_t idType, id_t id, siginfo_t* info, int options) 83 { 84 // translate the idType, id pair to a waitpid() style ID 85 switch (idType) { 86 case P_ALL: 87 // any child 88 id = -1; 89 break; 90 91 case P_PID: 92 // the child with the given ID 93 if (id <= 0) 94 RETURN_AND_SET_ERRNO_TEST_CANCEL(EINVAL); 95 break; 96 97 case P_PGID: 98 // any child in the given process group 99 if (id <= 1) 100 RETURN_AND_SET_ERRNO_TEST_CANCEL(EINVAL); 101 id = -id; 102 break; 103 104 default: 105 RETURN_AND_SET_ERRNO_TEST_CANCEL(EINVAL); 106 } 107 108 pid_t child = _kern_wait_for_child(id, options, info); 109 if (child >= 0 || child == B_WOULD_BLOCK) 110 return 0; 111 112 RETURN_AND_SET_ERRNO_TEST_CANCEL(child); 113 } 114