diff options
| author | Wes Peters <wes@FreeBSD.org> | 2001-12-20 06:31:26 +0000 | 
|---|---|---|
| committer | Wes Peters <wes@FreeBSD.org> | 2001-12-20 06:31:26 +0000 | 
| commit | 0b6d38c427a9bc4123401e283c9255a12701d46a (patch) | |
| tree | b71b6e099a52f19081a81da58f0a9829681760c5 /lib | |
| parent | 933ff66cf7afdccd2d734e467ec887e947fbbe9e (diff) | |
Notes
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/libc/string/strerror.3 | 60 | ||||
| -rw-r--r-- | lib/libc/string/strerror.c | 107 | 
2 files changed, 143 insertions, 24 deletions
diff --git a/lib/libc/string/strerror.3 b/lib/libc/string/strerror.3 index 447e208c39c0..e64e79c4b17e 100644 --- a/lib/libc/string/strerror.3 +++ b/lib/libc/string/strerror.3 @@ -36,12 +36,13 @@  .\"     @(#)strerror.3	8.1 (Berkeley) 6/9/93  .\" $FreeBSD$  .\" -.Dd June 9, 1993 +.Dd Nov 26, 2001  .Dt STRERROR 3  .Os  .Sh NAME  .Nm perror ,  .Nm strerror , +.Nm strerror_r ,  .Nm sys_errlist ,  .Nm sys_nerr  .Nd system error messages @@ -56,9 +57,12 @@  .In string.h  .Ft char *  .Fn strerror "int errnum" +.Ft int +.Fn strerror_r "int errnum" "char * strerrbuf" "size_t buflen"  .Sh DESCRIPTION  The -.Fn strerror +.Fn strerror , +.Fn strerror_r   and  .Fn perror  functions look up the error message string corresponding to an @@ -68,11 +72,18 @@ The  .Fn strerror  function accepts an error number argument  .Fa errnum -and -returns a pointer to the corresponding +and returns a pointer to the corresponding  message string.  .Pp  The +.Fn strerror_r +function renders the same result into +.Fa strerrbuf +for a maximum of  +.Fa buflen +characters and returns 0 upon success. +.Pp +The  .Fn perror  function finds the error message corresponding to the current  value of the global variable @@ -94,9 +105,37 @@ 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 and sets +.Va errno +to  +.Er EINVAL . +.Fn strerror_r +leaves +.Fa strerrbuf +unchanged and returns  +.Er EINVAL . +Error numbers recognized by this implementation fall in +the range 0 <=  +.Fa errnum +< +.Fa sys_nerr . +.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  +.Fa strerrbuf +will contain an error message that has been truncated and nul  +terminated to fit the length specified by  +.Fa buflen .  .Pp  The message strings can be accessed directly using the external  array @@ -107,6 +146,8 @@ contains a count of the messages in  .Va sys_errlist .  The use of these variables is deprecated;  .Fn strerror +or +.Fn strerror_r  should be used instead.  .Sh SEE ALSO  .Xr intro 2 , @@ -118,6 +159,13 @@ and  .Fn perror  functions first appeared in  .Bx 4.4 . +The  +.Fn strerror_r +function was implemented in +.Fx 4.4 +by  +.An Wes Peters +.Aq wes@freebsd.org .  .Sh BUGS  For unknown error numbers, the  .Fn strerror diff --git a/lib/libc/string/strerror.c b/lib/libc/string/strerror.c index d64120f225ca..085ea240be79 100644 --- a/lib/libc/string/strerror.c +++ b/lib/libc/string/strerror.c @@ -41,35 +41,106 @@ static const char rcsid[] =  #include <stdio.h>  #include <string.h> +#include <errno.h> + +int +strerror_r(int errnum, char *strerrbuf, size_t buflen) +{ +	int             len; + +	if ((errnum >= 0) && (errnum < sys_nerr)) { +		len = strlcpy(strerrbuf, (char *)sys_errlist[errnum], buflen); +		return ((len < buflen) ? 0 : ERANGE); +	} +	return (EINVAL); +}  char *  strerror(num) -	int num; +	int             num;  { -#define	UPREFIX	"Unknown error: " -	static char ebuf[40] = UPREFIX;		/* 64-bit number + slop */ -	register unsigned int errnum; -	register char *p, *t; -	char tmp[40]; +	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 */ -	errnum = num;				/* convert to unsigned */ -	if (errnum < sys_nerr) -		return ((char *)sys_errlist[errnum]); +	if ((num >= 0) && (num < sys_nerr)) +		return ((char *)sys_errlist[num]); -	/* Do this by hand, so we don't link to stdio(3). */ +	/* +	 * Set errno to EINVAL per P1003.1-200x Draft June 14, 2001. +	 */ +	errno = EINVAL; + +	/* +	 * 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 (num < 0) -		errnum = -errnum;  	do { -		*t++ = "0123456789"[errnum % 10]; -	} while (errnum /= 10); +		*t++ = "0123456789"[uerr % 10]; +	} while (uerr /= 10);  	if (num < 0)  		*t++ = '-'; -	for (p = ebuf + sizeof(UPREFIX) - 1;;) { + +	/* +	 * 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; -	}  	*p = '\0';  	return (ebuf);  } + +#ifdef STANDALONE_TEST + +#include <limits.h> + +main() +{ +	char            mybuf[64]; +	int             ret; + +	errno = 0; + +	printf("strerror(0) yeilds: %s\n", strerror(0)); +	printf("strerror(1) yeilds: %s\n", strerror(1)); +	printf("strerror(47) yeilds: %s\n", strerror(47)); +	printf("strerror(sys_nerr - 1) yeilds: %s\n", strerror(sys_nerr - 1)); +	printf("errno = %d\n", errno); errno = 0; + +	printf("strerror(sys_nerr) yeilds: %s\n", strerror(sys_nerr)); +	printf("errno = %d\n", errno);  errno = 0; + +	printf("strerror(437) yeilds: %s\n", strerror(437)); +	printf("errno = %d\n", errno);  errno = 0; + +	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); + +	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  | 
