summaryrefslogtreecommitdiff
path: root/src/lib/libc/string/strerror_r.c
diff options
context:
space:
mode:
authorespie <>2004-05-03 05:07:34 +0000
committerespie <>2004-05-03 05:07:34 +0000
commit76aa3dd62e5e4b02cca65819f1c8d9938aec06fd (patch)
treecc1b644adae829dec9c5b074cb0a9ba027eb4839 /src/lib/libc/string/strerror_r.c
parent3b9905250348125fe22a21c5b8f4eb7ae5fbcded (diff)
downloadopenbsd-76aa3dd62e5e4b02cca65819f1c8d9938aec06fd.tar.gz
openbsd-76aa3dd62e5e4b02cca65819f1c8d9938aec06fd.tar.bz2
openbsd-76aa3dd62e5e4b02cca65819f1c8d9938aec06fd.zip
build the error message in strerror_r.c directly, avoiding one copy there.
handle a few subtle details caught by the regression tests: correct termination, non copying if buffer length == 0, errno setting. let all former users of __strerror go through strerror_r. Work by Todd Miller and I. Okay millert@.
Diffstat (limited to 'src/lib/libc/string/strerror_r.c')
-rw-r--r--src/lib/libc/string/strerror_r.c110
1 files changed, 100 insertions, 10 deletions
diff --git a/src/lib/libc/string/strerror_r.c b/src/lib/libc/string/strerror_r.c
index aab6db5303..db264bcf50 100644
--- a/src/lib/libc/string/strerror_r.c
+++ b/src/lib/libc/string/strerror_r.c
@@ -1,30 +1,120 @@
1/* $OpenBSD: strerror_r.c,v 1.1 2002/11/21 20:45:05 marc Exp $ */ 1/* $OpenBSD: strerror_r.c,v 1.2 2004/05/03 05:07:34 espie Exp $ */
2/* Public Domain <marc@snafu.org> */ 2/* Public Domain <marc@snafu.org> */
3 3
4#if defined(LIBC_SCCS) && !defined(lint) 4#if defined(LIBC_SCCS) && !defined(lint)
5static char *rcsid = "$OpenBSD: strerror_r.c,v 1.1 2002/11/21 20:45:05 marc Exp $"; 5static char *rcsid = "$OpenBSD: strerror_r.c,v 1.2 2004/05/03 05:07:34 espie Exp $";
6#endif /* LIBC_SCCS and not lint */ 6#endif /* LIBC_SCCS and not lint */
7 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
8#include <errno.h> 18#include <errno.h>
9#include <limits.h> 19#include <limits.h>
10#include <string.h> 20#include <string.h>
11 21
12extern char *__strerror(int, char *); 22static 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
35static 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: "
13 76
14int 77int
15strerror_r(int errnum, char *strerrbuf, size_t buflen) 78strerror_r(int errnum, char *strerrbuf, size_t buflen)
16{ 79{
17 int save_errno; 80 int save_errno;
18 int ret_errno; 81 int ret_errno;
19 char buf[NL_TEXTMAX]; 82 size_t len;
83#ifdef NLS
84 nl_catd catd;
85#endif
20 86
21 save_errno = errno; 87 save_errno = errno;
22 errno = 0; 88 ret_errno = 0;
23 __strerror(errnum, buf); 89
24 if (strlcpy(strerrbuf, buf, buflen) >= buflen) 90#ifdef NLS
25 errno = ERANGE; 91 catd = catopen("libc", 0);
26 ret_errno = errno; 92#endif
27 errno = save_errno; 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
28 117
118 errno = ret_errno ? ret_errno : save_errno;
29 return (ret_errno); 119 return (ret_errno);
30} 120}