1 /* $OpenBSD: strerror_r.c,v 1.6 2005/08/08 08:05:37 espie Exp $ */
2 /* Public Domain <marc@snafu.org> */
3
4 #define sys_siglist _sys_siglist
5
6 #include <errno.h>
7 #include <limits.h>
8 #include <signal.h>
9 #include <string.h>
10
11 typedef struct {
12 int code;
13 const char* msg;
14 } CodeString;
15
16 static const char*
__code_string_lookup(const CodeString * strings,int code)17 __code_string_lookup( const CodeString* strings,
18 int code )
19 {
20 int nn = 0;
21
22 for (;;)
23 {
24 if (strings[nn].code == 0)
25 break;
26
27 if (strings[nn].code == code)
28 return strings[nn].msg;
29
30 nn++;
31 }
32 return NULL;
33 }
34
35
36 static const CodeString _sys_error_strings[] =
37 {
38 #define __BIONIC_ERRDEF(x,y,z) { y, z },
39 #include <sys/_errdefs.h>
40 { 0, NULL }
41 };
42
43 static size_t
__digits10(unsigned int num)44 __digits10(unsigned int num)
45 {
46 size_t i = 0;
47
48 do {
49 num /= 10;
50 i++;
51 } while (num != 0);
52
53 return i;
54 }
55
56 static int
__itoa(int num,int sign,char * buffer,size_t start,size_t end)57 __itoa(int num, int sign, char *buffer, size_t start, size_t end)
58 {
59 size_t pos;
60 unsigned int a;
61 int neg;
62
63 if (sign && num < 0) {
64 a = -num;
65 neg = 1;
66 }
67 else {
68 a = num;
69 neg = 0;
70 }
71
72 pos = start + __digits10(a);
73 if (neg)
74 pos++;
75
76 if (pos < end)
77 buffer[pos] = '\0';
78 else
79 return ERANGE;
80 pos--;
81 do {
82 buffer[pos] = (a % 10) + '0';
83 pos--;
84 a /= 10;
85 } while (a != 0);
86 if (neg)
87 buffer[pos] = '-';
88 return 0;
89 }
90
91
92 int
strerror_r(int errnum,char * strerrbuf,size_t buflen)93 strerror_r(int errnum, char *strerrbuf, size_t buflen)
94 {
95 int save_errno;
96 int len, ret = 0;
97 const char* msg;
98
99 save_errno = errno;
100 msg = __code_string_lookup( _sys_error_strings, errnum );
101 if (msg != NULL) {
102 len = strlcpy(strerrbuf, msg, buflen);
103 if ((size_t)len >= buflen)
104 ret = ERANGE;
105 } else {
106 len = strlcpy(strerrbuf, "Unknown error: ", buflen);
107 if ((size_t)len >= buflen)
108 ret = ERANGE;
109 else {
110 int ret = __itoa(errnum, 1, strerrbuf, len, buflen);
111
112 if (ret == 0)
113 ret = EINVAL;
114 }
115 }
116 return ret;
117 }
118
119 #if 0
120 static const CodeString _sys_signal_strings[] =
121 {
122 #define SIGDEF(x,y,z) { y, z },
123 #include <sys/_sigdefs.h>
124 };
125
126
127 static int
128 __num2string(int num, int sign, int setid, char *buf, size_t buflen,
129 char * list[], size_t max, const char *def)
130 {
131 int ret = 0;
132 size_t len;
133
134 if (0 <= num && num < max) {
135 len = strlcpy(buf, def, buflen);
136 if (len >= buflen)
137 ret = ERANGE;
138 } else {
139 len = strlcpy(buf, def, buflen);
140 if (len >= buflen)
141 ret = ERANGE;
142 else {
143 ret = __itoa(num, sign, buf, len, buflen);
144 if (ret == 0)
145 ret = EINVAL;
146 }
147 }
148
149 return ret;
150 }
151
152
153
154 #define USIGPREFIX "Unknown signal: "
155
156 char *
157 __strsignal(int num, char *buf)
158 {
159 __num2string(num, 0, 2, buf, NL_TEXTMAX, (char **)sys_siglist, NSIG,
160 USIGPREFIX);
161 return buf;
162 }
163 #endif
164