1*3a9dd5c3Sbluhm /* $OpenBSD: strerror_r.c,v 1.13 2016/10/19 16:26:16 bluhm Exp $ */
2b418cc48Smarc /* Public Domain <marc@snafu.org> */
3b418cc48Smarc
4b418cc48Smarc #include <errno.h>
5b418cc48Smarc #include <limits.h>
653d7e922Sotto #include <signal.h>
7b418cc48Smarc #include <string.h>
8b418cc48Smarc
9232b982aSespie static size_t
__digits10(unsigned int num)10232b982aSespie __digits10(unsigned int num)
11232b982aSespie {
12232b982aSespie size_t i = 0;
13232b982aSespie
14232b982aSespie do {
15232b982aSespie num /= 10;
16232b982aSespie i++;
17232b982aSespie } while (num != 0);
18232b982aSespie
19232b982aSespie return i;
20232b982aSespie }
21232b982aSespie
22d4786f81Sotto static int
__itoa(int num,int sign,char * buffer,size_t start,size_t end)2353d7e922Sotto __itoa(int num, int sign, char *buffer, size_t start, size_t end)
24232b982aSespie {
25232b982aSespie size_t pos;
26232b982aSespie unsigned int a;
27232b982aSespie int neg;
28232b982aSespie
2953d7e922Sotto if (sign && num < 0) {
30232b982aSespie a = -num;
31232b982aSespie neg = 1;
32232b982aSespie }
33232b982aSespie else {
34232b982aSespie a = num;
35232b982aSespie neg = 0;
36232b982aSespie }
37232b982aSespie
38232b982aSespie pos = start + __digits10(a);
39232b982aSespie if (neg)
40232b982aSespie pos++;
41232b982aSespie
42232b982aSespie if (pos < end)
43232b982aSespie buffer[pos] = '\0';
44d4786f81Sotto else
45d4786f81Sotto return ERANGE;
46232b982aSespie pos--;
47232b982aSespie do {
48232b982aSespie buffer[pos] = (a % 10) + '0';
49232b982aSespie pos--;
50232b982aSespie a /= 10;
51232b982aSespie } while (a != 0);
52232b982aSespie if (neg)
53232b982aSespie buffer[pos] = '-';
54d4786f81Sotto return 0;
55232b982aSespie }
56232b982aSespie
57232b982aSespie
5853d7e922Sotto static int
__num2string(int num,int sign,int setid,char * buf,size_t buflen,const char * const list[],size_t max,const char * def)5953d7e922Sotto __num2string(int num, int sign, int setid, char *buf, size_t buflen,
603f5ad7fcSguenther const char * const list[], size_t max, const char *def)
61b418cc48Smarc {
6253d7e922Sotto int ret = 0;
63232b982aSespie size_t len;
6453d7e922Sotto
6553d7e922Sotto if (0 <= num && num < max) {
66c6ac99c8Sbluhm len = strlcpy(buf, list[num], buflen);
675233054aSbeck if (len >= buflen)
6853d7e922Sotto ret = ERANGE;
6953d7e922Sotto } else {
7053d7e922Sotto len = strlcpy(buf, def, buflen);
7153d7e922Sotto if (len >= buflen)
7253d7e922Sotto ret = ERANGE;
735233054aSbeck else {
7453d7e922Sotto ret = __itoa(num, sign, buf, len, buflen);
7553d7e922Sotto if (ret == 0)
7653d7e922Sotto ret = EINVAL;
77232b982aSespie }
785233054aSbeck }
79232b982aSespie
8053d7e922Sotto return ret;
8153d7e922Sotto }
8253d7e922Sotto
8353d7e922Sotto #define UPREFIX "Unknown error: "
8453d7e922Sotto
8553d7e922Sotto int
strerror_r(int errnum,char * strerrbuf,size_t buflen)8653d7e922Sotto strerror_r(int errnum, char *strerrbuf, size_t buflen)
8753d7e922Sotto {
8853d7e922Sotto int ret_errno;
8953d7e922Sotto
9053d7e922Sotto ret_errno = __num2string(errnum, 1, 1, strerrbuf, buflen,
9153d7e922Sotto sys_errlist, sys_nerr, UPREFIX);
9253d7e922Sotto
93*3a9dd5c3Sbluhm if (ret_errno)
94*3a9dd5c3Sbluhm errno = ret_errno;
95b418cc48Smarc return (ret_errno);
96b418cc48Smarc }
979b9d2a55Sguenther DEF_WEAK(strerror_r);
9853d7e922Sotto
9953d7e922Sotto #define USIGPREFIX "Unknown signal: "
10053d7e922Sotto
10153d7e922Sotto char *
__strsignal(int num,char * buf)10253d7e922Sotto __strsignal(int num, char *buf)
10353d7e922Sotto {
1043f5ad7fcSguenther __num2string(num, 0, 2, buf, NL_TEXTMAX, sys_siglist, NSIG,
10553d7e922Sotto USIGPREFIX);
10653d7e922Sotto return buf;
10753d7e922Sotto }
108