summaryrefslogtreecommitdiff
path: root/libc/string/strsignal.c
diff options
context:
space:
mode:
Diffstat (limited to 'libc/string/strsignal.c')
-rw-r--r--libc/string/strsignal.c144
1 files changed, 144 insertions, 0 deletions
diff --git a/libc/string/strsignal.c b/libc/string/strsignal.c
new file mode 100644
index 000000000..21b987926
--- /dev/null
+++ b/libc/string/strsignal.c
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2002 Manuel Novoa III
+ * Copyright (C) 2000-2005 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+/*
+ * Sep 11, 2003
+ * Patch by Atsushi Nemoto <anemo@mba.ocn.ne.jp> to do arch-required
+ * mapping of signal strings (alpha, mips, hppa, sparc).
+ */
+
+/* TODO: make a threadsafe version? */
+
+#define _GNU_SOURCE
+#include <features.h>
+#include <string.h>
+#include <bits/uClibc_uintmaxtostr.h>
+
+#define _SYS_NSIG 32
+
+#ifdef __UCLIBC_HAS_SIGNUM_MESSAGES__
+# define _SYS_SIGMSG_MAXLEN 25
+#else /* __UCLIBC_HAS_SIGNUM_MESSAGES__ */
+# define _SYS_SIGMSG_MAXLEN 0
+#endif /* __UCLIBC_HAS_SIGNUM_MESSAGES__ */
+
+#if _SYS_SIGMSG_MAXLEN < __UIM_BUFLEN_INT + 15
+# define _STRSIGNAL_BUFSIZE (__UIM_BUFLEN_INT + 15)
+#else
+# define _STRSIGNAL_BUFSIZE _SYS_SIGMSG_MAXLEN
+#endif
+
+#ifdef __UCLIBC_HAS_SIGNUM_MESSAGES__
+
+extern const char _string_syssigmsgs[];
+
+#if defined(__alpha__) || defined(__mips__) || defined(__hppa__) || defined(__sparc__)
+static const unsigned char sstridx[] = {
+ 0,
+ SIGHUP,
+ SIGINT,
+ SIGQUIT,
+ SIGILL,
+ SIGTRAP,
+ SIGIOT,
+ SIGBUS,
+ SIGFPE,
+ SIGKILL,
+ SIGUSR1,
+ SIGSEGV,
+ SIGUSR2,
+ SIGPIPE,
+ SIGALRM,
+ SIGTERM,
+#if defined(__alpha__) || defined(__mips__) || defined(__sparc__)
+ 0,
+#else
+ SIGSTKFLT,
+#endif
+ SIGCHLD,
+ SIGCONT,
+ SIGSTOP,
+ SIGTSTP,
+ SIGTTIN,
+ SIGTTOU,
+ SIGURG,
+ SIGXCPU,
+ SIGXFSZ,
+ SIGVTALRM,
+ SIGPROF,
+ SIGWINCH,
+ SIGIO,
+ SIGPWR,
+ SIGSYS,
+#if defined(__alpha__) || defined(__mips__) || defined(__hppa__) || defined(__sparc__)
+ SIGEMT,
+#endif
+};
+#endif
+
+char attribute_hidden *__strsignal(int signum)
+{
+ register char *s;
+ int i;
+ static char buf[_STRSIGNAL_BUFSIZE];
+ static const char unknown[] = {
+ 'U', 'n', 'k', 'n', 'o', 'w', 'n', ' ', 's', 'i', 'g', 'n', 'a', 'l', ' '
+ };
+
+#if defined(__alpha__) || defined(__mips__) || defined(__hppa__) || defined(__sparc__)
+ /* Need to translate signum to string index. */
+ for (i = 0 ; i < sizeof(sstridx)/sizeof(sstridx[0]) ; i++) {
+ if (sstridx[i] == signum) {
+ goto GOT_SSTRIDX;
+ }
+ }
+ i = INT_MAX; /* Failed. */
+ GOT_SSTRIDX:
+#else
+ /* No signum to string index translation needed. */
+ i = signum;
+#endif
+
+ if (((unsigned int) signum) < _SYS_NSIG) {
+ /* Trade time for space. This function should rarely be called
+ * so rather than keeping an array of pointers for the different
+ * messages, just run through the buffer until we find the
+ * correct string. */
+ for (s = (char *) _string_syssigmsgs ; i ; ++s) {
+ if (!*s) {
+ --i;
+ }
+ }
+ if (*s) { /* Make sure we have an actual message. */
+ goto DONE;
+ }
+ }
+
+ s = _int10tostr(buf+sizeof(buf)-1, signum) - sizeof(unknown);
+ __memcpy(s, unknown, sizeof(unknown));
+
+ DONE:
+ return s;
+}
+
+#else /* __UCLIBC_HAS_SIGNUM_MESSAGES__ */
+
+char attribute_hidden *__strsignal(int signum)
+{
+ static char buf[_STRSIGNAL_BUFSIZE];
+ static const char unknown[] = {
+ 'U', 'n', 'k', 'n', 'o', 'w', 'n', ' ', 's', 'i', 'g', 'n', 'a', 'l', ' '
+ };
+
+ return (char *) __memcpy(_int10tostr(buf+sizeof(buf)-1, signum)
+ - sizeof(unknown),
+ unknown, sizeof(unknown));
+}
+
+#endif /* __UCLIBC_HAS_SIGNUM_MESSAGES__ */
+
+strong_alias(__strsignal,strsignal)