Add strerror_r function per Posix prototype.
Reviewed by: Mike Barcroft <mike@FreeBSD.org> MFC after: 2 weeks
This commit is contained in:
parent
0cf1f69300
commit
9c324dc0c0
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=86944
@ -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));
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
/* 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;
|
||||
}
|
||||
*p = '\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
|
||||
|
Loading…
Reference in New Issue
Block a user