mirror of
				https://github.com/jart/cosmopolitan.git
				synced 2025-10-27 19:34:33 +00:00 
			
		
		
		
	Introduce sigtimedwait() and sigwaitinfo()
This change also invents sigcountset() and strsignal_r() and improves the quality of siginfo_t handling.
This commit is contained in:
		
							parent
							
								
									7ae556463a
								
							
						
					
					
						commit
						467a332e38
					
				
					 41 changed files with 887 additions and 345 deletions
				
			
		|  | @ -65,6 +65,13 @@ $(LIBC_CALLS_A).pkg:					\ | |||
| 		$(LIBC_CALLS_A_OBJS)			\
 | ||||
| 		$(foreach x,$(LIBC_CALLS_A_DIRECTDEPS),$($(x)_A).pkg) | ||||
| 
 | ||||
| # we can't use asan because:
 | ||||
| #   siginfo_t memory is owned by kernels
 | ||||
| o/$(MODE)/libc/calls/siginfo2cosmo.o: private		\ | ||||
| 		OVERRIDE_COPTS +=			\
 | ||||
| 			-ffreestanding			\
 | ||||
| 			-fno-sanitize=address | ||||
| 
 | ||||
| # we can't use asan because:
 | ||||
| #   ucontext_t memory is owned by xnu kernel
 | ||||
| o/$(MODE)/libc/calls/sigenter-xnu.o: private		\ | ||||
|  |  | |||
|  | @ -556,6 +556,7 @@ static const uint16_t kPledgeStdio[] = { | |||
|     __NR_linux_prlimit | STDIO,    //
 | ||||
|     __NR_linux_sched_getaffinity,  //
 | ||||
|     __NR_linux_sched_setaffinity,  //
 | ||||
|     __NR_linux_sigtimedwait,       //
 | ||||
| }; | ||||
| 
 | ||||
