summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorWes Peters <wes@FreeBSD.org>2001-12-20 06:31:26 +0000
committerWes Peters <wes@FreeBSD.org>2001-12-20 06:31:26 +0000
commit0b6d38c427a9bc4123401e283c9255a12701d46a (patch)
treeb71b6e099a52f19081a81da58f0a9829681760c5 /lib
parent933ff66cf7afdccd2d734e467ec887e947fbbe9e (diff)
Notes
Diffstat (limited to 'lib')
-rw-r--r--lib/libc/string/strerror.360
-rw-r--r--lib/libc/string/strerror.c107
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