Add strerror_r function per Posix prototype.

Reviewed by:	Mike Barcroft <mike@FreeBSD.org>
MFC after:	2 weeks
This commit is contained in:
wes 2001-11-27 07:39:46 +00:00
parent 2181f49061
commit bdb2c68332
3 changed files with 113 additions and 28 deletions

View File

@ -62,6 +62,7 @@ int strcoll __P((const char *, const char *));
char *strcpy __P((char *, const char *));
size_t strcspn __P((const char *, const char *));
char *strerror __P((int));
int strerror_r __P((int, char *, size_t));
size_t strlen __P((const char *));
char *strncat __P((char *, const char *, size_t));
int strncmp __P((const char *, const char *, size_t));

View File

@ -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,27 @@ 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. 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.
.Pp
The
.Fn perror
function finds the error message corresponding to the current
value of the global variable
@ -107,6 +127,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 +140,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

View File

@ -39,35 +39,90 @@ __FBSDID("$FreeBSD$");
#include <stdio.h>
#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;
}
/* Print unknown errno by hand so we don't link to stdio(3). */
t = tmp;
if (errnum < 0)
uerr = -uerr;
do {
*t++ = "0123456789"[uerr % 10];
} while (uerr /= 10);
if (errnum < 0)
*t++ = '-';
strlcpy(strerrbuf, UPREFIX, buflen);
for (p = strerrbuf + sizeof(UPREFIX) - 1; p < strerrbuf + buflen; ) {
*p++ = *--t;
if (t <= tmp)
break;
}
if (p < strerrbuf + buflen) {
*p = '\0';
return 0;
}
return ERANGE;
}
/*
* 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;
{
#define UPREFIX "Unknown error: "
static char ebuf[40] = UPREFIX; /* 64-bit number + slop */
register unsigned int errnum;
register char *p, *t;
char tmp[40];
unsigned int uerr;
static char ebuf[ERR_LEN];
errnum = num; /* convert to unsigned */
if (errnum < sys_nerr)
return ((char *)sys_errlist[errnum]);
uerr = num; /* convert to unsigned */
if (uerr < sys_nerr)
return (char *)sys_errlist[uerr];
/* Do this by hand, so we don't link to stdio(3). */
t = tmp;
if (num < 0)
errnum = -errnum;
do {
*t++ = "0123456789"[errnum % 10];
} while (errnum /= 10);
if (num < 0)
*t++ = '-';
for (p = ebuf + sizeof(UPREFIX) - 1;;) {
*p++ = *--t;
if (t <= tmp)
break;
}
*p = '\0';
return (ebuf);
/* 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;
}
#ifdef STANDALONE_TEST
main()
{
char mybuf[64];
int ret;
printf("strerror(47) yeilds: %s\n", strerror(47));
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);
printf("strerror_r on short buffer returns %d (%s)\n", ret, mybuf);
}
#endif