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