1 /* $OpenBSD: strerror_r.c,v 1.6 2005/08/08 08:05:37 espie Exp $ */ 2 /* Public Domain <marc (at) 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* 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 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 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 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