1 /* $OpenBSD: strerror_r.c,v 1.2 2004/05/03 05:07:34 espie 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.2 2004/05/03 05:07:34 espie 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 18 #include <errno.h> 19 #include <limits.h> 20 #include <string.h> 21 22 static size_t 23 __digits10(unsigned int num) 24 { 25 size_t i = 0; 26 27 do { 28 num /= 10; 29 i++; 30 } while (num != 0); 31 32 return i; 33 } 34 35 static void 36 __itoa(int num, char *buffer, size_t start, size_t end) 37 { 38 size_t pos; 39 unsigned int a; 40 int neg; 41 42 if (num < 0) { 43 a = -num; 44 neg = 1; 45 } 46 else { 47 a = num; 48 neg = 0; 49 } 50 51 pos = start + __digits10(a); 52 if (neg) 53 pos++; 54 55 if (pos < end) 56 buffer[pos] = '\0'; 57 else { 58 if (end) 59 buffer[--end] = '\0'; /* XXX */ 60 } 61 pos--; 62 do { 63 64 if (pos < end) 65 buffer[pos] = (a % 10) + '0'; 66 pos--; 67 a /= 10; 68 } while (a != 0); 69 if (neg) 70 if (pos < end) 71 buffer[pos] = '-'; 72 } 73 74 75 #define UPREFIX "Unknown error: " 76 77 int 78 strerror_r(int errnum, char *strerrbuf, size_t buflen) 79 { 80 int save_errno; 81 int ret_errno; 82 size_t len; 83 #ifdef NLS 84 nl_catd catd; 85 #endif 86 87 save_errno = errno; 88 ret_errno = 0; 89 90 #ifdef NLS 91 catd = catopen("libc", 0); 92 #endif 93 94 if (errnum >= 0 && errnum < sys_nerr) { 95 #ifdef NLS 96 len = strlcpy(strerrbuf, catgets(catd, 1, errnum, 97 (char *)sys_errlist[errnum]), buflen); 98 #else 99 len = strlcpy(strerrbuf, sys_errlist[errnum], buflen); 100 #endif 101 if (len >= buflen) 102 ret_errno = ERANGE; 103 } else { 104 #ifdef NLS 105 len = strlcpy(strerrbuf, catgets(catd, 1, 0xffff, UPREFIX), 106 buflen); 107 #else 108 len = strlcpy(strerrbuf, UPREFIX, buflen); 109 #endif 110 __itoa(errnum, strerrbuf, len, buflen); 111 ret_errno = EINVAL; 112 } 113 114 #ifdef NLS 115 catclose(catd); 116 #endif 117 118 errno = ret_errno ? ret_errno : save_errno; 119 return (ret_errno); 120 } 121