xref: /openbsd-src/lib/libc/string/strerror_r.c (revision b725ae7711052a2233e31a66fefb8a752c388d7a)
1 /* $OpenBSD: strerror_r.c,v 1.2 2004/05/03 05:07:34 espie Exp $ */
2 /* Public Domain <marc@snafu.org> */
3 
4 #if defined(LIBC_SCCS) && !defined(lint)
5 static char *rcsid = "$OpenBSD: strerror_r.c,v 1.2 2004/05/03 05:07:34 espie Exp $";
6 #endif /* LIBC_SCCS and not lint */
7 
8 #ifdef NLS
9 #define catclose	_catclose
10 #define catgets		_catgets
11 #define catopen		_catopen
12 #include <nl_types.h>
13 #endif
14 
15 #define sys_errlist	_sys_errlist
16 #define sys_nerr	_sys_nerr
17 
18 #include <errno.h>
19 #include <limits.h>
20 #include <string.h>
21 
22 static size_t
23 __digits10(unsigned int num)
24 {
25 	size_t i = 0;
26 
27 	do {
28 		num /= 10;
29 		i++;
30 	} while (num != 0);
31 
32 	return i;
33 }
34 
35 static void
36 __itoa(int num, char *buffer, size_t start, size_t end)
37 {
38 	size_t pos;
39 	unsigned int a;
40 	int neg;
41 
42 	if (num < 0) {
43 		a = -num;
44 		neg = 1;
45 	}
46 	else {
47 		a = num;
48 		neg = 0;
49 	}
50 
51 	pos = start + __digits10(a);
52 	if (neg)
53 	    pos++;
54 
55 	if (pos < end)
56 		buffer[pos] = '\0';
57 	else {
58 		if (end)
59 			buffer[--end] = '\0'; /* XXX */
60 	}
61 	pos--;
62 	do {
63 
64 		if (pos < end)
65 			buffer[pos] = (a % 10) + '0';
66 		pos--;
67 		a /= 10;
68 	} while (a != 0);
69 	if (neg)
70 		if (pos < end)
71 			buffer[pos] = '-';
72 }
73 
74 
75 #define	UPREFIX	"Unknown error: "
76 
77 int
78 strerror_r(int errnum, char *strerrbuf, size_t buflen)
79 {
80 	int save_errno;
81 	int ret_errno;
82 	size_t len;
83 #ifdef NLS
84 	nl_catd catd;
85 #endif
86 
87 	save_errno = errno;
88 	ret_errno = 0;
89 
90 #ifdef NLS
91 	catd = catopen("libc", 0);
92 #endif
93 
94 	if (errnum >= 0 && errnum < sys_nerr) {
95 #ifdef NLS
96 		len = strlcpy(strerrbuf, catgets(catd, 1, errnum,
97 		    (char *)sys_errlist[errnum]), buflen);
98 #else
99 		len = strlcpy(strerrbuf, sys_errlist[errnum], buflen);
100 #endif
101 		if (len >= buflen)
102 			ret_errno = ERANGE;
103 	} else {
104 #ifdef NLS
105 		len = strlcpy(strerrbuf, catgets(catd, 1, 0xffff, UPREFIX),
106 		    buflen);
107 #else
108 		len = strlcpy(strerrbuf, UPREFIX, buflen);
109 #endif
110 		__itoa(errnum, strerrbuf, len, buflen);
111 		ret_errno = EINVAL;
112 	}
113 
114 #ifdef NLS
115 	catclose(catd);
116 #endif
117 
118 	errno = ret_errno ? ret_errno : save_errno;
119 	return (ret_errno);
120 }
121