Home | History | Annotate | Download | only in string
      1 /* $OpenBSD: strerror_r.c,v 1.6 2005/08/08 08:05:37 espie Exp $ */
      2 /* Public Domain <marc (at) snafu.org> */
      3 
      4 #define sys_siglist	_sys_siglist
      5 
      6 #include <errno.h>
      7 #include <limits.h>
      8 #include <signal.h>
      9 #include <string.h>
     10 
     11 typedef struct {
     12   int           code;
     13   const char*   msg;
     14 } CodeString;
     15 
     16 static const char*
     17 __code_string_lookup( const CodeString*  strings,
     18                       int                code )
     19 {
     20     int  nn = 0;
     21 
     22     for (;;)
     23     {
     24         if (strings[nn].msg == NULL)
     25             break;
     26 
     27         if (strings[nn].code == code)
     28             return strings[nn].msg;
     29 
     30         nn++;
     31     }
     32     return NULL;
     33 }
     34 
     35 
     36 static const CodeString  _sys_error_strings[] =
     37 {
     38 #define  __BIONIC_ERRDEF(x,y,z)  { y, z },
     39 #include <sys/_errdefs.h>
     40     { 0, NULL }
     41 };
     42 
     43 static size_t
     44 __digits10(unsigned int num)
     45 {
     46 	size_t i = 0;
     47 
     48 	do {
     49 		num /= 10;
     50 		i++;
     51 	} while (num != 0);
     52 
     53 	return i;
     54 }
     55 
     56 static int
     57 __itoa(int num, int sign, char *buffer, size_t start, size_t end)
     58 {
     59 	size_t pos;
     60 	unsigned int a;
     61 	int neg;
     62 
     63 	if (sign && num < 0) {
     64 		a = -num;
     65 		neg = 1;
     66 	}
     67 	else {
     68 		a = num;
     69 		neg = 0;
     70 	}
     71 
     72 	pos = start + __digits10(a);
     73 	if (neg)
     74 	    pos++;
     75 
     76 	if (pos < end)
     77 		buffer[pos] = '\0';
     78 	else
     79 		return ERANGE;
     80 	pos--;
     81 	do {
     82 		buffer[pos] = (a % 10) + '0';
     83 		pos--;
     84 		a /= 10;
     85 	} while (a != 0);
     86 	if (neg)
     87 		buffer[pos] = '-';
     88 	return 0;
     89 }
     90 
     91 
     92 int
     93 strerror_r(int errnum, char *strerrbuf, size_t buflen)
     94 {
     95     int          save_errno;
     96     int          len, ret = 0;
     97     const char*  msg;
     98 
     99     save_errno = errno;
    100     msg        = __code_string_lookup( _sys_error_strings, errnum );
    101     if (msg != NULL) {
    102         len = strlcpy(strerrbuf, msg, buflen);
    103         if ((size_t)len >= buflen)
    104             ret = ERANGE;
    105     } else {
    106         len = strlcpy(strerrbuf, "Unknown error: ", buflen);
    107         if ((size_t)len >= buflen)
    108             ret = ERANGE;
    109         else {
    110             int  ret = __itoa(errnum, 1, strerrbuf, len, buflen);
    111 
    112             if (ret == 0)
    113                 ret = EINVAL;
    114         }
    115     }
    116     return ret;
    117 }
    118 
    119 #if 0
    120 static const CodeString  _sys_signal_strings[] =
    121 {
    122 #define  SIGDEF(x,y,z)  { y, z },
    123 #include <sys/_sigdefs.h>
    124 };
    125 
    126 
    127 static int
    128 __num2string(int num, int sign, int setid, char *buf, size_t buflen,
    129     char * list[], size_t max, const char *def)
    130 {
    131 	int ret = 0;
    132 	size_t len;
    133 
    134 	if (0 <= num && num < max) {
    135 		len = strlcpy(buf, def, buflen);
    136 		if (len >= buflen)
    137 			ret = ERANGE;
    138 	} else {
    139 		len = strlcpy(buf, def, buflen);
    140 		if (len >= buflen)
    141 			ret = ERANGE;
    142 		else {
    143 			ret = __itoa(num, sign, buf, len, buflen);
    144 			if (ret == 0)
    145 				ret = EINVAL;
    146 		}
    147 	}
    148 
    149 	return ret;
    150 }
    151 
    152 
    153 
    154 #define USIGPREFIX "Unknown signal: "
    155 
    156 char *
    157 __strsignal(int num, char *buf)
    158 {
    159 	__num2string(num, 0, 2, buf, NL_TEXTMAX, (char **)sys_siglist, NSIG,
    160 	    USIGPREFIX);
    161 	return buf;
    162 }
    163 #endif
    164