xref: /openbsd-src/lib/libc/string/strerror_r.c (revision 3a9dd5c3476b66d67674a94ff403050abfa7df18)
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