summaryrefslogtreecommitdiffstats
path: root/libc/string/strsignal.c
blob: 7d7f613feb1233597cdba65027d9cf4c2a4d699e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
/*
 * 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>
#include <signal.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)