• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* $OpenBSD: strerror_r.c,v 1.6 2005/08/08 08:05:37 espie Exp $ */
2 /* Public Domain <marc@snafu.org> */
3 
4 #define sys_siglist	_sys_siglist
5 
6 #include <errno.h>
7 #include <limits.h>
8 #include <signal.h>
9 #include <string.h>
10 
11 typedef struct {
12   int           code;
13   const char*   msg;
14 } CodeString;
15 
16 static const char*
__code_string_lookup(const CodeString * strings,int code)17 __code_string_lookup( const CodeString*  strings,
18                       int                code )
19 {
20     int  nn = 0;
21 
22     for (;;)
23     {
24         if (strings[nn].code == 0)
25             break;
26 
27         if (strings[nn].code == code)
28             return strings[nn].msg;
29 
30         nn++;
31     }
32     return NULL;
33 }
34 
35 
36 static const CodeString  _sys_error_strings[] =
37 {
38 #define  __BIONIC_ERRDEF(x,y,z)  { y, z },
39 #include <sys/_errdefs.h>
40     { 0, NULL }
41 };
42 
43 static size_t
__digits10(unsigned int num)44 __digits10(unsigned int num)
45 {
46 	size_t i = 0;
47 
48 	do {
49 		num /= 10;
50 		i++;
51 	} while (num != 0);
52 
53 	return i;
54 }
55 
56 static int
__itoa(int num,int sign,char * buffer,size_t start,size_t end)57 __itoa(int num, int sign, char *buffer, size_t start, size_t end)
58 {
59 	size_t pos;
60 	unsigned int a;
61 	int neg;
62 
63 	if (sign && num < 0) {
64 		a = -num;
65 		neg = 1;
66 	}
67 	else {
68 		a = num;
69 		neg = 0;
70 	}
71 
72 	pos = start + __digits10(a);
73 	if (neg)
74 	    pos++;
75 
76 	if (pos < end)
77 		buffer[pos] = '\0';
78 	else
79 		return ERANGE;
80 	pos--;
81 	do {
82 		buffer[pos] = (a % 10) + '0';
83 		pos--;
84 		a /= 10;
85 	} while (a != 0);
86 	if (neg)
87 		buffer[pos] = '-';
88 	return 0;
89 }
90 
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          len, ret = 0;
97     const char*  msg;
98 
99     save_errno = errno;
100     msg        = __code_string_lookup( _sys_error_strings, errnum );
101     if (msg != NULL) {
102         len = strlcpy(strerrbuf, msg, buflen);
103         if ((size_t)len >= buflen)
104             ret = ERANGE;
105     } else {
106         len = strlcpy(strerrbuf, "Unknown error: ", buflen);
107         if ((size_t)len >= buflen)
108             ret = ERANGE;
109         else {
110             int  ret = __itoa(errnum, 1, strerrbuf, len, buflen);
111 
112             if (ret == 0)
113                 ret = EINVAL;
114         }
115     }
116     return ret;
117 }
118 
119 #if 0
120 static const CodeString  _sys_signal_strings[] =
121 {
122 #define  SIGDEF(x,y,z)  { y, z },
123 #include <sys/_sigdefs.h>
124 };
125 
126 
127 static int
128 __num2string(int num, int sign, int setid, char *buf, size_t buflen,
129     char * list[], size_t max, const char *def)
130 {
131 	int ret = 0;
132 	size_t len;
133 
134 	if (0 <= num && num < max) {
135 		len = strlcpy(buf, def, buflen);
136 		if (len >= buflen)
137 			ret = ERANGE;
138 	} else {
139 		len = strlcpy(buf, def, buflen);
140 		if (len >= buflen)
141 			ret = ERANGE;
142 		else {
143 			ret = __itoa(num, sign, buf, len, buflen);
144 			if (ret == 0)
145 				ret = EINVAL;
146 		}
147 	}
148 
149 	return ret;
150 }
151 
152 
153 
154 #define USIGPREFIX "Unknown signal: "
155 
156 char *
157 __strsignal(int num, char *buf)
158 {
159 	__num2string(num, 0, 2, buf, NL_TEXTMAX, (char **)sys_siglist, NSIG,
160 	    USIGPREFIX);
161 	return buf;
162 }
163 #endif
164