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