1 /* $OpenBSD: strerror_r.c,v 1.11 2015/09/06 20:26:20 guenther Exp $ */ 2 /* Public Domain <marc@snafu.org> */ 3 4 #ifdef NLS 5 #include <nl_types.h> 6 #endif 7 8 #include <errno.h> 9 #include <limits.h> 10 #include <signal.h> 11 #include <string.h> 12 13 static size_t 14 __digits10(unsigned int num) 15 { 16 size_t i = 0; 17 18 do { 19 num /= 10; 20 i++; 21 } while (num != 0); 22 23 return i; 24 } 25 26 static int 27 __itoa(int num, int sign, char *buffer, size_t start, size_t end) 28 { 29 size_t pos; 30 unsigned int a; 31 int neg; 32 33 if (sign && num < 0) { 34 a = -num; 35 neg = 1; 36 } 37 else { 38 a = num; 39 neg = 0; 40 } 41 42 pos = start + __digits10(a); 43 if (neg) 44 pos++; 45 46 if (pos < end) 47 buffer[pos] = '\0'; 48 else 49 return ERANGE; 50 pos--; 51 do { 52 buffer[pos] = (a % 10) + '0'; 53 pos--; 54 a /= 10; 55 } while (a != 0); 56 if (neg) 57 buffer[pos] = '-'; 58 return 0; 59 } 60 61 62 static int 63 __num2string(int num, int sign, int setid, char *buf, size_t buflen, 64 const char * const list[], size_t max, const char *def) 65 { 66 int ret = 0; 67 size_t len; 68 69 #ifdef NLS 70 nl_catd catd; 71 catd = catopen("libc", NL_CAT_LOCALE); 72 #endif 73 74 if (0 <= num && num < max) { 75 #ifdef NLS 76 len = strlcpy(buf, catgets(catd, setid, num, list[num]), 77 buflen); 78 #else 79 len = strlcpy(buf, list[num], buflen); 80 #endif 81 if (len >= buflen) 82 ret = ERANGE; 83 } else { 84 #ifdef NLS 85 len = strlcpy(buf, catgets(catd, setid, 0xffff, def), buflen); 86 #else 87 len = strlcpy(buf, def, buflen); 88 #endif 89 if (len >= buflen) 90 ret = ERANGE; 91 else { 92 ret = __itoa(num, sign, buf, len, buflen); 93 if (ret == 0) 94 ret = EINVAL; 95 } 96 } 97 98 #ifdef NLS 99 catclose(catd); 100 #endif 101 102 return ret; 103 } 104 105 #define UPREFIX "Unknown error: " 106 107 int 108 strerror_r(int errnum, char *strerrbuf, size_t buflen) 109 { 110 int save_errno; 111 int ret_errno; 112 113 save_errno = errno; 114 115 ret_errno = __num2string(errnum, 1, 1, strerrbuf, buflen, 116 sys_errlist, sys_nerr, UPREFIX); 117 118 errno = ret_errno ? ret_errno : save_errno; 119 return (ret_errno); 120 } 121 DEF_WEAK(strerror_r); 122 123 #define USIGPREFIX "Unknown signal: " 124 125 char * 126 __strsignal(int num, char *buf) 127 { 128 __num2string(num, 0, 2, buf, NL_TEXTMAX, sys_siglist, NSIG, 129 USIGPREFIX); 130 return buf; 131 } 132