diff options
| author | Wes Peters <wes@FreeBSD.org> | 2001-12-06 04:53:31 +0000 | 
|---|---|---|
| committer | Wes Peters <wes@FreeBSD.org> | 2001-12-06 04:53:31 +0000 | 
| commit | f61a2ede84c391c2bc6212d37885d68cf07d4fe6 (patch) | |
| tree | 5e497a3ec40cddc305b92cc007654a2bd8169cbb | |
| parent | 5a31fd21e9b3cce9c3106437fe15a417e0161ba5 (diff) | |
Notes
| -rw-r--r-- | lib/libc/string/strerror.3 | 31 | ||||
| -rw-r--r-- | lib/libc/string/strerror.c | 119 | 
2 files changed, 78 insertions, 72 deletions
diff --git a/lib/libc/string/strerror.3 b/lib/libc/string/strerror.3 index ed63b25f5be7..037b138cad9e 100644 --- a/lib/libc/string/strerror.3 +++ b/lib/libc/string/strerror.3 @@ -81,16 +81,7 @@ function renders the same result into  .Fa strerrbuf  for a maximum of   .Fa buflen -characters and returns 0 upon success.  If insufficient -storage is provided in -.Fa strerrbuf  -(as specified in  -.Fa buflen ) -to contain the error string,  -.Er ERANGE  -is returned and the string in  -.Fa strerrbuf -may not be null-terminated. +characters and returns 0 upon success.  .Pp  The  .Fn perror @@ -114,9 +105,25 @@ otherwise, only the error message string is printed.  If  .Fa errnum  is not a recognized error number, -the error message string will contain +.Fn strerror +returns an error message string containing  .Dq Li "Unknown error:\ " -followed by the error number in decimal. +followed by the error number in decimal, while  +.Fn strerror_r +returns  +.Er EINVAL . +.Pp +If insufficient storage is provided in +.Fa strerrbuf  +(as specified in  +.Fa buflen ) +to contain the error string,  +.Fn strerror_r +returns +.Er ERANGE  +and the contents of +.Fa strerrbuf +are indeterminate.  .Pp  The message strings can be accessed directly using the external  array diff --git a/lib/libc/string/strerror.c b/lib/libc/string/strerror.c index 8628d8d9c436..e0f4cd3f778c 100644 --- a/lib/libc/string/strerror.c +++ b/lib/libc/string/strerror.c @@ -41,88 +41,87 @@ __FBSDID("$FreeBSD$");  #include <string.h>  #include <errno.h> -  int  strerror_r(int errnum, char *strerrbuf, size_t buflen)  { -#define	UPREFIX	"Unknown error: " -	unsigned int uerr; -	char *p, *t; -	char tmp[40];				/* 64-bit number + slop */ -	int len; - -	uerr = errnum;				/* convert to unsigned */ -	if (uerr < sys_nerr) { -		len = strlcpy(strerrbuf, (char *)sys_errlist[uerr], buflen); -		return (len <= buflen) ? 0 : ERANGE; +	int             len; + +	if ((errnum > 0) && (errnum < sys_nerr)) { +		len = strlcpy(strerrbuf, (char *)sys_errlist[errnum], buflen); +		return ((len <= buflen) ? 0 : ERANGE);  	} +	return (EINVAL); +} -	/* Print unknown errno by hand so we don't link to stdio(3). */ +char * +strerror(num) +	int             num; +{ +	char           *p, *t; +	unsigned int	uerr; +	static char const unknown_prefix[] = "Unknown error: "; + +	/* +	 * Define a buffer size big enough to describe a 64-bit +	 * number in ASCII decimal (19), with optional leading sign +	 * (+1) and trailing NUL (+1). +	 */ +#       define		NUMLEN 21 +#	define		EBUFLEN (sizeof unknown_prefix + NUMLEN) +	char            tmp[NUMLEN];	/* temporary number */ +	static char     ebuf[EBUFLEN];	/* error message */ + +	if ((num > 0) && (num < sys_nerr)) +		return ((char *)sys_errlist[num]); + +	/* +	 * Print unknown errno by hand so we don't link to stdio(3). +	 * This collects the ASCII digits in reverse order. +	 */ +	uerr = (num > 0) ? num : -num;  	t = tmp; -	if (errnum < 0) -		uerr = -uerr;  	do {  		*t++ = "0123456789"[uerr % 10];  	} while (uerr /= 10); - -	if (errnum < 0) +	if (num < 0)  		*t++ = '-'; -	strlcpy(strerrbuf, UPREFIX, buflen); -	for (p = strerrbuf + sizeof(UPREFIX) - 1; p < strerrbuf + buflen; ) { +	/* +	 * Copy the "unknown" message and the number into the caller +	 * supplied buffer, inverting the number string. +	 */ +	strcpy(ebuf, unknown_prefix); +	for (p = ebuf + sizeof unknown_prefix - 1; t >= tmp; )  		*p++ = *--t; -		if (t <= tmp) -			break; -	} - -	if (p < strerrbuf + buflen) { -		*p = '\0'; -		return 0; -	} - -	return ERANGE; +	*p = '\0'; +	return (ebuf);  } +#ifdef STANDALONE_TEST -/* - * NOTE: the following length should be enough to hold the longest defined - * error message in sys_errlist, defined in ../gen/errlst.c.  This is a WAG - * that is better than the previous value. - */ -#define ERR_LEN 64 - -char * -strerror(num) -	int num; -{ -	unsigned int uerr; -	static char ebuf[ERR_LEN]; - -	uerr = num;				/* convert to unsigned */ -	if (uerr < sys_nerr) -		return (char *)sys_errlist[uerr]; - -	/* strerror can't fail so handle truncation semi-elegantly */ -	if (strerror_r(num, ebuf, (size_t) ERR_LEN) != 0) -	    ebuf[ERR_LEN - 1] = '\0'; - -	return ebuf; -} - +#include <limits.h> -#ifdef STANDALONE_TEST  main()  { -	char mybuf[64]; -	int ret; +	char            mybuf[64]; +	int             ret;  	printf("strerror(47) yeilds: %s\n", strerror(47)); +	printf("strerror(437) yeilds: %s\n", strerror(437)); +	printf("strerror(LONG_MAX) yeilds: %s\n", strerror(LONG_MAX)); +	printf("strerror(LONG_MIN) yeilds: %s\n", strerror(LONG_MIN)); +	printf("strerror(ULONG_MAX) yeilds: %s\n", strerror(ULONG_MAX)); + +	memset(mybuf, '*', 63); mybuf[63] = '\0';  	strerror_r(11, mybuf, 64);  	printf("strerror_r(11) yeilds: %s\n", mybuf); -	strerror_r(1234, mybuf, 64); -	printf("strerror_r(1234) yeilds: %s\n", mybuf); -	memset(mybuf, '*', 63); -	ret = strerror_r(4321, mybuf, 16); + +	memset(mybuf, '*', 63); mybuf[63] = '\0'; +	ret = strerror_r(1234, mybuf, 64); +	printf("strerror_r(1234) returns %d (%s)\n", ret, mybuf); + +	memset(mybuf, '*', 63); mybuf[63] = '\0'; +	ret = strerror_r(1, mybuf, 10);  	printf("strerror_r on short buffer returns %d (%s)\n", ret, mybuf);  }  #endif  | 
