Serenity Operating System
at master 271 lines 6.4 kB view raw
1/* 2 * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#include <AK/StringView.h> 8#include <assert.h> 9#include <bits/pthread_cancel.h> 10#include <errno.h> 11#include <setjmp.h> 12#include <signal.h> 13#include <string.h> 14#include <sys/select.h> 15#include <syscall.h> 16#include <unistd.h> 17 18extern "C" { 19 20// https://pubs.opengroup.org/onlinepubs/9699919799/functions/kill.html 21int kill(pid_t pid, int sig) 22{ 23 int rc = syscall(SC_kill, pid, sig); 24 __RETURN_WITH_ERRNO(rc, rc, -1); 25} 26 27// https://pubs.opengroup.org/onlinepubs/9699919799/functions/killpg.html 28int killpg(int pgrp, int sig) 29{ 30 int rc = syscall(SC_killpg, pgrp, sig); 31 __RETURN_WITH_ERRNO(rc, rc, -1); 32} 33 34// https://pubs.opengroup.org/onlinepubs/9699919799/functions/raise.html 35int raise(int sig) 36{ 37 // FIXME: Support multi-threaded programs. 38 return kill(getpid(), sig); 39} 40 41// https://pubs.opengroup.org/onlinepubs/9699919799/functions/signal.html 42sighandler_t signal(int signum, sighandler_t handler) 43{ 44 struct sigaction new_act; 45 struct sigaction old_act; 46 new_act.sa_handler = handler; 47 new_act.sa_flags = 0; 48 new_act.sa_mask = 0; 49 int rc = sigaction(signum, &new_act, &old_act); 50 if (rc < 0) 51 return SIG_ERR; 52 return old_act.sa_handler; 53} 54 55// https://pubs.opengroup.org/onlinepubs/9699919799/functions/sigaction.html 56int sigaction(int signum, const struct sigaction* act, struct sigaction* old_act) 57{ 58 int rc = syscall(SC_sigaction, signum, act, old_act); 59 __RETURN_WITH_ERRNO(rc, rc, -1); 60} 61 62// https://pubs.opengroup.org/onlinepubs/9699919799/functions/sigemptyset.html 63int sigemptyset(sigset_t* set) 64{ 65 *set = 0; 66 return 0; 67} 68 69// https://pubs.opengroup.org/onlinepubs/9699919799/functions/sigfillset.html 70int sigfillset(sigset_t* set) 71{ 72 *set = 0xffffffff; 73 return 0; 74} 75 76// https://pubs.opengroup.org/onlinepubs/9699919799/functions/sigaddset.html 77int sigaddset(sigset_t* set, int sig) 78{ 79 if (sig < 1 || sig > 32) { 80 errno = EINVAL; 81 return -1; 82 } 83 *set |= 1 << (sig - 1); 84 return 0; 85} 86 87// https://pubs.opengroup.org/onlinepubs/9699919799/functions/sigaltstack.html 88int sigaltstack(stack_t const* ss, stack_t* old_ss) 89{ 90 int rc = syscall(SC_sigaltstack, ss, old_ss); 91 __RETURN_WITH_ERRNO(rc, rc, -1); 92} 93 94// https://pubs.opengroup.org/onlinepubs/9699919799/functions/sigdelset.html 95int sigdelset(sigset_t* set, int sig) 96{ 97 if (sig < 1 || sig > 32) { 98 errno = EINVAL; 99 return -1; 100 } 101 *set &= ~(1 << (sig - 1)); 102 return 0; 103} 104 105// https://pubs.opengroup.org/onlinepubs/9699919799/functions/sigismember.html 106int sigismember(sigset_t const* set, int sig) 107{ 108 if (sig < 1 || sig > 32) { 109 errno = EINVAL; 110 return -1; 111 } 112 if (*set & (1 << (sig - 1))) 113 return 1; 114 return 0; 115} 116 117// https://pubs.opengroup.org/onlinepubs/9699919799/functions/sigprocmask.html 118int sigprocmask(int how, sigset_t const* set, sigset_t* old_set) 119{ 120 int rc = syscall(SC_sigprocmask, how, set, old_set); 121 __RETURN_WITH_ERRNO(rc, rc, -1); 122} 123 124// https://pubs.opengroup.org/onlinepubs/9699919799/functions/sigpending.html 125int sigpending(sigset_t* set) 126{ 127 int rc = syscall(SC_sigpending, set); 128 __RETURN_WITH_ERRNO(rc, rc, -1); 129} 130 131char const* sys_siglist[NSIG] = { 132 "Invalid signal number", 133 "Hangup", 134 "Interrupt", 135 "Quit", 136 "Illegal instruction", 137 "Trap", 138 "Aborted", 139 "Bus error", 140 "Division by zero", 141 "Killed", 142 "User signal 1", 143 "Segmentation violation", 144 "User signal 2", 145 "Broken pipe", 146 "Alarm clock", 147 "Terminated", 148 "Stack fault", 149 "Child exited", 150 "Continued", 151 "Stopped (signal)", 152 "Stopped", 153 "Stopped (tty input)", 154 "Stopped (tty output)", 155 "Urgent I/O condition)", 156 "CPU limit exceeded", 157 "File size limit exceeded", 158 "Virtual timer expired", 159 "Profiling timer expired", 160 "Window changed", 161 "I/O possible", 162 "Power failure", 163 "Bad system call", 164}; 165 166// https://pubs.opengroup.org/onlinepubs/9699919799/functions/siglongjmp.html 167void siglongjmp(jmp_buf env, int val) 168{ 169 if (env->did_save_signal_mask) { 170 int rc = sigprocmask(SIG_SETMASK, &env->saved_signal_mask, nullptr); 171 assert(rc == 0); 172 } 173 longjmp(env, val); 174} 175 176// https://pubs.opengroup.org/onlinepubs/9699919799/functions/sigsuspend.html 177int sigsuspend(sigset_t const* set) 178{ 179 __pthread_maybe_cancel(); 180 181 int rc = syscall(SC_sigsuspend, set); 182 __RETURN_WITH_ERRNO(rc, rc, -1); 183} 184 185// https://pubs.opengroup.org/onlinepubs/009604499/functions/sigwait.html 186int sigwait(sigset_t const* set, int* sig) 187{ 188 __pthread_maybe_cancel(); 189 190 int rc = syscall(Syscall::SC_sigtimedwait, set, nullptr, nullptr); 191 VERIFY(rc != 0); 192 if (rc < 0) 193 return -rc; 194 *sig = rc; 195 return 0; 196} 197 198// https://pubs.opengroup.org/onlinepubs/9699919799/functions/sigwaitinfo.html 199int sigwaitinfo(sigset_t const* set, siginfo_t* info) 200{ 201 return sigtimedwait(set, info, nullptr); 202} 203 204// https://pubs.opengroup.org/onlinepubs/9699919799/functions/sigtimedwait.html 205int sigtimedwait(sigset_t const* set, siginfo_t* info, struct timespec const* timeout) 206{ 207 __pthread_maybe_cancel(); 208 209 int rc = syscall(Syscall::SC_sigtimedwait, set, info, timeout); 210 __RETURN_WITH_ERRNO(rc, rc, -1); 211} 212 213char const* sys_signame[] = { 214 "INVAL", 215 "HUP", 216 "INT", 217 "QUIT", 218 "ILL", 219 "TRAP", 220 "ABRT", 221 "BUS", 222 "FPE", 223 "KILL", 224 "USR1", 225 "SEGV", 226 "USR2", 227 "PIPE", 228 "ALRM", 229 "TERM", 230 "STKFLT", 231 "CHLD", 232 "CONT", 233 "STOP", 234 "TSTP", 235 "TTIN", 236 "TTOU", 237 "URG", 238 "XCPU", 239 "XFSZ", 240 "VTALRM", 241 "PROF", 242 "WINCH", 243 "IO", 244 "INFO", 245 "SYS", 246}; 247 248static_assert(sizeof(sys_signame) == sizeof(char const*) * NSIG); 249 250int getsignalbyname(char const* name) 251{ 252 VERIFY(name); 253 StringView name_sv { name, strlen(name) }; 254 for (size_t i = 0; i < NSIG; ++i) { 255 StringView signal_name { sys_signame[i], sizeof(sys_signame[i]) - 1 }; 256 if (signal_name == name_sv || (name_sv.starts_with("SIG"sv) && signal_name == name_sv.substring_view(3))) 257 return i; 258 } 259 errno = EINVAL; 260 return -1; 261} 262 263char const* getsignalname(int signal) 264{ 265 if (signal < 0 || signal >= NSIG) { 266 errno = EINVAL; 267 return nullptr; 268 } 269 return sys_signame[signal]; 270} 271}