1 /* $OpenBSD: strerror_r.c,v 1.4 2005/05/08 06:25:44 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.4 2005/05/08 06:25:44 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 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 int 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 return ERANGE; 59 pos--; 60 do { 61 buffer[pos] = (a % 10) + '0'; 62 pos--; 63 a /= 10; 64 } while (a != 0); 65 if (neg) 66 buffer[pos] = '-'; 67 return 0; 68 } 69 70 71 #define UPREFIX "Unknown error: " 72 73 int 74 strerror_r(int errnum, char *strerrbuf, size_t buflen) 75 { 76 int save_errno; 77 int ret_errno; 78 size_t len; 79 #ifdef NLS 80 nl_catd catd; 81 #endif 82 83 save_errno = errno; 84 ret_errno = 0; 85 86 #ifdef NLS 87 catd = catopen("libc", 0); 88 #endif 89 90 if (errnum >= 0 && errnum < sys_nerr) { 91 #ifdef NLS 92 len = strlcpy(strerrbuf, catgets(catd, 1, errnum, 93 (char *)sys_errlist[errnum]), buflen); 94 #else 95 len = strlcpy(strerrbuf, sys_errlist[errnum], buflen); 96 #endif 97 if (len >= buflen) 98 ret_errno = ERANGE; 99 } else { 100 #ifdef NLS 101 len = strlcpy(strerrbuf, catgets(catd, 1, 0xffff, UPREFIX), 102 buflen); 103 #else 104 len = strlcpy(strerrbuf, UPREFIX, buflen); 105 #endif 106 if (len >= buflen) 107 ret_errno = ERANGE; 108 else { 109 ret_errno = __itoa(errnum, strerrbuf, len, buflen); 110 if (ret_errno == 0) 111 ret_errno = EINVAL; 112 } 113 } 114 115 #ifdef NLS 116 catclose(catd); 117 #endif 118 119 errno = ret_errno ? ret_errno : save_errno; 120 return (ret_errno); 121 } 122