| static const uint16_t kPledgeFlock[] = { | ||||
|  |  | |||
|  | @ -22,6 +22,7 @@ | |||
| #include "libc/calls/struct/sigaction-freebsd.internal.h" | ||||
| #include "libc/calls/struct/sigaction.h" | ||||
| #include "libc/calls/struct/siginfo-freebsd.internal.h" | ||||
| #include "libc/calls/struct/siginfo-meta.internal.h" | ||||
| #include "libc/calls/struct/siginfo.h" | ||||
| #include "libc/calls/struct/ucontext-freebsd.internal.h" | ||||
| #include "libc/calls/ucontext.h" | ||||
|  | @ -75,16 +76,7 @@ privileged void __sigenter_freebsd(int sig, struct siginfo_freebsd *freebsdinfo, | |||
|       g.uc.uc_mcontext.err = ctx->uc_mcontext.mc_err; | ||||
|       g.uc.uc_mcontext.trapno = ctx->uc_mcontext.mc_trapno; | ||||
|       __repmovsb(&g.uc.__fpustate, &ctx->uc_mcontext.mc_fpstate, 512); | ||||
|       g.si.si_signo = freebsdinfo->si_signo; | ||||
|       g.si.si_errno = freebsdinfo->si_errno; | ||||
|       g.si.si_code = freebsdinfo->si_code; | ||||
|       if (freebsdinfo->si_pid) { | ||||
|         g.si.si_pid = freebsdinfo->si_pid; | ||||
|         g.si.si_uid = freebsdinfo->si_uid; | ||||
|       } else { | ||||
|         g.si.si_addr = (void *)freebsdinfo->si_addr; | ||||
|       } | ||||
|       g.si.si_value = freebsdinfo->si_value; | ||||
|       __siginfo2cosmo(&g.si, (void *)freebsdinfo); | ||||
|       ((sigaction_f)(_base + rva))(sig, &g.si, &g.uc); | ||||
|       ctx->uc_stack.ss_sp = g.uc.uc_stack.ss_sp; | ||||
|       ctx->uc_stack.ss_size = g.uc.uc_stack.ss_size; | ||||
|  |  | |||
|  | @ -21,6 +21,7 @@ | |||
| #include "libc/calls/state.internal.h" | ||||
| #include "libc/calls/struct/sigaction-freebsd.internal.h" | ||||
| #include "libc/calls/struct/sigaction.h" | ||||
| #include "libc/calls/struct/siginfo-meta.internal.h" | ||||
| #include "libc/calls/struct/siginfo-netbsd.internal.h" | ||||
| #include "libc/calls/struct/siginfo.h" | ||||
| #include "libc/calls/struct/ucontext-netbsd.internal.h" | ||||
|  | @ -43,13 +44,7 @@ privileged void __sigenter_netbsd(int sig, struct siginfo_netbsd *si, | |||
|       ((sigaction_f)(_base + rva))(sig, 0, 0); | ||||
|     } else { | ||||
|       __repstosb(&uc, 0, sizeof(uc)); | ||||
|       __repstosb(&si2, 0, sizeof(si2)); | ||||
|       si2.si_signo = si->si_signo; | ||||
|       si2.si_code = si->si_code; | ||||
|       si2.si_errno = si->si_errno; | ||||
|       si2.si_pid = si->si_pid; | ||||
|       si2.si_uid = si->si_uid; | ||||
|       si2.si_value = si->si_value; | ||||
|       __siginfo2cosmo(&si2, (void *)si); | ||||
|       uc.uc_mcontext.fpregs = &uc.__fpustate; | ||||
|       uc.uc_flags = ctx->uc_flags; | ||||
|       uc.uc_stack.ss_sp = ctx->uc_stack.ss_sp; | ||||
|  |  | |||
|  | @ -21,6 +21,7 @@ | |||
| #include "libc/calls/state.internal.h" | ||||
| #include "libc/calls/struct/sigaction-freebsd.internal.h" | ||||
| #include "libc/calls/struct/sigaction.h" | ||||
| #include "libc/calls/struct/siginfo-meta.internal.h" | ||||
| #include "libc/calls/struct/siginfo-openbsd.internal.h" | ||||
| #include "libc/calls/struct/siginfo.h" | ||||
| #include "libc/calls/struct/ucontext-openbsd.internal.h" | ||||
|  | @ -44,17 +45,8 @@ privileged void __sigenter_openbsd(int sig, struct siginfo_openbsd *openbsdinfo, | |||
|     if (~flags & SA_SIGINFO) { | ||||
|       ((sigaction_f)(_base + rva))(sig, 0, 0); | ||||
|     } else { | ||||
|       __repstosb(&g, 0, sizeof(g)); | ||||
|       g.si.si_signo = openbsdinfo->si_signo; | ||||
|       g.si.si_code = openbsdinfo->si_code; | ||||
|       g.si.si_errno = openbsdinfo->si_errno; | ||||
|       if (openbsdinfo->si_pid) { | ||||
|         g.si.si_pid = openbsdinfo->si_pid; | ||||
|         g.si.si_uid = openbsdinfo->si_uid; | ||||
|       } else { | ||||
|         g.si.si_addr = (void *)openbsdinfo->si_addr; | ||||
|       } | ||||
|       g.si.si_value = openbsdinfo->si_value; | ||||
|       __repstosb(&g.uc, 0, sizeof(g.uc)); | ||||
|       __siginfo2cosmo(&g.si, (void *)openbsdinfo); | ||||
|       g.uc.uc_mcontext.fpregs = &g.uc.__fpustate; | ||||
|       __repmovsb(&g.uc.uc_sigmask, &ctx->sc_mask, | ||||
|                  MIN(sizeof(g.uc.uc_sigmask), sizeof(ctx->sc_mask))); | ||||
|  |  | |||
|  | @ -21,6 +21,7 @@ | |||
| #include "libc/calls/state.internal.h" | ||||
| #include "libc/calls/struct/metasigaltstack.h" | ||||
| #include "libc/calls/struct/sigaction.h" | ||||
| #include "libc/calls/struct/siginfo-meta.internal.h" | ||||
| #include "libc/calls/struct/siginfo-xnu.internal.h" | ||||
| #include "libc/calls/struct/siginfo.h" | ||||
| #include "libc/calls/ucontext.h" | ||||
|  | @ -492,16 +493,7 @@ privileged void __sigenter_xnu(void *fn, int infostyle, int sig, | |||
|         } | ||||
|       } | ||||
|       if (xnuinfo) { | ||||
|         g.si.si_signo = xnuinfo->si_signo; | ||||
|         g.si.si_errno = xnuinfo->si_errno; | ||||
|         g.si.si_code = xnuinfo->si_code; | ||||
|         if (xnuinfo->si_pid) { | ||||
|           g.si.si_pid = xnuinfo->si_pid; | ||||
|           g.si.si_uid = xnuinfo->si_uid; | ||||
|         } else { | ||||
|           g.si.si_addr = (void *)xnuinfo->si_addr; | ||||
|         } | ||||
|         g.si.si_value = xnuinfo->si_value; | ||||
|         __siginfo2cosmo(&g.si, (void *)xnuinfo); | ||||
|       } | ||||
|       ((sigaction_f)(_base + rva))(sig, &g.si, &g.uc); | ||||
|       if (xnuctx) { | ||||
|  |  | |||
							
								
								
									
										106
									
								
								libc/calls/siginfo2cosmo.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										106
									
								
								libc/calls/siginfo2cosmo.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,106 @@ | |||
| /*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
 | ||||
| │vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│ | ||||
| ╞══════════════════════════════════════════════════════════════════════════════╡ | ||||
| │ Copyright 2022 Justine Alexandra Roberts Tunney                              │ | ||||
| │                                                                              │ | ||||
| │ Permission to use, copy, modify, and/or distribute this software for         │ | ||||
| │ any purpose with or without fee is hereby granted, provided that the         │ | ||||
| │ above copyright notice and this permission notice appear in all copies.      │ | ||||
| │                                                                              │ | ||||
| │ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │ | ||||
| │ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │ | ||||
| │ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │ | ||||
| │ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │ | ||||
| │ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │ | ||||
| │ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │ | ||||
| │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │ | ||||
| │ PERFORMANCE OF THIS SOFTWARE.                                                │ | ||||
| ╚─────────────────────────────────────────────────────────────────────────────*/ | ||||
| #include "libc/calls/struct/siginfo-meta.internal.h" | ||||
| #include "libc/calls/struct/siginfo.h" | ||||
| #include "libc/dce.h" | ||||
| #include "libc/sysv/consts/sig.h" | ||||
| 
 | ||||
| privileged void __siginfo2cosmo(struct siginfo *si, | ||||
|                                 const union siginfo_meta *m) { | ||||
|   void *si_addr; | ||||
|   int32_t si_signo; | ||||
|   int32_t si_errno; | ||||
|   int32_t si_code; | ||||
|   int32_t si_pid; | ||||
|   int32_t si_uid; | ||||
|   int32_t si_status; | ||||
|   int32_t si_timerid; | ||||
|   int32_t si_overrun; | ||||
|   union sigval si_value; | ||||
| 
 | ||||
|   if (IsLinux()) { | ||||
|     *si = m->linux; | ||||
|     return; | ||||
|   } else if (IsFreebsd()) { | ||||
|     si_signo = m->freebsd.si_signo; | ||||
|     si_errno = m->freebsd.si_errno; | ||||
|     si_code = m->freebsd.si_code; | ||||
|     si_pid = m->freebsd.si_pid; | ||||
|     si_uid = m->freebsd.si_uid; | ||||
|     si_status = m->freebsd.si_status; | ||||
|     si_timerid = m->freebsd.si_timerid; | ||||
|     si_overrun = m->freebsd.si_overrun; | ||||
|     si_addr = m->freebsd.si_addr; | ||||
|     si_value = m->freebsd.si_value; | ||||
|   } else if (IsXnu()) { | ||||
|     si_signo = m->xnu.si_signo; | ||||
|     si_errno = m->xnu.si_errno; | ||||
|     si_code = m->xnu.si_code; | ||||
|     si_pid = m->xnu.si_pid; | ||||
|     si_uid = m->xnu.si_uid; | ||||
|     si_status = m->xnu.si_status; | ||||
|     si_timerid = 0; | ||||
|     si_overrun = 0; | ||||
|     si_addr = m->xnu.si_addr; | ||||
|     si_value = m->xnu.si_value; | ||||
|   } else if (IsOpenbsd()) { | ||||
|     si_signo = m->openbsd.si_signo; | ||||
|     si_errno = m->openbsd.si_errno; | ||||
|     si_code = m->openbsd.si_code; | ||||
|     si_pid = m->openbsd.si_pid; | ||||
|     si_uid = m->openbsd.si_uid; | ||||
|     si_status = m->openbsd.si_status; | ||||
|     si_timerid = 0; | ||||
|     si_overrun = 0; | ||||
|     si_addr = m->openbsd.si_addr; | ||||
|     si_value = m->openbsd.si_value; | ||||
|   } else if (IsNetbsd()) { | ||||
|     si_signo = m->netbsd.si_signo; | ||||
|     si_errno = m->netbsd.si_errno; | ||||
|     si_code = m->netbsd.si_code; | ||||
|     si_pid = m->netbsd.si_pid; | ||||
|     si_uid = m->netbsd.si_uid; | ||||
|     si_status = m->netbsd.si_status; | ||||
|     si_timerid = 0; | ||||
|     si_overrun = 0; | ||||
|     si_addr = m->netbsd.si_addr; | ||||
|     si_value = m->netbsd.si_value; | ||||
|   } else { | ||||
|     notpossible; | ||||
|   } | ||||
| 
 | ||||
|   *si = (struct siginfo){0}; | ||||
|   si->si_signo = si_signo; | ||||
|   si->si_errno = si_errno; | ||||
|   si->si_code = si_code; | ||||
|   si->si_value = si_value; | ||||
|   if (si_signo == SIGILL ||   //
 | ||||
|       si_signo == SIGFPE ||   //
 | ||||
|       si_signo == SIGSEGV ||  //
 | ||||
|       si_signo == SIGBUS ||   //
 | ||||
|       si_signo == SIGTRAP) { | ||||
|     si->si_addr = si_addr; | ||||
|   } else if (si_signo == SIGALRM) { | ||||
|     si->si_timerid = si_timerid; | ||||
|     si->si_overrun = si_overrun; | ||||
|   } else { | ||||
|     si->si_pid = si_pid; | ||||
|     si->si_uid = si_uid; | ||||
|   } | ||||
| } | ||||
|  | @ -17,37 +17,44 @@ | |||
| │ PERFORMANCE OF THIS SOFTWARE.                                                │ | ||||
| ╚─────────────────────────────────────────────────────────────────────────────*/ | ||||
| #include "libc/calls/sig.internal.h" | ||||
| #include "libc/intrin/strace.internal.h" | ||||
| #include "libc/calls/struct/sigset.h" | ||||
| #include "libc/calls/struct/sigset.internal.h" | ||||
| #include "libc/dce.h" | ||||
| #include "libc/intrin/asan.internal.h" | ||||
| #include "libc/intrin/describeflags.internal.h" | ||||
| #include "libc/intrin/strace.internal.h" | ||||
| #include "libc/sysv/errfuns.h" | ||||
| 
 | ||||
| /**
 | ||||
|  * Determines the blocked pending signals | ||||
|  * | ||||
|  * @param pending is where the bitset of pending signals is returned, | ||||
|  *     may not be NULL. | ||||
|  * @return -1 w/ EFAULT | ||||
|  *     which may not be null | ||||
|  * @return 0 on success, or -1 w/ errno | ||||
|  * @raise EFAULT if `pending` points to invalid memory | ||||
|  * @asyncsignalsafe | ||||
|  */ | ||||
| int sigpending(sigset_t *pending) { | ||||
|   int rc; | ||||
|   if (IsAsan() && !__asan_is_valid(pending, sizeof(*pending))) { | ||||
|   if (!pending || (IsAsan() && !__asan_is_valid(pending, sizeof(*pending)))) { | ||||
|     rc = efault(); | ||||
|   } else if (IsLinux() || IsNetbsd() || IsOpenbsd() || IsFreebsd() || IsXnu()) { | ||||
|     // 128 signals on NetBSD and FreeBSD, 64 on Linux, 32 on OpenBSD and XNU
 | ||||
|     rc = sys_sigpending(pending, 8); | ||||
|     // 128 signals on NetBSD and FreeBSD, 64 on Linux, 32 on OpenBSD and XNU.
 | ||||
|     // OpenBSD passes signal sets in words rather than pointers
 | ||||
|     if (IsOpenbsd()) { | ||||
|       pending->__bits[0] = (unsigned)rc; | ||||
|       rc = 0; | ||||
|     } else if (IsXnu()) { | ||||
|       pending->__bits[0] &= 0xFFFFFFFF; | ||||
|     } | ||||
|     if (IsLinux() || IsOpenbsd() || IsXnu()) { | ||||
|       pending->__bits[1] = 0; | ||||
|     // only modify memory on success
 | ||||
|     if (!rc) { | ||||
|       // clear unsupported bits
 | ||||
|       if (IsXnu()) { | ||||
|         pending->__bits[0] &= 0xFFFFFFFF; | ||||
|       } | ||||
|       if (IsLinux() || IsOpenbsd() || IsXnu()) { | ||||
|         pending->__bits[1] = 0; | ||||
|       } | ||||
|     } | ||||
|   } else if (IsWindows()) { | ||||
|     sigemptyset(pending); | ||||
|  |  | |||
							
								
								
									
										75
									
								
								libc/calls/sigtimedwait.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								libc/calls/sigtimedwait.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,75 @@ | |||
| /*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
 | ||||
| │vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│ | ||||
| ╞══════════════════════════════════════════════════════════════════════════════╡ | ||||
| │ Copyright 2022 Justine Alexandra Roberts Tunney                              │ | ||||
| │                                                                              │ | ||||
| │ Permission to use, copy, modify, and/or distribute this software for         │ | ||||
| │ any purpose with or without fee is hereby granted, provided that the         │ | ||||
| │ above copyright notice and this permission notice appear in all copies.      │ | ||||
| │                                                                              │ | ||||
| │ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │ | ||||
| │ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │ | ||||
| │ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │ | ||||
| │ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │ | ||||
| │ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │ | ||||
| │ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │ | ||||
| │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │ | ||||
| │ PERFORMANCE OF THIS SOFTWARE.                                                │ | ||||
| ╚─────────────────────────────────────────────────────────────────────────────*/ | ||||
| #include "libc/calls/asan.internal.h" | ||||
| #include "libc/calls/sigtimedwait.h" | ||||
| #include "libc/calls/sigtimedwait.internal.h" | ||||
| #include "libc/calls/struct/siginfo.internal.h" | ||||
| #include "libc/calls/struct/sigset.internal.h" | ||||
| #include "libc/calls/struct/timespec.internal.h" | ||||
| #include "libc/dce.h" | ||||
| #include "libc/intrin/asan.internal.h" | ||||
| #include "libc/intrin/strace.internal.h" | ||||
| #include "libc/str/str.h" | ||||
| #include "libc/sysv/errfuns.h" | ||||
| 
 | ||||
| /**
 | ||||
|  * Waits for signal synchronously, w/ timeout. | ||||
|  * | ||||
|  * @param set is signals for which we'll be waiting | ||||
|  * @param info if not null shall receive info about signal | ||||
|  * @param timeout is relative deadline and null means wait forever | ||||
|  * @return signal number on success, or -1 w/ errno | ||||
|  * @raise EINTR if an asynchronous signal was delivered instead | ||||
|  * @raise EINVAL if nanoseconds parameter was out of range | ||||
|  * @raise EAGAIN if deadline expired | ||||
|  * @raise ENOSYS on Windows, XNU, OpenBSD, Metal | ||||
|  * @raise EFAULT if invalid memory was supplied | ||||
|  */ | ||||
| int sigtimedwait(const sigset_t *set, siginfo_t *info, | ||||
|                  const struct timespec *timeout) { | ||||
|   int rc; | ||||
|   char strsig[15]; | ||||
|   struct timespec ts; | ||||
|   union siginfo_meta si = {0}; | ||||
| 
 | ||||
|   if (IsAsan() && (!__asan_is_valid(set, sizeof(*set)) || | ||||
|                    (info && !__asan_is_valid(info, sizeof(*info))) || | ||||
|                    (timeout && !__asan_is_valid_timespec(timeout)))) { | ||||
|     rc = efault(); | ||||
|   } else if (IsLinux() || IsFreebsd() || IsNetbsd()) { | ||||
|     if (timeout) { | ||||
|       // 1. Linux needs its size parameter
 | ||||
|       // 2. NetBSD modifies timeout argument
 | ||||
|       ts = *timeout; | ||||
|       rc = sys_sigtimedwait(set, &si, &ts, 8); | ||||
|     } else { | ||||
|       rc = sys_sigtimedwait(set, &si, 0, 8); | ||||
|     } | ||||
|     if (rc != -1 && info) { | ||||
|       __siginfo2cosmo(info, &si); | ||||
|     } | ||||
|   } else { | ||||
|     rc = enosys(); | ||||
|   } | ||||
| 
 | ||||
|   STRACE("sigtimedwait(%s, [%s], %s) → %s% m", DescribeSigset(0, set), | ||||
|          DescribeSiginfo(rc, info), DescribeTimespec(0, timeout), | ||||
|          strsignal_r(rc, strsig)); | ||||
|   return rc; | ||||
| } | ||||
							
								
								
									
										14
									
								
								libc/calls/sigtimedwait.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								libc/calls/sigtimedwait.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,14 @@ | |||
| #ifndef COSMOPOLITAN_LIBC_CALLS_SIGTIMEDWAIT_H_ | ||||
| #define COSMOPOLITAN_LIBC_CALLS_SIGTIMEDWAIT_H_ | ||||
| #include "libc/calls/struct/siginfo.h" | ||||
| #include "libc/calls/struct/sigset.h" | ||||
| #include "libc/calls/struct/timespec.h" | ||||
| #if !(__ASSEMBLER__ + __LINKER__ + 0) | ||||
| COSMOPOLITAN_C_START_ | ||||
| 
 | ||||
| int sigtimedwait(const sigset_t *, siginfo_t *, const struct timespec *); | ||||
| int sigwaitinfo(const sigset_t *, siginfo_t *); | ||||
| 
 | ||||
| COSMOPOLITAN_C_END_ | ||||
| #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ | ||||
| #endif /* COSMOPOLITAN_LIBC_CALLS_SIGTIMEDWAIT_H_ */ | ||||
							
								
								
									
										14
									
								
								libc/calls/sigtimedwait.internal.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								libc/calls/sigtimedwait.internal.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,14 @@ | |||
| #ifndef COSMOPOLITAN_LIBC_CALLS_SIGTIMEDWAIT_INTERNAL_H_ | ||||
| #define COSMOPOLITAN_LIBC_CALLS_SIGTIMEDWAIT_INTERNAL_H_ | ||||
| #include "libc/calls/struct/siginfo-meta.internal.h" | ||||
| #include "libc/calls/struct/sigset.h" | ||||
| #include "libc/calls/struct/timespec.h" | ||||
| #if !(__ASSEMBLER__ + __LINKER__ + 0) | ||||
| COSMOPOLITAN_C_START_ | ||||
| 
 | ||||
| int sys_sigtimedwait(const sigset_t *, union siginfo_meta *, | ||||
|                      const struct timespec *, size_t) hidden; | ||||
| 
 | ||||
| COSMOPOLITAN_C_END_ | ||||
| #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ | ||||
| #endif /* COSMOPOLITAN_LIBC_CALLS_SIGTIMEDWAIT_INTERNAL_H_ */ | ||||
							
								
								
									
										33
									
								
								libc/calls/sigwaitinfo.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								libc/calls/sigwaitinfo.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,33 @@ | |||
| /*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
 | ||||
| │vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│ | ||||
| ╞══════════════════════════════════════════════════════════════════════════════╡ | ||||
| │ Copyright 2022 Justine Alexandra Roberts Tunney                              │ | ||||
| │                                                                              │ | ||||
| │ Permission to use, copy, modify, and/or distribute this software for         │ | ||||
| │ any purpose with or without fee is hereby granted, provided that the         │ | ||||
| │ above copyright notice and this permission notice appear in all copies.      │ | ||||
| │                                                                              │ | ||||
| │ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │ | ||||
| │ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │ | ||||
| │ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │ | ||||
| │ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │ | ||||
| │ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │ | ||||
| │ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │ | ||||
| │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │ | ||||
| │ PERFORMANCE OF THIS SOFTWARE.                                                │ | ||||
| ╚─────────────────────────────────────────────────────────────────────────────*/ | ||||
| #include "libc/calls/sigtimedwait.h" | ||||
| 
 | ||||
| /**
 | ||||
|  * Waits for signal synchronously. | ||||
|  * | ||||
|  * @param set is signals for which we'll be waiting | ||||
|  * @param info if not null shall receive info about signal | ||||
|  * @return signal number on success, or -1 w/ errno | ||||
|  * @raise EINTR if an asynchronous signal was delivered instead | ||||
|  * @raise ENOSYS on OpenBSD, XNU, and Windows | ||||
|  * @see sigtimedwait() | ||||
|  */ | ||||
| int sigwaitinfo(const sigset_t *mask, siginfo_t *si) { | ||||
|   return sigtimedwait(mask, si, 0); | ||||
| } | ||||
							
								
								
									
										23
									
								
								libc/calls/struct/siginfo-meta.internal.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								libc/calls/struct/siginfo-meta.internal.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,23 @@ | |||
| #ifndef COSMOPOLITAN_LIBC_CALLS_STRUCT_SIGINFO_META_INTERNAL_H_ | ||||
| #define COSMOPOLITAN_LIBC_CALLS_STRUCT_SIGINFO_META_INTERNAL_H_ | ||||
| #include "libc/calls/struct/siginfo-freebsd.internal.h" | ||||
| #include "libc/calls/struct/siginfo-netbsd.internal.h" | ||||
| #include "libc/calls/struct/siginfo-openbsd.internal.h" | ||||
| #include "libc/calls/struct/siginfo-xnu.internal.h" | ||||
| #include "libc/calls/struct/siginfo.h" | ||||
| #if !(__ASSEMBLER__ + __LINKER__ + 0) | ||||
| COSMOPOLITAN_C_START_ | ||||
| 
 | ||||
| union siginfo_meta { | ||||
|   struct siginfo linux; | ||||
|   struct siginfo_xnu xnu; | ||||
|   struct siginfo_freebsd freebsd; | ||||
|   struct siginfo_openbsd openbsd; | ||||
|   struct siginfo_netbsd netbsd; | ||||
| }; | ||||
| 
 | ||||
| void __siginfo2cosmo(struct siginfo *, const union siginfo_meta *) hidden; | ||||
| 
 | ||||
| COSMOPOLITAN_C_END_ | ||||
| #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ | ||||
| #endif /* COSMOPOLITAN_LIBC_CALLS_STRUCT_SIGINFO_META_INTERNAL_H_ */ | ||||
|  | @ -12,11 +12,13 @@ struct siginfo { | |||
|     struct { | ||||
|       union { | ||||
|         struct { | ||||
|           /* signals sent by kill() and sigqueue() set these */ | ||||
|           int32_t si_pid; | ||||
|           uint32_t si_uid; | ||||
|         }; | ||||
|         struct { | ||||
|           int32_t si_timerid; /* SIGALRM */ | ||||
|           /* SIGALRM sets these */ | ||||
|           int32_t si_timerid; | ||||
|           int32_t si_overrun; | ||||
|         }; | ||||
|       }; | ||||
|  |  | |||
|  | @ -3,6 +3,7 @@ | |||
| #include "libc/calls/struct/sigaction-xnu.internal.h" | ||||
| #include "libc/calls/struct/siginfo-xnu.internal.h" | ||||
| #include "libc/calls/struct/siginfo.h" | ||||
| #include "libc/mem/alloca.h" | ||||
| #if !(__ASSEMBLER__ + __LINKER__ + 0) | ||||
| COSMOPOLITAN_C_START_ | ||||
| 
 | ||||
|  | @ -10,6 +11,9 @@ int sys_sigqueueinfo(int, const siginfo_t *) hidden; | |||
| void __sigenter_xnu(void *, int, int, struct siginfo_xnu *, | ||||
|                     struct __darwin_ucontext *) hidden; | ||||
| 
 | ||||
| const char *DescribeSiginfo(char[300], int, const siginfo_t *); | ||||
| #define DescribeSiginfo(x, y) DescribeSiginfo(alloca(300), x, y) | ||||
| 
 | ||||
| COSMOPOLITAN_C_END_ | ||||
| #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ | ||||
| #endif /* COSMOPOLITAN_LIBC_CALLS_STRUCT_SIGINFO_INTERNAL_H_ */ | ||||
|  |  | |||
|  | @ -13,11 +13,12 @@ int sigemptyset(sigset_t *) paramsnonnull(); | |||
| int sigfillset(sigset_t *) paramsnonnull(); | ||||
| int sigandset(sigset_t *, const sigset_t *, const sigset_t *) paramsnonnull(); | ||||
| int sigorset(sigset_t *, const sigset_t *, const sigset_t *) paramsnonnull(); | ||||
| int sigisemptyset(const sigset_t *) paramsnonnull(); | ||||
| int sigisemptyset(const sigset_t *) paramsnonnull() nosideeffect; | ||||
| int sigismember(const sigset_t *, int) paramsnonnull() nosideeffect; | ||||
| int sigcountset(const sigset_t *) paramsnonnull() nosideeffect; | ||||
| int sigprocmask(int, const sigset_t *, sigset_t *); | ||||
| int sigsuspend(const sigset_t *); | ||||
| int sigpending(sigset_t *) paramsnonnull() nosideeffect; | ||||
| int sigpending(sigset_t *); | ||||
| int pthread_sigmask(int, const sigset_t *, sigset_t *); | ||||
| 
 | ||||
| COSMOPOLITAN_C_END_ | ||||
|  |  | |||
							
								
								
									
										28
									
								
								libc/intrin/describeerrno.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								libc/intrin/describeerrno.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,28 @@ | |||
| /*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
 | ||||
| │vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│ | ||||
| ╞══════════════════════════════════════════════════════════════════════════════╡ | ||||
| │ Copyright 2022 Justine Alexandra Roberts Tunney                              │ | ||||
| │                                                                              │ | ||||
| │ Permission to use, copy, modify, and/or distribute this software for         │ | ||||
| │ any purpose with or without fee is hereby granted, provided that the         │ | ||||
| │ above copyright notice and this permission notice appear in all copies.      │ | ||||
| │                                                                              │ | ||||
| │ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │ | ||||
| │ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │ | ||||
| │ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │ | ||||
| │ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │ | ||||
| │ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │ | ||||
| │ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │ | ||||
| │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │ | ||||
| │ PERFORMANCE OF THIS SOFTWARE.                                                │ | ||||
| ╚─────────────────────────────────────────────────────────────────────────────*/ | ||||
| #include "libc/fmt/itoa.h" | ||||
| #include "libc/intrin/describeflags.internal.h" | ||||
| #include "libc/str/str.h" | ||||
| 
 | ||||
| const char *(DescribeErrno)(char buf[12], int x) { | ||||
|   const char *s; | ||||
|   if ((s = _strerrno(x))) return s; | ||||
|   FormatInt32(buf, x); | ||||
|   return buf; | ||||
| } | ||||
|  | @ -16,6 +16,7 @@ const char *DescribeArchPrctlCode(char[12], int); | |||
| const char *DescribeCapability(char[20], int); | ||||
| const char *DescribeClockName(char[32], int); | ||||
| const char *DescribeDirfd(char[12], int); | ||||
| const char *DescribeErrno(char[12], int); | ||||
| const char *DescribeErrnoResult(char[12], int); | ||||
| const char *DescribeFrame(char[32], int); | ||||
| const char *DescribeFutexOp(char[64], int); | ||||
|  | @ -50,6 +51,7 @@ const char *DescribeRemapFlags(char[48], int); | |||
| const char *DescribeRlimitName(char[20], int); | ||||
| const char *DescribeSchedPolicy(char[48], int); | ||||
| const char *DescribeSeccompOperation(int); | ||||
| const char *DescribeSiCode(char[17], int, int); | ||||
| const char *DescribeSleepFlags(char[16], int); | ||||
| const char *DescribeSockLevel(char[12], int); | ||||
| const char *DescribeSockOptname(char[32], int, int); | ||||
|  | @ -63,6 +65,7 @@ const char *DescribeWhence(char[12], int); | |||
| #define DescribeCapability(x)        DescribeCapability(alloca(20), x) | ||||
| #define DescribeClockName(x)         DescribeClockName(alloca(32), x) | ||||
| #define DescribeDirfd(x)             DescribeDirfd(alloca(12), x) | ||||
| #define DescribeErrno(x)             DescribeErrno(alloca(12), x) | ||||
| #define DescribeErrnoResult(x)       DescribeErrnoResult(alloca(12), x) | ||||
| #define DescribeFrame(x)             DescribeFrame(alloca(32), x) | ||||
| #define DescribeFutexOp(x)           DescribeFutexOp(alloca(64), x) | ||||
|  | @ -94,6 +97,7 @@ const char *DescribeWhence(char[12], int); | |||
| #define DescribeRemapFlags(x)        DescribeRemapFlags(alloca(48), x) | ||||
| #define DescribeRlimitName(rl)       DescribeRlimitName(alloca(20), rl) | ||||
| #define DescribeSchedPolicy(x)       DescribeSchedPolicy(alloca(48), x) | ||||
| #define DescribeSiCode(x, y)         DescribeSiCode(alloca(17), x, y) | ||||
| #define DescribeSleepFlags(x)        DescribeSleepFlags(alloca(16), x) | ||||
| #define DescribeSockLevel(x)         DescribeSockLevel(alloca(12), x) | ||||
| #define DescribeSockOptname(x, y)    DescribeSockOptname(alloca(32), x, y) | ||||
|  |  | |||
							
								
								
									
										167
									
								
								libc/intrin/describesicode.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										167
									
								
								libc/intrin/describesicode.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,167 @@ | |||
| /*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
 | ||||
| │vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│ | ||||
| ╞══════════════════════════════════════════════════════════════════════════════╡ | ||||
| │ Copyright 2022 Justine Alexandra Roberts Tunney                              │ | ||||
| │                                                                              │ | ||||
| │ Permission to use, copy, modify, and/or distribute this software for         │ | ||||
| │ any purpose with or without fee is hereby granted, provided that the         │ | ||||
| │ above copyright notice and this permission notice appear in all copies.      │ | ||||
| │                                                                              │ | ||||
| │ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │ | ||||
| │ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │ | ||||
| │ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │ | ||||
| │ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │ | ||||
| │ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │ | ||||
| │ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │ | ||||
| │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │ | ||||
| │ PERFORMANCE OF THIS SOFTWARE.                                                │ | ||||
| ╚─────────────────────────────────────────────────────────────────────────────*/ | ||||
| #include "libc/dce.h" | ||||
| #include "libc/fmt/itoa.h" | ||||
| #include "libc/str/str.h" | ||||
| #include "libc/sysv/consts/sicode.h" | ||||
| #include "libc/sysv/consts/sig.h" | ||||
| 
 | ||||
| static bool IsSiUser(int si_code) { | ||||
|   if (!IsOpenbsd()) { | ||||
|     return si_code == SI_USER; | ||||
|   } else { | ||||
|     return si_code <= 0; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| static void NameIt(char p[17], const char *s, int si_code) { | ||||
|   p = stpcpy(p, s); | ||||
|   FormatInt32(p, si_code); | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * Returns symbolic name for siginfo::si_code value. | ||||
|  */ | ||||
| const char *(DescribeSiCode)(char b[17], int sig, int si_code) { | ||||
|   NameIt(b, "SI_", si_code); | ||||
|   if (si_code == SI_QUEUE) { | ||||
|     strcpy(b + 3, "QUEUE"); /* sent by sigqueue(2) */ | ||||
|   } else if (si_code == SI_TIMER) { | ||||
|     strcpy(b + 3, "TIMER"); /* sent by setitimer(2) or clock_settime(2) */ | ||||
|   } else if (si_code == SI_TKILL) { | ||||
|     strcpy(b + 3, "TKILL"); /* sent by tkill(2), etc. */ | ||||
|   } else if (si_code == SI_MESGQ) { | ||||
|     strcpy(b + 3, "MESGQ"); /* sent by mq_notify(2) */ | ||||
|   } else if (si_code == SI_MESGQ) { | ||||
|     strcpy(b + 3, "MESGQ"); /* aio completion */ | ||||
|   } else if (si_code == SI_ASYNCNL) { | ||||
|     strcpy(b + 3, "ASYNCNL"); /* aio completion for dns; the horror */ | ||||
|   } else if (si_code == SI_NOINFO) { | ||||
|     strcpy(b + 3, "NOINFO"); /* no signal specific info available */ | ||||
|   } else if (si_code == SI_KERNEL) { | ||||
|     strcpy(b + 3, "KERNEL"); /* sent by kernel */ | ||||
|   } else if (IsSiUser(si_code)) { | ||||
|     strcpy(b + 3, "USER"); /* sent by kill(2) i.e. from userspace */ | ||||
|   } else if (sig == SIGCHLD) { | ||||
|     NameIt(b, "CLD_", si_code); | ||||
|     if (si_code == CLD_EXITED) { | ||||
|       strcpy(b + 4, "EXITED"); /* child exited */ | ||||
|     } else if (si_code == CLD_KILLED) { | ||||
|       strcpy(b + 4, "KILLED"); /* child terminated w/o core */ | ||||
|     } else if (si_code == CLD_DUMPED) { | ||||
|       strcpy(b + 4, "DUMPED"); /* child terminated w/ core */ | ||||
|     } else if (si_code == CLD_TRAPPED) { | ||||
|       strcpy(b + 4, "TRAPPED"); /* traced child trapped */ | ||||
|     } else if (si_code == CLD_STOPPED) { | ||||
|       strcpy(b + 4, "STOPPED"); /* child stopped */ | ||||
|     } else if (si_code == CLD_CONTINUED) { | ||||
|       strcpy(b + 4, "CONTINUED"); /* stopped child continued */ | ||||
|     } | ||||
|   } else if (sig == SIGTRAP) { | ||||
|     NameIt(b, "TRAP_", si_code); | ||||
|     if (si_code == TRAP_BRKPT) { | ||||
|       strcpy(b + 5, "BRKPT"); /* process breakpoint */ | ||||
|     } else if (si_code == TRAP_TRACE) { | ||||
|       strcpy(b + 5, "TRACE"); /* process trace trap */ | ||||
|     } | ||||
|   } else if (sig == SIGSEGV) { | ||||
|     NameIt(b, "SEGV_", si_code); | ||||
|     if (si_code == SEGV_MAPERR) { | ||||
|       strcpy(b + 5, "MAPERR"); /* address not mapped to object */ | ||||
|     } else if (si_code == SEGV_ACCERR) { | ||||
|       strcpy(b + 5, "ACCERR"); /* invalid permissions for mapped object */ | ||||
|     } else if (si_code == SEGV_PKUERR) { | ||||
|       strcpy(b + 5, "PKUERR"); /* FreeBSD: x86: PKU violation */ | ||||
|     } | ||||
|   } else if (sig == SIGFPE) { | ||||
|     NameIt(b, "FPE_???", si_code); | ||||
|     if (si_code == FPE_INTDIV) { | ||||
|       strcpy(b + 4, "INTDIV"); /* integer divide by zero */ | ||||
|     } else if (si_code == FPE_INTOVF) { | ||||
|       strcpy(b + 4, "INTOVF"); /* integer overflow */ | ||||
|     } else if (si_code == FPE_FLTDIV) { | ||||
|       strcpy(b + 4, "FLTDIV"); /* floating point divide by zero */ | ||||
|     } else if (si_code == FPE_FLTOVF) { | ||||
|       strcpy(b + 4, "FLTOVF"); /* floating point overflow */ | ||||
|     } else if (si_code == FPE_FLTUND) { | ||||
|       strcpy(b + 4, "FLTUND"); /* floating point underflow */ | ||||
|     } else if (si_code == FPE_FLTRES) { | ||||
|       strcpy(b + 4, "FLTRES"); /* floating point inexact */ | ||||
|     } else if (si_code == FPE_FLTINV) { | ||||
|       strcpy(b + 4, "FLTINV"); /* invalid floating point operation */ | ||||
|     } else if (si_code == FPE_FLTSUB) { | ||||
|       strcpy(b + 4, "FLTSUB"); /* subscript out of range */ | ||||
|     } | ||||
|   } else if (sig == SIGILL) { | ||||
|     NameIt(b, "ILL_", si_code); | ||||
|     if (si_code == ILL_ILLOPC) { | ||||
|       strcpy(b + 4, "ILLOPC"); /* illegal opcode */ | ||||
|     } else if (si_code == ILL_ILLOPN) { | ||||
|       strcpy(b + 4, "ILLOPN"); /* illegal operand */ | ||||
|     } else if (si_code == ILL_ILLADR) { | ||||
|       strcpy(b + 4, "ILLADR"); /* illegal addressing mode */ | ||||
|     } else if (si_code == ILL_ILLTRP) { | ||||
|       strcpy(b + 4, "ILLTRP"); /* illegal trap */ | ||||
|     } else if (si_code == ILL_PRVOPC) { | ||||
|       strcpy(b + 4, "PRVOPC"); /* privileged opcode */ | ||||
|     } else if (si_code == ILL_PRVREG) { | ||||
|       strcpy(b + 4, "PRVREG"); /* privileged register */ | ||||
|     } else if (si_code == ILL_COPROC) { | ||||
|       strcpy(b + 4, "COPROC"); /* coprocessor error */ | ||||
|     } else if (si_code == ILL_BADSTK) { | ||||
|       strcpy(b + 4, "BADSTK"); /* internal stack error */ | ||||
|     } | ||||
|   } else if (sig == SIGBUS) { | ||||
|     NameIt(b, "BUS_", si_code); | ||||
|     if (si_code == BUS_ADRALN) { | ||||
|       strcpy(b + 4, "ADRALN"); /* invalid address alignment */ | ||||
|     } else if (si_code == BUS_ADRERR) { | ||||
|       strcpy(b + 4, "ADRERR"); /* non-existent physical address */ | ||||
|     } else if (si_code == BUS_OBJERR) { | ||||
|       strcpy(b + 4, "OBJERR"); /* object specific hardware error */ | ||||
|     } else if (si_code == BUS_OOMERR) { | ||||
|       strcpy(b + 4, "OOMERR"); /* FreeBSD */ | ||||
|     } else if (si_code == BUS_MCEERR_AR) { | ||||
|       strcpy(b + 4, "MCEERR_AR"); /* Linux 2.6.32+ */ | ||||
|     } else if (si_code == BUS_MCEERR_AO) { | ||||
|       strcpy(b + 4, "MCEERR_AO"); /* Linux 2.6.32+ */ | ||||
|     } | ||||
|   } else if (sig == SIGIO) { | ||||
|     NameIt(b, "POLL_", si_code); | ||||
|     if (si_code == POLL_IN) { | ||||
|       strcpy(b + 5, "IN"); /* data input available */ | ||||
|     } else if (si_code == POLL_OUT) { | ||||
|       strcpy(b + 5, "OUT"); /* output buffer available */ | ||||
|     } else if (si_code == POLL_MSG) { | ||||
|       strcpy(b + 5, "MSG"); /* input message available */ | ||||
|     } else if (si_code == POLL_ERR) { | ||||
|       strcpy(b + 5, "ERR"); /* i/o error */ | ||||
|     } else if (si_code == POLL_PRI) { | ||||
|       strcpy(b + 5, "PRI"); /* high priority input available */ | ||||
|     } else if (si_code == POLL_HUP) { | ||||
|       strcpy(b + 5, "HUP"); /* device disconnected */ | ||||
|     } | ||||
|   } else if (sig == SIGSYS) { | ||||
|     NameIt(b, "SYS_", si_code); | ||||
|     if (si_code == SYS_SECCOMP) { | ||||
|       strcpy(b + 4, "SECCOMP"); | ||||
|     } | ||||
|   } | ||||
|   return b; | ||||
| } | ||||
							
								
								
									
										84
									
								
								libc/intrin/describesiginfo.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								libc/intrin/describesiginfo.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,84 @@ | |||
| /*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
 | ||||
| │vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│ | ||||
| ╞══════════════════════════════════════════════════════════════════════════════╡ | ||||
| │ Copyright 2021 Justine Alexandra Roberts Tunney                              │ | ||||
| │                                                                              │ | ||||
| │ Permission to use, copy, modify, and/or distribute this software for         │ | ||||
| │ any purpose with or without fee is hereby granted, provided that the         │ | ||||
| │ above copyright notice and this permission notice appear in all copies.      │ | ||||
| │                                                                              │ | ||||
| │ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │ | ||||
| │ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │ | ||||
| │ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │ | ||||
| │ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │ | ||||
| │ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │ | ||||
| │ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │ | ||||
| │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │ | ||||
| │ PERFORMANCE OF THIS SOFTWARE.                                                │ | ||||
| ╚─────────────────────────────────────────────────────────────────────────────*/ | ||||
| #include "libc/calls/struct/siginfo.h" | ||||
| #include "libc/calls/struct/siginfo.internal.h" | ||||
| #include "libc/dce.h" | ||||
| #include "libc/intrin/asan.internal.h" | ||||
| #include "libc/intrin/describeflags.internal.h" | ||||
| #include "libc/intrin/kprintf.h" | ||||
| #include "libc/intrin/weaken.h" | ||||
| #include "libc/str/str.h" | ||||
| #include "libc/sysv/consts/sig.h" | ||||
| 
 | ||||
| #define N 300 | ||||
| 
 | ||||
| #define append(...) i += ksnprintf(buf + i, N - i, __VA_ARGS__) | ||||
| 
 | ||||
| const char *(DescribeSiginfo)(char buf[N], int rc, const siginfo_t *si) { | ||||
|   int i = 0; | ||||
| 
 | ||||
|   if (rc == -1) return "n/a"; | ||||
|   if (!si) return "NULL"; | ||||
|   if ((!IsAsan() && kisdangerous(si)) || | ||||
|       (IsAsan() && !__asan_is_valid(si, sizeof(*si)))) { | ||||
|     ksnprintf(buf, N, "%p", si); | ||||
|     return buf; | ||||
|   } | ||||
| 
 | ||||
|   append("{.si_signo=%s, si_code=%s", strsignal(si->si_signo), | ||||
|          DescribeSiCode(si->si_signo, si->si_code)); | ||||
| 
 | ||||
|   if (si->si_errno) { | ||||
|     append(", .si_errno=%s", DescribeErrno(si->si_errno)); | ||||
|   } | ||||
| 
 | ||||
|   if (si->si_signo == SIGILL ||   //
 | ||||
|       si->si_signo == SIGFPE ||   //
 | ||||
|       si->si_signo == SIGSEGV ||  //
 | ||||
|       si->si_signo == SIGBUS ||   //
 | ||||
|       si->si_signo == SIGTRAP) { | ||||
|     append(", .si_addr=%p, .si_addr_lsb=%d, .si_pkey=%u", si->si_addr, | ||||
|            si->si_addr_lsb, si->si_pkey); | ||||
|   } else if (si->si_signo == SIGALRM) { | ||||
|     append(", .si_timerid=%d, .si_overrun=%d", si->si_timerid, si->si_overrun); | ||||
|   } else { | ||||
|     if (si->si_pid) { | ||||
|       append(", .si_pid=%d", si->si_pid); | ||||
|     } | ||||
|     if (si->si_uid) { | ||||
|       append(", .si_uid=%d", si->si_uid); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   if (si->si_status) { | ||||
|     append(", .si_status=%d", si->si_status); | ||||
|   } | ||||
| 
 | ||||
|   if (si->si_utime) { | ||||
|     append(", .si_utime=%d", si->si_utime); | ||||
|   } | ||||
| 
 | ||||
|   if (si->si_stime) { | ||||
|     append(", .si_stime=%d", si->si_stime); | ||||
|   } | ||||
| 
 | ||||
|   append("}"); | ||||
| 
 | ||||
|   return buf; | ||||
| } | ||||
|  | @ -26,9 +26,11 @@ | |||
| 
 | ||||
| #define N 128 | ||||
| 
 | ||||
| #define append(...) i += ksnprintf(buf + i, N - i, __VA_ARGS__) | ||||
| 
 | ||||
| const char *(DescribeSigset)(char buf[N], int rc, const sigset_t *ss) { | ||||
|   bool gotsome; | ||||
|   int i, sig; | ||||
|   bool gotsome; | ||||
|   sigset_t sigset; | ||||
| 
 | ||||
|   if (rc == -1) return "n/a"; | ||||
|  | @ -43,22 +45,22 @@ const char *(DescribeSigset)(char buf[N], int rc, const sigset_t *ss) { | |||
|   sigset = *ss; | ||||
|   gotsome = false; | ||||
|   if (popcnt(sigset.__bits[0] & 0xffffffff) > 16) { | ||||
|     i += ksnprintf(buf + i, N - i, "~"); | ||||
|     append("~"); | ||||
|     sigset.__bits[0] = ~sigset.__bits[0]; | ||||
|     sigset.__bits[1] = ~sigset.__bits[1]; | ||||
|   } | ||||
|   i += ksnprintf(buf + i, N - i, "{"); | ||||
|   append("{"); | ||||
|   for (sig = 1; sig < 32; ++sig) { | ||||
|     if (sigismember(&sigset, sig)) { | ||||
|       if (gotsome) { | ||||
|         i += ksnprintf(buf + i, N - i, ","); | ||||
|         append(","); | ||||
|       } else { | ||||
|         gotsome = true; | ||||
|       } | ||||
|       i += ksnprintf(buf + i, N - i, "%s", strsignal(sig) + 3); | ||||
|       append("%s", strsignal(sig) + 3); | ||||
|     } | ||||
|   } | ||||
|   i += ksnprintf(buf + i, N - i, "}"); | ||||
|   append("}"); | ||||
| 
 | ||||
|   return buf; | ||||
| } | ||||
|  |  | |||
|  | @ -22,67 +22,64 @@ | |||
| #include "libc/intrin/asan.internal.h" | ||||
| #include "libc/intrin/kprintf.h" | ||||
| 
 | ||||
| const char *(DescribeStat)(char buf[300], int rc, const struct stat *st) { | ||||
|   int i, n; | ||||
| #define N 300 | ||||
| 
 | ||||
| #define append(...) i += ksnprintf(buf + i, N - i, __VA_ARGS__) | ||||
| 
 | ||||
| const char *(DescribeStat)(char buf[N], int rc, const struct stat *st) { | ||||
|   int i = 0; | ||||
| 
 | ||||
|   if (rc == -1) return "n/a"; | ||||
|   if (!st) return "NULL"; | ||||
|   if ((!IsAsan() && kisdangerous(st)) || | ||||
|       (IsAsan() && !__asan_is_valid(st, sizeof(*st)))) { | ||||
|     ksnprintf(buf, 300, "%p", st); | ||||
|     ksnprintf(buf, N, "%p", st); | ||||
|     return buf; | ||||
|   } | ||||
| 
 | ||||
|   i = 0; | ||||
|   n = 300; | ||||
| 
 | ||||
|   i += ksnprintf(buf + i, n - i, "{.st_%s=%'ld", "size", st->st_size); | ||||
|   append("{.st_%s=%'ld", "size", st->st_size); | ||||
| 
 | ||||
|   if (st->st_blocks) { | ||||
|     i += | ||||
|         ksnprintf(buf + i, n - i, ", .st_blocks=%'lu/512", st->st_blocks * 512); | ||||
|     append(", .st_blocks=%'lu/512", st->st_blocks * 512); | ||||
|   } | ||||
| 
 | ||||
|   if (st->st_mode) { | ||||
|     i += ksnprintf(buf + i, n - i, ", .st_%s=%#o", "mode", st->st_mode); | ||||
|     append(", .st_%s=%#o", "mode", st->st_mode); | ||||
|   } | ||||
| 
 | ||||
|   if (st->st_nlink != 1) { | ||||
|     i += ksnprintf(buf + i, n - i, ", .st_%s=%'lu", "nlink", st->st_nlink); | ||||
|     append(", .st_%s=%'lu", "nlink", st->st_nlink); | ||||
|   } | ||||
| 
 | ||||
|   if (st->st_uid) { | ||||
|     i += ksnprintf(buf + i, n - i, ", .st_%s=%lu", "uid", st->st_uid); | ||||
|     append(", .st_%s=%lu", "uid", st->st_uid); | ||||
|   } | ||||
| 
 | ||||
|   if (st->st_gid) { | ||||
|     i += ksnprintf(buf + i, n - i, ", .st_%s=%lu", "gid", st->st_gid); | ||||
|     append(", .st_%s=%lu", "gid", st->st_gid); | ||||
|   } | ||||
| 
 | ||||
|   if (st->st_ino) { | ||||
|     i += ksnprintf(buf + i, n - i, ", .st_%s=%lu", "ino", st->st_ino); | ||||
|     append(", .st_%s=%lu", "ino", st->st_ino); | ||||
|   } | ||||
| 
 | ||||
|   if (st->st_gen) { | ||||
|     i += ksnprintf(buf + i, n - i, ", .st_%s=%'lu", "gen", st->st_gen); | ||||
|     append(", .st_%s=%'lu", "gen", st->st_gen); | ||||
|   } | ||||
| 
 | ||||
|   if (st->st_flags) { | ||||
|     i += ksnprintf(buf + i, n - i, ", .st_%s=%lx", "flags", st->st_flags); | ||||
|     append(", .st_%s=%lx", "flags", st->st_flags); | ||||
|   } | ||||
| 
 | ||||
|   if (st->st_rdev) { | ||||
|     i += ksnprintf(buf + i, n - i, ", .st_%s=%'lu", "rdev", st->st_rdev); | ||||
|     append(", .st_%s=%'lu", "rdev", st->st_rdev); | ||||
|   } | ||||
| 
 | ||||
|   if (st->st_blksize != PAGESIZE) { | ||||
|     i += ksnprintf(buf + i, n - i, ", .st_%s=%'lu", "blksize", st->st_blksize); | ||||
|     append(", .st_%s=%'lu", "blksize", st->st_blksize); | ||||
|   } | ||||
| 
 | ||||
|   if (n - i >= 2) { | ||||
|     buf[i + 0] = '}'; | ||||
|     buf[i + 1] = 0; | ||||
|   } | ||||
|   append("}"); | ||||
| 
 | ||||
|   return buf; | ||||
| } | ||||
|  |  | |||
|  | @ -24,8 +24,12 @@ | |||
| #include "libc/intrin/kprintf.h" | ||||
| #include "libc/sysv/consts/st.h" | ||||
| 
 | ||||
| const char *(DescribeStatfs)(char buf[300], int rc, const struct statfs *f) { | ||||
|   int i, n; | ||||
| #define N 300 | ||||
| 
 | ||||
| #define append(...) i += ksnprintf(buf + i, N - i, __VA_ARGS__) | ||||
| 
 | ||||
| const char *(DescribeStatfs)(char buf[N], int rc, const struct statfs *f) { | ||||
|   int i = 0; | ||||
|   char ibuf[21]; | ||||
|   int64_t flags; | ||||
| 
 | ||||
|  | @ -33,90 +37,82 @@ const char *(DescribeStatfs)(char buf[300], int rc, const struct statfs *f) { | |||
|   if (!f) return "NULL"; | ||||
|   if ((!IsAsan() && kisdangerous(f)) || | ||||
|       (IsAsan() && !__asan_is_valid(f, sizeof(*f)))) { | ||||
|     ksnprintf(buf, 300, "%p", f); | ||||
|     ksnprintf(buf, N, "%p", f); | ||||
|     return buf; | ||||
|   } | ||||
| 
 | ||||
|   i = 0; | ||||
|   n = 300; | ||||
| 
 | ||||
|   i += ksnprintf(buf + i, n - i, "{.f_type=%#lx /* %s */", f->f_type, | ||||
|                  f->f_fstypename); | ||||
|   append("{.f_type=%#lx /* %s */", f->f_type, f->f_fstypename); | ||||
| 
 | ||||
|   sizefmt(ibuf, f->f_bsize, 1024); | ||||
|   i += ksnprintf(buf + i, n - i, ", .f_%s=%sb", "bsize", ibuf); | ||||
|   append(", .f_%s=%sb", "bsize", ibuf); | ||||
| 
 | ||||
|   sizefmt(ibuf, f->f_blocks * f->f_bsize, 1024); | ||||
|   i += ksnprintf(buf + i, n - i, ", .f_%s=%sb", "blocks", ibuf); | ||||
|   append(", .f_%s=%sb", "blocks", ibuf); | ||||
| 
 | ||||
|   sizefmt(ibuf, f->f_bfree * f->f_bsize, 1024); | ||||
|   i += ksnprintf(buf + i, n - i, ", .f_%s=%sb", "bfree", ibuf); | ||||
|   append(", .f_%s=%sb", "bfree", ibuf); | ||||
| 
 | ||||
|   sizefmt(ibuf, f->f_bavail * f->f_bsize, 1024); | ||||
|   i += ksnprintf(buf + i, n - i, ", .f_%s=%sb", "bavail", ibuf); | ||||
|   append(", .f_%s=%sb", "bavail", ibuf); | ||||
| 
 | ||||
|   i += ksnprintf(buf + i, n - i, ", .f_%s=%'zu", "files", f->f_files); | ||||
|   i += ksnprintf(buf + i, n - i, ", .f_%s=%'zu", "ffree", f->f_ffree); | ||||
|   i += ksnprintf(buf + i, n - i, ", .f_fsid=%#lx", f->f_fsid); | ||||
|   i += ksnprintf(buf + i, n - i, ", .f_%s=%'zu", "namelen", f->f_namelen); | ||||
|   i += ksnprintf(buf + i, n - i, ", .f_%s=%d", "owner", f->f_owner); | ||||
|   append(", .f_%s=%'zu", "files", f->f_files); | ||||
|   append(", .f_%s=%'zu", "ffree", f->f_ffree); | ||||
|   append(", .f_fsid=%#lx", f->f_fsid); | ||||
|   append(", .f_%s=%'zu", "namelen", f->f_namelen); | ||||
|   append(", .f_%s=%d", "owner", f->f_owner); | ||||
| 
 | ||||
|   flags = f->f_flags; | ||||
|   i += ksnprintf(buf + i, n - i, ", .f_flags="); | ||||
|   append(", .f_flags="); | ||||
|   if (ST_RDONLY && (flags & ST_RDONLY)) { | ||||
|     i += ksnprintf(buf + i, n - i, "ST_RDONLY|"); | ||||
|     append("ST_RDONLY|"); | ||||
|     flags &= ~ST_RDONLY; | ||||
|   } | ||||
|   if (ST_NOSUID && (flags & ST_NOSUID)) { | ||||
|     i += ksnprintf(buf + i, n - i, "ST_NOSUID|"); | ||||
|     append("ST_NOSUID|"); | ||||
|     flags &= ~ST_NOSUID; | ||||
|   } | ||||
|   if (ST_NODEV && (flags & ST_NODEV)) { | ||||
|     i += ksnprintf(buf + i, n - i, "ST_NODEV|"); | ||||
|     append("ST_NODEV|"); | ||||
|     flags &= ~ST_NODEV; | ||||
|   } | ||||
|   if (ST_NOEXEC && (flags & ST_NOEXEC)) { | ||||
|     i += ksnprintf(buf + i, n - i, "ST_NOEXEC|"); | ||||
|     append("ST_NOEXEC|"); | ||||
|     flags &= ~ST_NOEXEC; | ||||
|   } | ||||
|   if (ST_SYNCHRONOUS && (flags & ST_SYNCHRONOUS)) { | ||||
|     i += ksnprintf(buf + i, n - i, "ST_SYNCHRONOUS|"); | ||||
|     append("ST_SYNCHRONOUS|"); | ||||
|     flags &= ~ST_SYNCHRONOUS; | ||||
|   } | ||||
|   if (ST_MANDLOCK && (flags & ST_MANDLOCK)) { | ||||
|     i += ksnprintf(buf + i, n - i, "ST_MANDLOCK|"); | ||||
|     append("ST_MANDLOCK|"); | ||||
|     flags &= ~ST_MANDLOCK; | ||||
|   } | ||||
|   if (ST_WRITE && (flags & ST_WRITE)) { | ||||
|     i += ksnprintf(buf + i, n - i, "ST_WRITE|"); | ||||
|     append("ST_WRITE|"); | ||||
|     flags &= ~ST_WRITE; | ||||
|   } | ||||
|   if (ST_APPEND && (flags & ST_APPEND)) { | ||||
|     i += ksnprintf(buf + i, n - i, "ST_APPEND|"); | ||||
|     append("ST_APPEND|"); | ||||
|     flags &= ~ST_APPEND; | ||||
|   } | ||||
|   if (ST_IMMUTABLE && (flags & ST_IMMUTABLE)) { | ||||
|     i += ksnprintf(buf + i, n - i, "ST_IMMUTABLE|"); | ||||
|     append("ST_IMMUTABLE|"); | ||||
|     flags &= ~ST_IMMUTABLE; | ||||
|   } | ||||
|   if (ST_NOATIME && (flags & ST_NOATIME)) { | ||||
|     i += ksnprintf(buf + i, n - i, "ST_NOATIME|"); | ||||
|     append("ST_NOATIME|"); | ||||
|     flags &= ~ST_NOATIME; | ||||
|   } | ||||
|   if (ST_NODIRATIME && (flags & ST_NODIRATIME)) { | ||||
|     i += ksnprintf(buf + i, n - i, "ST_NODIRATIME|"); | ||||
|     append("ST_NODIRATIME|"); | ||||
|     flags &= ~ST_NODIRATIME; | ||||
|   } | ||||
|   if (ST_RELATIME && (flags & ST_RELATIME)) { | ||||
|     i += ksnprintf(buf + i, n - i, "ST_RELATIME|"); | ||||
|     append("ST_RELATIME|"); | ||||
|     flags &= ~ST_RELATIME; | ||||
|   } | ||||
|   i += ksnprintf(buf + i, n - i, "%#lx", flags); | ||||
| 
 | ||||
|   if (n - i >= 2) { | ||||
|     buf[i + 0] = '}'; | ||||
|     buf[i + 1] = 0; | ||||
|   } | ||||
|   append("%#lx}", flags); | ||||
| 
 | ||||
|   return buf; | ||||
| } | ||||
|  |  | |||
|  | @ -212,7 +212,7 @@ privileged static size_t kformat(char *b, size_t n, const char *fmt, | |||
|   if (!kistextpointer(fmt)) fmt = "!!WONTFMT"; | ||||
|   p = b; | ||||
|   f = fmt; | ||||
|   e = p + n; | ||||
|   e = p + n;  // assume if n was negative e < p will be the case
 | ||||
|   for (;;) { | ||||
|     for (;;) { | ||||
|       if (!(c = *f++) || c == '%') break; | ||||
|  | @ -502,7 +502,7 @@ privileged static size_t kformat(char *b, size_t n, const char *fmt, | |||
| 
 | ||||
|         case 'G': | ||||
|           x = va_arg(va, int); | ||||
|           if (_weaken(strsignal) && (s = _weaken(strsignal)(x))) { | ||||
|           if (_weaken(strsignal_r) && (s = _weaken(strsignal_r)(x, z))) { | ||||
|             goto FormatString; | ||||
|           } else { | ||||
|             goto FormatDecimal; | ||||
|  |  | |||
|  | @ -23,7 +23,7 @@ | |||
|  * Adds signal to set. | ||||
|  * | ||||
|  * @return 0 on success, or -1 w/ errno | ||||
|  * @raises EINVAL if `1 ≤ sig ≤ NSIG` isn't the case | ||||
|  * @raise EINVAL if `1 ≤ sig ≤ NSIG` isn't the case | ||||
|  * @asyncsignalsafe | ||||
|  */ | ||||
| int sigaddset(sigset_t *set, int sig) { | ||||
|  |  | |||
							
								
								
									
										35
									
								
								libc/intrin/sigcountset.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								libc/intrin/sigcountset.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,35 @@ | |||
| /*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
 | ||||
| │vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│ | ||||
| ╞══════════════════════════════════════════════════════════════════════════════╡ | ||||
| │ Copyright 2020 Justine Alexandra Roberts Tunney                              │ | ||||
| │                                                                              │ | ||||
| │ Permission to use, copy, modify, and/or distribute this software for         │ | ||||
| │ any purpose with or without fee is hereby granted, provided that the         │ | ||||
| │ above copyright notice and this permission notice appear in all copies.      │ | ||||
| │                                                                              │ | ||||
| │ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │ | ||||
| │ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │ | ||||
| │ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │ | ||||
| │ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │ | ||||
| │ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │ | ||||
| │ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │ | ||||
| │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │ | ||||
| │ PERFORMANCE OF THIS SOFTWARE.                                                │ | ||||
| ╚─────────────────────────────────────────────────────────────────────────────*/ | ||||
| #include "libc/calls/struct/sigset.h" | ||||
| #include "libc/intrin/popcnt.h" | ||||
| #include "libc/macros.internal.h" | ||||
| 
 | ||||
| /**
 | ||||
|  * Returns population count of signal set. | ||||
|  * | ||||
|  * @return value greater than or equal to zero | ||||
|  * @asyncsignalsafe | ||||
|  */ | ||||
| int sigcountset(const sigset_t *set) { | ||||
|   int r, i; | ||||
|   for (r = i = 0; i < ARRAYLEN(set->__bits); ++i) { | ||||
|     r += popcnt(set->__bits[i]); | ||||
|   } | ||||
|   return r; | ||||
| } | ||||
|  | @ -16,52 +16,26 @@ | |||
| │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │ | ||||
| │ PERFORMANCE OF THIS SOFTWARE.                                                │ | ||||
| ╚─────────────────────────────────────────────────────────────────────────────*/ | ||||
| #include "libc/fmt/magnumstrs.internal.h" | ||||
| #include "libc/str/str.h" | ||||
| 
 | ||||
| static char g_strsignal[12]; | ||||
| static char g_strsignal[15]; | ||||
| 
 | ||||
| /**
 | ||||
|  * Returns string describing signal code. | ||||
|  * | ||||
|  * This returns SIGZERO for 0 which is the empty value. Textual names | ||||
|  * should be available for signals 1 through 32. Signals in the range 33 | ||||
|  * and 128 are returned as a `SIG%03d` string. Everything else is SIGWUT | ||||
|  * This returns `"0"` for 0 which is the empty value. Symbolic names | ||||
|  * should be available for signals 1 through 32. If the system supports | ||||
|  * real-time signals, they're returned as `SIGRTMIN+%d`. For all other | ||||
|  * 32-bit signed integer, a plain integer representation is returned. | ||||
|  * | ||||
|  * This function is thread safe when `sig` is a known signal magnum. | ||||
|  * Otherwise a pointer to static memory is returned which is unsafe. | ||||
|  * | ||||
|  * @param sig is signal number which should be in range 1 through 128 | ||||
|  * @return pointer to static memory that mutates on subsequent calls | ||||
|  * @return string which is valid code describing signal | ||||
|  * @see strsignal_r() for better thread safety | ||||
|  * @see sigaction() | ||||
|  * @threadsafe | ||||
|  */ | ||||
| char *strsignal(int sig) { | ||||
|   char *p; | ||||
|   const char *s; | ||||
|   if (!sig) return "0"; | ||||
|   if ((s = GetMagnumStr(kSignalNames, sig))) return s; | ||||
|   p = g_strsignal; | ||||
|   p[0] = 'S'; | ||||
|   p[1] = 'I'; | ||||
|   p[2] = 'G'; | ||||
|   p[3] = 0; | ||||
|   if (!sig) { | ||||
|     p[3] = 'Z'; | ||||
|     p[4] = 'E'; | ||||
|     p[5] = 'R'; | ||||
|     p[6] = 'O'; | ||||
|     p[7] = 0; | ||||
|   } else if (1 <= sig && sig <= 128) { | ||||
|     p[3] = '0' + sig / 100; | ||||
|     p[4] = '0' + sig / 10 % 10; | ||||
|     p[5] = '0' + sig % 10; | ||||
|     p[6] = 0; | ||||
|   } else { | ||||
|     p[3] = 'W'; | ||||
|     p[4] = 'U'; | ||||
|     p[5] = 'T'; | ||||
|     p[6] = 0; | ||||
|   } | ||||
|   return g_strsignal; | ||||
|   return strsignal_r(sig, g_strsignal); | ||||
| } | ||||
|  |  | |||
							
								
								
									
										60
									
								
								libc/intrin/strsignal_r.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								libc/intrin/strsignal_r.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,60 @@ | |||
| /*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
 | ||||
| │vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│ | ||||
| ╞══════════════════════════════════════════════════════════════════════════════╡ | ||||
| │ Copyright 2020 Justine Alexandra Roberts Tunney                              │ | ||||
| │                                                                              │ | ||||
| │ Permission to use, copy, modify, and/or distribute this software for         │ | ||||
| │ any purpose with or without fee is hereby granted, provided that the         │ | ||||
| │ above copyright notice and this permission notice appear in all copies.      │ | ||||
| │                                                                              │ | ||||
| │ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │ | ||||
| │ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │ | ||||
| │ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │ | ||||
| │ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │ | ||||
| │ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │ | ||||
| │ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │ | ||||
| │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │ | ||||
| │ PERFORMANCE OF THIS SOFTWARE.                                                │ | ||||
| ╚─────────────────────────────────────────────────────────────────────────────*/ | ||||
| #include "libc/fmt/itoa.h" | ||||
| #include "libc/fmt/magnumstrs.internal.h" | ||||
| #include "libc/str/str.h" | ||||
| #include "libc/sysv/consts/sig.h" | ||||
| 
 | ||||
| /**
 | ||||
|  * Returns string describing signal code. | ||||
|  * | ||||
|  * This returns `"0"` for 0 which is the empty value. Symbolic names | ||||
|  * should be available for signals 1 through 32. If the system supports | ||||
|  * real-time signals, they're returned as `SIGRTMIN+%d`. For all other | ||||
|  * 32-bit signed integer, a plain integer representation is returned. | ||||
|  * | ||||
|  * @param sig is signal number which should be in range 1 through 128 | ||||
|  * @param buf may be used to store output having at least 15 bytes | ||||
|  * @return pointer to .rodata string, or to `buf` after mutating | ||||
|  * @see sigaction() | ||||
|  * @threadsafe | ||||
|  */ | ||||
| char *strsignal_r(int sig, char buf[hasatleast 15]) { | ||||
|   int i; | ||||
|   char *p; | ||||
|   const char *s; | ||||
|   if (!sig) return "0"; | ||||
|   if ((s = GetMagnumStr(kSignalNames, sig))) return s; | ||||
|   if (SIGRTMIN <= sig && sig <= SIGRTMAX) { | ||||
|     sig -= SIGRTMIN; | ||||
|     buf[0] = 'S'; | ||||
|     buf[1] = 'I'; | ||||
|     buf[2] = 'G'; | ||||
|     buf[3] = 'R'; | ||||
|     buf[4] = 'T'; | ||||
|     buf[5] = 'M'; | ||||
|     buf[6] = 'I'; | ||||
|     buf[7] = 'N'; | ||||
|     buf[8] = '+'; | ||||
|     FormatInt32(buf + 9, sig); | ||||
|   } else { | ||||
|     FormatInt32(buf, sig); | ||||
|   } | ||||
|   return buf; | ||||
| } | ||||
|  | @ -1,6 +1,7 @@ | |||
| #ifndef LIBC_ISYSTEM_SIGNAL_H_ | ||||
| #define LIBC_ISYSTEM_SIGNAL_H_ | ||||
| #include "libc/calls/calls.h" | ||||
| #include "libc/calls/sigtimedwait.h" | ||||
| #include "libc/calls/struct/sigaction.h" | ||||
| #include "libc/calls/struct/siginfo.h" | ||||
| #include "libc/sysv/consts/sa.h" | ||||
|  |  | |||
|  | @ -16,154 +16,13 @@ | |||
| │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │ | ||||
| │ PERFORMANCE OF THIS SOFTWARE.                                                │ | ||||
| ╚─────────────────────────────────────────────────────────────────────────────*/ | ||||
| #include "libc/dce.h" | ||||
| #include "libc/fmt/itoa.h" | ||||
| #include "libc/intrin/describeflags.internal.h" | ||||
| #include "libc/log/log.h" | ||||
| #include "libc/str/str.h" | ||||
| #include "libc/sysv/consts/sicode.h" | ||||
| #include "libc/sysv/consts/sig.h" | ||||
| 
 | ||||
| static bool IsSiUser(int si_code) { | ||||
|   if (!IsOpenbsd()) { | ||||
|     return si_code == SI_USER; | ||||
|   } else { | ||||
|     return si_code <= 0; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| static void NameIt(char p[17], const char *s, int si_code) { | ||||
|   p = stpcpy(p, s); | ||||
|   FormatInt32(p, si_code); | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * Returns symbolic name for siginfo::si_code value. | ||||
|  */ | ||||
| const char *GetSiCodeName(int sig, int si_code) { | ||||
|   static char b[17]; | ||||
|   NameIt(b, "SI_", si_code); | ||||
|   if (si_code == SI_QUEUE) { | ||||
|     strcpy(b + 3, "QUEUE"); /* sent by sigqueue(2) */ | ||||
|   } else if (si_code == SI_TIMER) { | ||||
|     strcpy(b + 3, "TIMER"); /* sent by setitimer(2) or clock_settime(2) */ | ||||
|   } else if (si_code == SI_TKILL) { | ||||
|     strcpy(b + 3, "TKILL"); /* sent by tkill(2), etc. */ | ||||
|   } else if (si_code == SI_MESGQ) { | ||||
|     strcpy(b + 3, "MESGQ"); /* sent by mq_notify(2) */ | ||||
|   } else if (si_code == SI_MESGQ) { | ||||
|     strcpy(b + 3, "MESGQ"); /* aio completion */ | ||||
|   } else if (si_code == SI_ASYNCNL) { | ||||
|     strcpy(b + 3, "ASYNCNL"); /* aio completion for dns; the horror */ | ||||
|   } else if (si_code == SI_NOINFO) { | ||||
|     strcpy(b + 3, "NOINFO"); /* no signal specific info available */ | ||||
|   } else if (si_code == SI_KERNEL) { | ||||
|     strcpy(b + 3, "KERNEL"); /* sent by kernel */ | ||||
|   } else if (IsSiUser(si_code)) { | ||||
|     strcpy(b + 3, "USER"); /* sent by kill(2) i.e. from userspace */ | ||||
|   } else if (sig == SIGCHLD) { | ||||
|     NameIt(b, "CLD_", si_code); | ||||
|     if (si_code == CLD_EXITED) { | ||||
|       strcpy(b + 4, "EXITED"); /* child exited */ | ||||
|     } else if (si_code == CLD_KILLED) { | ||||
|       strcpy(b + 4, "KILLED"); /* child terminated w/o core */ | ||||
|     } else if (si_code == CLD_DUMPED) { | ||||
|       strcpy(b + 4, "DUMPED"); /* child terminated w/ core */ | ||||
|     } else if (si_code == CLD_TRAPPED) { | ||||
|       strcpy(b + 4, "TRAPPED"); /* traced child trapped */ | ||||
|     } else if (si_code == CLD_STOPPED) { | ||||
|       strcpy(b + 4, "STOPPED"); /* child stopped */ | ||||
|     } else if (si_code == CLD_CONTINUED) { | ||||
|       strcpy(b + 4, "CONTINUED"); /* stopped child continued */ | ||||
|     } | ||||
|   } else if (sig == SIGTRAP) { | ||||
|     NameIt(b, "TRAP_", si_code); | ||||
|     if (si_code == TRAP_BRKPT) { | ||||
|       strcpy(b + 5, "BRKPT"); /* process breakpoint */ | ||||
|     } else if (si_code == TRAP_TRACE) { | ||||
|       strcpy(b + 5, "TRACE"); /* process trace trap */ | ||||
|     } | ||||
|   } else if (sig == SIGSEGV) { | ||||
|     NameIt(b, "SEGV_", si_code); | ||||
|     if (si_code == SEGV_MAPERR) { | ||||
|       strcpy(b + 5, "MAPERR"); /* address not mapped to object */ | ||||
|     } else if (si_code == SEGV_ACCERR) { | ||||
|       strcpy(b + 5, "ACCERR"); /* invalid permissions for mapped object */ | ||||
|     } else if (si_code == SEGV_PKUERR) { | ||||
|       strcpy(b + 5, "PKUERR"); /* FreeBSD: x86: PKU violation */ | ||||
|     } | ||||
|   } else if (sig == SIGFPE) { | ||||
|     NameIt(b, "FPE_???", si_code); | ||||
|     if (si_code == FPE_INTDIV) { | ||||
|       strcpy(b + 4, "INTDIV"); /* integer divide by zero */ | ||||
|     } else if (si_code == FPE_INTOVF) { | ||||
|       strcpy(b + 4, "INTOVF"); /* integer overflow */ | ||||
|     } else if (si_code == FPE_FLTDIV) { | ||||
|       strcpy(b + 4, "FLTDIV"); /* floating point divide by zero */ | ||||
|     } else if (si_code == FPE_FLTOVF) { | ||||
|       strcpy(b + 4, "FLTOVF"); /* floating point overflow */ | ||||
|     } else if (si_code == FPE_FLTUND) { | ||||
|       strcpy(b + 4, "FLTUND"); /* floating point underflow */ | ||||
|     } else if (si_code == FPE_FLTRES) { | ||||
|       strcpy(b + 4, "FLTRES"); /* floating point inexact */ | ||||
|     } else if (si_code == FPE_FLTINV) { | ||||
|       strcpy(b + 4, "FLTINV"); /* invalid floating point operation */ | ||||
|     } else if (si_code == FPE_FLTSUB) { | ||||
|       strcpy(b + 4, "FLTSUB"); /* subscript out of range */ | ||||
|     } | ||||
|   } else if (sig == SIGILL) { | ||||
|     NameIt(b, "ILL_", si_code); | ||||
|     if (si_code == ILL_ILLOPC) { | ||||
|       strcpy(b + 4, "ILLOPC"); /* illegal opcode */ | ||||
|     } else if (si_code == ILL_ILLOPN) { | ||||
|       strcpy(b + 4, "ILLOPN"); /* illegal operand */ | ||||
|     } else if (si_code == ILL_ILLADR) { | ||||
|       strcpy(b + 4, "ILLADR"); /* illegal addressing mode */ | ||||
|     } else if (si_code == ILL_ILLTRP) { | ||||
|       strcpy(b + 4, "ILLTRP"); /* illegal trap */ | ||||
|     } else if (si_code == ILL_PRVOPC) { | ||||
|       strcpy(b + 4, "PRVOPC"); /* privileged opcode */ | ||||
|     } else if (si_code == ILL_PRVREG) { | ||||
|       strcpy(b + 4, "PRVREG"); /* privileged register */ | ||||
|     } else if (si_code == ILL_COPROC) { | ||||
|       strcpy(b + 4, "COPROC"); /* coprocessor error */ | ||||
|     } else if (si_code == ILL_BADSTK) { | ||||
|       strcpy(b + 4, "BADSTK"); /* internal stack error */ | ||||
|     } | ||||
|   } else if (sig == SIGBUS) { | ||||
|     NameIt(b, "BUS_", si_code); | ||||
|     if (si_code == BUS_ADRALN) { | ||||
|       strcpy(b + 4, "ADRALN"); /* invalid address alignment */ | ||||
|     } else if (si_code == BUS_ADRERR) { | ||||
|       strcpy(b + 4, "ADRERR"); /* non-existent physical address */ | ||||
|     } else if (si_code == BUS_OBJERR) { | ||||
|       strcpy(b + 4, "OBJERR"); /* object specific hardware error */ | ||||
|     } else if (si_code == BUS_OOMERR) { | ||||
|       strcpy(b + 4, "OOMERR"); /* FreeBSD */ | ||||
|     } else if (si_code == BUS_MCEERR_AR) { | ||||
|       strcpy(b + 4, "MCEERR_AR"); /* Linux 2.6.32+ */ | ||||
|     } else if (si_code == BUS_MCEERR_AO) { | ||||
|       strcpy(b + 4, "MCEERR_AO"); /* Linux 2.6.32+ */ | ||||
|     } | ||||
|   } else if (sig == SIGIO) { | ||||
|     NameIt(b, "POLL_", si_code); | ||||
|     if (si_code == POLL_IN) { | ||||
|       strcpy(b + 5, "IN"); /* data input available */ | ||||
|     } else if (si_code == POLL_OUT) { | ||||
|       strcpy(b + 5, "OUT"); /* output buffer available */ | ||||
|     } else if (si_code == POLL_MSG) { | ||||
|       strcpy(b + 5, "MSG"); /* input message available */ | ||||
|     } else if (si_code == POLL_ERR) { | ||||
|       strcpy(b + 5, "ERR"); /* i/o error */ | ||||
|     } else if (si_code == POLL_PRI) { | ||||
|       strcpy(b + 5, "PRI"); /* high priority input available */ | ||||
|     } else if (si_code == POLL_HUP) { | ||||
|       strcpy(b + 5, "HUP"); /* device disconnected */ | ||||
|     } | ||||
|   } else if (sig == SIGSYS) { | ||||
|     NameIt(b, "SYS_", si_code); | ||||
|     if (si_code == SYS_SECCOMP) { | ||||
|       strcpy(b + 4, "SECCOMP"); | ||||
|     } | ||||
|   } | ||||
|   return b; | ||||
|   return (DescribeSiCode)(b, sig, si_code); | ||||
| } | ||||
|  |  | |||
|  | @ -203,6 +203,7 @@ wctrans_t wctrans(const char *); | |||
| wint_t towctrans(wint_t, wctrans_t); | ||||
| 
 | ||||
| char *strsignal(int) returnsnonnull libcesque; | ||||
| char *strsignal_r(int, char[hasatleast 15]) returnsnonnull libcesque; | ||||
| char *strerror(int) returnsnonnull dontthrow nocallback; | ||||
| int strerror_r(int, char *, size_t) dontthrow nocallback; | ||||
| int strerror_wr(int, uint32_t, char *, size_t) dontthrow nocallback; | ||||
|  |  | |||
|  | @ -1,2 +1,2 @@ | |||
| .include "o/libc/sysv/macros.internal.inc" | ||||
| .scall sys_sigtimedwait,0xffffff159ffff080,globl | ||||
| .scall sys_sigtimedwait,0x1affff159ffff080,globl,hidden | ||||
|  |  | |||
|  | @ -168,11 +168,11 @@ syscon	sig	SIGPROF					27			27			27			27			27			27			# profiling timer expired; | |||
| syscon	sig	SIGWINCH				28			28			28			28			28			28			# terminal resized; unix consensus & faked on nt | ||||
| syscon	sig	SIGIO					29			23			23			23			23			29			# bsd consensus | ||||
| syscon	sig	SIGSYS					31			12			12			12			12			31			# wut; bsd consensus | ||||
| syscon	sig	SIGINFO					0			29			29			29			29			0			# bsd consensus | ||||
| syscon	sig	SIGRTMAX				64			0			126			0			63			0 | ||||
| syscon	sig	SIGRTMIN				32			0			65			0			33			0 | ||||
| syscon	sig	SIGEMT					0			7			7			7			7			0			# not implemented in most community editions of system five; consider doing this using SIGUSR1 or SIGUSR2 instead | ||||
| syscon	sig	SIGPWR					30			30			30			30			32			30			# not implemented in most community editions of system five; consider doing this using SIGUSR1 or SIGUSR2 instead | ||||
| syscon	sig	SIGINFO					0			29			29			29			29			0			# bsd consensus | ||||
| syscon	sig	SIGRTMIN				32			0			65			0			33			32 | ||||
| syscon	sig	SIGRTMAX				64			0			126			0			63			64 | ||||
| syscon	compat	SIGPOLL					29			23			23			23			23			29			# same as SIGIO | ||||
| syscon	compat	SIGIOT					6			6			6			6			6			6			# PDP-11 feature; same as SIGABRT | ||||
| 
 | ||||
|  | @ -1232,7 +1232,7 @@ syscon	limits	SOMAXCONN				4096			128			128			128			128			2147483647		# maximum | |||
| syscon	limits	_ARG_MAX				128*1024		1024*1024		512*1024		512*1024		256*1024		32767*2			# bsd consensus | ||||
| syscon	limits	_NAME_MAX				255			255			255			255			511			255			# probably higher on windows? | ||||
| syscon	limits	_PATH_MAX				4096			1024			1024			1024			1024			512			# cosmopolitan libc imposes a lower 512 limit; nt theoretically goes up to 32767 | ||||
| syscon	limits	_NSIG					64			32			128			32			64			32			# _SIG_MAXSIG on FreeBSD | ||||
| syscon	limits	_NSIG					64			32			128			32			64			64			# _SIG_MAXSIG on FreeBSD | ||||
| 
 | ||||
| #	unmount() flags | ||||
| #	a.k.a. umount2() on linux | ||||
|  |  | |||
|  | @ -1,2 +1,2 @@ | |||
| .include "o/libc/sysv/consts/syscon.internal.inc" | ||||
| .syscon sig,SIGRTMAX,64,0,126,0,63,0 | ||||
| .syscon sig,SIGRTMAX,64,0,126,0,63,64 | ||||
|  |  | |||
|  | @ -1,2 +1,2 @@ | |||
| .include "o/libc/sysv/consts/syscon.internal.inc" | ||||
| .syscon sig,SIGRTMIN,32,0,65,0,33,0 | ||||
| .syscon sig,SIGRTMIN,32,0,65,0,33,32 | ||||
|  |  | |||
|  | @ -1,2 +1,2 @@ | |||
| .include "o/libc/sysv/consts/syscon.internal.inc" | ||||
| .syscon limits,_NSIG,64,32,128,32,64,32 | ||||
| .syscon limits,_NSIG,64,32,128,32,64,64 | ||||
|  |  | |||
|  | @ -192,7 +192,7 @@ scall	sys_setfsuid		0xfffffffffffff07a	globl hidden | |||
| scall	sys_setfsgid		0xfffffffffffff07b	globl hidden | ||||
| scall	sys_capget		0xfffffffffffff07d	globl # no wrapper | ||||
| scall	sys_capset		0xfffffffffffff07e	globl # no wrapper | ||||
| scall	sys_sigtimedwait	0xffffff159ffff080	globl # no wrapper | ||||
| scall	sys_sigtimedwait	0x1affff159ffff080	globl hidden | ||||
| scall	sys_sigqueue		0xffffff1c8fffffff	globl hidden | ||||
| scall	sys_sigqueueinfo	0x0f5ffffffffff081	globl hidden # a.k.a. rt_sigqueueinfo on linux | ||||
| scall	sys_personality		0xfffffffffffff087	globl # no wrapper | ||||
|  |  | |||
|  | @ -20,27 +20,27 @@ | |||
| #include "libc/calls/struct/sigaction.h" | ||||
| #include "libc/calls/struct/siginfo.h" | ||||
| #include "libc/calls/struct/sigset.h" | ||||
| #include "libc/errno.h" | ||||
| #include "libc/sysv/consts/sa.h" | ||||
| #include "libc/sysv/consts/sig.h" | ||||
| #include "libc/testlib/testlib.h" | ||||
| 
 | ||||
| static unsigned OnSignalCnt = 0; | ||||
| 
 | ||||
| void OnSignal(int sig, siginfo_t *si, void *ctx) { | ||||
|   OnSignalCnt++; | ||||
|   EXPECT_EQ(SIGUSR1, sig); | ||||
| } | ||||
| 
 | ||||
| TEST(sigpending, efault) { | ||||
|   ASSERT_SYS(EFAULT, -1, sigpending(0)); | ||||
| } | ||||
| 
 | ||||
| TEST(sigpending, test) { | ||||
|   sigset_t pending; | ||||
|   sigfillset(&pending); | ||||
|   EXPECT_EQ(0, sigpending(&pending)); | ||||
|   unsigned cnt = 0; | ||||
|   for (unsigned sig = 1; sig < NSIG; sig++) { | ||||
|     if (sigismember(&pending, sig)) { | ||||
|       cnt++; | ||||
|     } | ||||
|   } | ||||
|   EXPECT_EQ(0, cnt); | ||||
|   EXPECT_EQ(0, sigcountset(&pending)); | ||||
| 
 | ||||
|   struct sigaction sa = {.sa_sigaction = OnSignal, .sa_flags = SA_SIGINFO}; | ||||
|   ASSERT_EQ(0, sigaction(SIGUSR1, &sa, NULL)); | ||||
|  | @ -51,47 +51,23 @@ TEST(sigpending, test) { | |||
|   ASSERT_EQ(0, raise(SIGUSR1)); | ||||
|   sigfillset(&pending); | ||||
|   EXPECT_EQ(0, sigpending(&pending)); | ||||
|   cnt = 0; | ||||
|   for (unsigned sig = 1; sig < NSIG; sig++) { | ||||
|     if (sigismember(&pending, sig)) { | ||||
|       cnt++; | ||||
|     } | ||||
|   } | ||||
|   EXPECT_EQ(1, cnt); | ||||
|   EXPECT_EQ(1, sigcountset(&pending)); | ||||
|   EXPECT_EQ(1, sigismember(&pending, SIGUSR1)); | ||||
| 
 | ||||
|   ASSERT_NE(SIG_ERR, signal(SIGUSR1, SIG_IGN)); | ||||
|   sigemptyset(&pending); | ||||
|   EXPECT_EQ(0, sigpending(&pending)); | ||||
|   cnt = 0; | ||||
|   for (unsigned sig = 1; sig < NSIG; sig++) { | ||||
|     if (sigismember(&pending, sig)) { | ||||
|       cnt++; | ||||
|     } | ||||
|   } | ||||
|   EXPECT_EQ(0, cnt); | ||||
|   EXPECT_EQ(0, sigcountset(&pending)); | ||||
| 
 | ||||
|   ASSERT_EQ(0, sigaction(SIGUSR1, &sa, NULL)); | ||||
|   ASSERT_EQ(0, raise(SIGUSR1)); | ||||
|   EXPECT_EQ(0, sigpending(&pending)); | ||||
|   cnt = 0; | ||||
|   for (unsigned sig = 1; sig < NSIG; sig++) { | ||||
|     if (sigismember(&pending, sig)) { | ||||
|       cnt++; | ||||
|     } | ||||
|   } | ||||
|   EXPECT_EQ(1, cnt); | ||||
|   EXPECT_EQ(1, sigcountset(&pending)); | ||||
|   EXPECT_EQ(1, sigismember(&pending, SIGUSR1)); | ||||
| 
 | ||||
|   sigemptyset(&blocked); | ||||
|   ASSERT_EQ(0, sigprocmask(SIG_SETMASK, &blocked, NULL)); | ||||
|   EXPECT_EQ(0, sigpending(&pending)); | ||||
|   cnt = 0; | ||||
|   for (unsigned sig = 1; sig < NSIG; sig++) { | ||||
|     if (sigismember(&pending, sig)) { | ||||
|       cnt++; | ||||
|     } | ||||
|   } | ||||
|   EXPECT_EQ(0, cnt); | ||||
|   EXPECT_EQ(0, sigcountset(&pending)); | ||||
|   EXPECT_EQ(1, OnSignalCnt); | ||||
| } | ||||
|  |  | |||
							
								
								
									
										75
									
								
								test/libc/calls/sigtimedwait_test.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								test/libc/calls/sigtimedwait_test.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,75 @@ | |||
| /*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
 | ||||
| │vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│ | ||||
| ╞══════════════════════════════════════════════════════════════════════════════╡ | ||||
| │ Copyright 2022 Justine Alexandra Roberts Tunney                              │ | ||||
| │                                                                              │ | ||||
| │ Permission to use, copy, modify, and/or distribute this software for         │ | ||||
| │ any purpose with or without fee is hereby granted, provided that the         │ | ||||
| │ above copyright notice and this permission notice appear in all copies.      │ | ||||
| │                                                                              │ | ||||
| │ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │ | ||||
| │ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │ | ||||
| │ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │ | ||||
| │ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │ | ||||
| │ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │ | ||||
| │ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │ | ||||
| │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │ | ||||
| │ PERFORMANCE OF THIS SOFTWARE.                                                │ | ||||
| ╚─────────────────────────────────────────────────────────────────────────────*/ | ||||
| #include "libc/calls/calls.h" | ||||
| #include "libc/calls/sigtimedwait.h" | ||||
| #include "libc/calls/struct/siginfo.h" | ||||
| #include "libc/calls/struct/siginfo.internal.h" | ||||
| #include "libc/calls/struct/sigset.h" | ||||
| #include "libc/calls/struct/timespec.h" | ||||
| #include "libc/dce.h" | ||||
| #include "libc/errno.h" | ||||
| #include "libc/runtime/runtime.h" | ||||
| #include "libc/sysv/consts/sicode.h" | ||||
| #include "libc/sysv/consts/sig.h" | ||||
| #include "libc/testlib/testlib.h" | ||||
| 
 | ||||
| void SetUp(void) { | ||||
|   if (IsXnu()) exit(0); | ||||
|   if (IsMetal()) exit(0); | ||||
|   if (IsWindows()) exit(0); | ||||
|   if (IsOpenbsd()) exit(0); | ||||
| } | ||||
| 
 | ||||
| TEST(sigtimedwait, nullSet_efault) { | ||||
|   ASSERT_SYS(EFAULT, -1, sigtimedwait(0, 0, 0)); | ||||
| } | ||||
| 
 | ||||
| TEST(sigtimedwait, emptySet_timesOut) { | ||||
|   sigset_t ss = {0}; | ||||
|   struct timespec ts = {0, 0}; | ||||
|   ASSERT_SYS(EAGAIN, -1, sigtimedwait(&ss, 0, &ts)); | ||||
| } | ||||
| 
 | ||||
| TEST(sigtimedwait, badTimestamp_einval) { | ||||
|   sigset_t ss = {0}; | ||||
|   struct timespec ts = {0, -1}; | ||||
|   ASSERT_SYS(EINVAL, -1, sigtimedwait(&ss, 0, &ts)); | ||||
| } | ||||
| 
 | ||||
| TEST(sigtimedwait, test) { | ||||
|   int pid, ws; | ||||
|   siginfo_t info; | ||||
|   sigset_t ss, oldss; | ||||
|   struct timespec ts = {1, 0}; | ||||
|   sigemptyset(&ss); | ||||
|   sigaddset(&ss, SIGUSR1); | ||||
|   ASSERT_SYS(0, 0, sigprocmask(SIG_BLOCK, &ss, &oldss)); | ||||
|   ASSERT_NE(-1, (pid = fork())); | ||||
|   if (!pid) { | ||||
|     ASSERT_SYS(0, SIGUSR1, sigtimedwait(&ss, &info, &ts)); | ||||
|     ASSERT_EQ(SIGUSR1, info.si_signo); | ||||
|     ASSERT_EQ(SI_USER, info.si_code); | ||||
|     ASSERT_EQ(getuid(), info.si_uid); | ||||
|     _Exit(0); | ||||
|   } | ||||
|   ASSERT_SYS(0, 0, kill(pid, SIGUSR1)); | ||||
|   ASSERT_SYS(0, pid, wait(&ws)); | ||||
|   ASSERT_EQ(0, ws); | ||||
|   ASSERT_SYS(0, 0, sigprocmask(SIG_SETMASK, &oldss, 0)); | ||||
| } | ||||
|  | @ -49,10 +49,6 @@ static uint64_t Rando(void) { | |||
|   return x; | ||||
| } | ||||
| 
 | ||||
| void SetUp(void) { | ||||
|   __print_maps(); | ||||
| } | ||||
| 
 | ||||
| static const struct { | ||||
|   const char *want; | ||||
|   const char *fmt; | ||||
|  | @ -356,6 +352,30 @@ TEST(ksnprintf, badUtf16) { | |||
|   } | ||||
| } | ||||
| 
 | ||||
| TEST(ksnprintf, negativeOverflowIdiom_isSafe) { | ||||
|   int i, n; | ||||
|   char golden[11]; | ||||
|   struct { | ||||
|     char underflow[11]; | ||||
|     char buf[11]; | ||||
|     char overflow[11]; | ||||
|   } u; | ||||
|   memset(golden, -1, 11); | ||||
|   memset(u.underflow, -1, 11); | ||||
|   memset(u.overflow, -1, 11); | ||||
|   i = 0; | ||||
|   n = 11; | ||||
|   i += ksnprintf(u.buf + i, n - i, "hello"); | ||||
|   ASSERT_STREQ("hello", u.buf); | ||||
|   i += ksnprintf(u.buf + i, n - i, " world"); | ||||
|   ASSERT_STREQ("hello w...", u.buf); | ||||
|   i += ksnprintf(u.buf + i, n - i, " i love you"); | ||||
|   ASSERT_STREQ("hello w...", u.buf); | ||||
|   ASSERT_EQ(i, 5 + 6 + 11); | ||||
|   ASSERT_EQ(0, memcmp(golden, u.underflow, 11)); | ||||
|   ASSERT_EQ(0, memcmp(golden, u.overflow, 11)); | ||||
| } | ||||
| 
 | ||||
| TEST(ksnprintf, truncation) { | ||||
|   char buf[16] = {0}; | ||||
|   rngset(buf, sizeof(buf) - 1, lemur64, -1); | ||||
|  |  | |||
|  | @ -27,8 +27,13 @@ TEST(strsignal, test) { | |||
|   EXPECT_STREQ("SIGALRM", strsignal(SIGALRM)); | ||||
|   EXPECT_STREQ("SIGUSR1", strsignal(SIGUSR1)); | ||||
|   EXPECT_STREQ("SIGSTOP", strsignal(SIGSTOP)); | ||||
|   EXPECT_STREQ("SIG099", strsignal(99)); | ||||
|   EXPECT_STREQ("SIG100", strsignal(100)); | ||||
|   EXPECT_STREQ("SIGWUT", strsignal(-1)); | ||||
|   EXPECT_STREQ("SIGWUT", strsignal(9001)); | ||||
|   EXPECT_STREQ("666", strsignal(666)); | ||||
|   EXPECT_STREQ("-1", strsignal(-1)); | ||||
|   EXPECT_STREQ("9001", strsignal(9001)); | ||||
| } | ||||
| 
 | ||||
| TEST(strsignal, realtime) { | ||||
|   if (!SIGRTMIN) return; | ||||
|   ASSERT_STREQ("SIGRTMIN", strsignal(SIGRTMIN)); | ||||
|   ASSERT_STREQ("SIGRTMIN+1", strsignal(SIGRTMIN + 1)); | ||||
| } | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue