1 /* $MirOS: src/lib/libc/string/strerror_r.c,v 1.4 2014/02/19 23:01:20 tg Exp $ */
2 /* $OpenBSD: strerror_r.c,v 1.6 2005/08/08 08:05:37 espie Exp $ */
3 /* Public Domain <marc@snafu.org> */
4
5 #define sys_errlist _sys_errlist
6 #define sys_nerr _sys_nerr
7 #define sys_siglist _sys_siglist
8
9 #include <errno.h>
10 #include <limits.h>
11 #include <signal.h>
12 #include <string.h>
13
14 __RCSID("$MirOS: src/lib/libc/string/strerror_r.c,v 1.4 2014/02/19 23:01:20 tg Exp $");
15
16 static size_t
__digits10(unsigned int num)17 __digits10(unsigned int num)
18 {
19 size_t i = 0;
20
21 do {
22 num /= 10;
23 i++;
24 } while (num != 0);
25
26 return i;
27 }
28
29 static int
__itoa(int num,int sign,char * buffer,size_t start,size_t end)30 __itoa(int num, int sign, char *buffer, size_t start, size_t end)
31 {
32 size_t pos;
33 unsigned int a;
34 int neg;
35
36 if (sign && num < 0) {
37 a = -num;
38 neg = 1;
39 }
40 else {
41 a = num;
42 neg = 0;
43 }
44
45 pos = start + __digits10(a);
46 if (neg)
47 pos++;
48
49 if (pos < end)
50 buffer[pos] = '\0';
51 else
52 return ERANGE;
53 pos--;
54 do {
55 buffer[pos] = (a % 10) + '0';
56 pos--;
57 a /= 10;
58 } while (a != 0);
59 if (neg)
60 buffer[pos] = '-';
61 return 0;
62 }
63
64
65 static int
__num2string(int num,int sign,char * buf,size_t buflen,const char * const list[],size_t max,const char * def)66 __num2string(int num, int sign, char *buf, size_t buflen,
67 const char * const list[], size_t max, const char *def)
68 {
69 int ret = 0;
70 size_t len;
71
72 if (0 <= num && (size_t)num < max) {
73 len = strlcpy(buf, list[num], buflen);
74 if (len >= buflen)
75 ret = ERANGE;
76 } else {
77 len = strlcpy(buf, def, buflen);
78 if (len >= buflen)
79 ret = ERANGE;
80 else {
81 ret = __itoa(num, sign, buf, len, buflen);
82 if (ret == 0)
83 ret = EINVAL;
84 }
85 }
86
87 return ret;
88 }
89
90 #define UPREFIX "Unknown error: "
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 ret_errno;
97
98 save_errno = errno;
99
100 ret_errno = __num2string(errnum, 1, strerrbuf, buflen,
101 (const char * const *)sys_errlist, sys_nerr, UPREFIX);
102
103 errno = ret_errno ? ret_errno : save_errno;
104 return (ret_errno);
105 }
106
107 #define USIGPREFIX "Unknown signal: "
108
109 /* from gen/psignal.c, string/strsignal.c */
110 char *__strsignal(int, char *);
111
112 char *
__strsignal(int num,char * buf)113 __strsignal(int num, char *buf)
114 {
115 __num2string(num, 0, buf, NL_TEXTMAX, sys_siglist, NSIG,
116 USIGPREFIX);
117 return buf;
118 }
119