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