Browse Source

build the error message in strerror_r.c directly, avoiding one copy there.

handle a few subtle details caught by the regression tests: correct
termination, non copying if buffer length == 0, errno setting.
let all former users of __strerror go through strerror_r.
Work by Todd Miller and I. Okay millert@.
OPENBSD_3_6
espie 20 years ago
parent
commit
075eca378d
3 changed files with 109 additions and 120 deletions
  1. +5
    -100
      src/lib/libc/string/__strerror.c
  2. +4
    -10
      src/lib/libc/string/strerror.c
  3. +100
    -10
      src/lib/libc/string/strerror_r.c

+ 5
- 100
src/lib/libc/string/__strerror.c View File

@ -28,114 +28,19 @@
*/ */
#if defined(LIBC_SCCS) && !defined(lint) #if defined(LIBC_SCCS) && !defined(lint)
static char *rcsid = "$OpenBSD: __strerror.c,v 1.12 2004/05/01 10:52:59 espie Exp $";
static char *rcsid = "$OpenBSD: __strerror.c,v 1.13 2004/05/03 05:07:34 espie Exp $";
#endif /* LIBC_SCCS and not lint */ #endif /* LIBC_SCCS and not lint */
#ifdef NLS
#define catclose _catclose
#define catgets _catgets
#define catopen _catopen
#include <nl_types.h>
#endif
#define sys_errlist _sys_errlist
#define sys_nerr _sys_nerr
#include <errno.h>
#include <limits.h> #include <limits.h>
#include <stdio.h>
#include <string.h> #include <string.h>
static size_t
__digits10(unsigned int num)
{
size_t i = 0;
do {
num /= 10;
i++;
} while (num != 0);
return i;
}
void
__itoa(int num, char *buffer, size_t start, size_t end)
{
size_t pos;
unsigned int a;
int neg;
if (num < 0) {
a = -num;
neg = 1;
}
else {
a = num;
neg = 0;
}
pos = start + __digits10(a);
if (neg)
pos++;
if (pos < end)
buffer[pos] = '\0';
else
buffer[end-1] = '\0';
pos--;
do {
if (pos < end)
buffer[pos] = (a % 10) + '0';
pos--;
a /= 10;
} while (a != 0);
if (neg)
if (pos < end)
buffer[pos] = '-';
}
/* /*
* Since perror() is not allowed to change the contents of strerror()'s
* static buffer, both functions supply their own buffers to the
* internal function __strerror().
* __strerror() has been deprecated in favor of strerror_r()
* and is provided for source compatibility only.
*/ */
char * char *
__strerror(int num, char *buf) __strerror(int num, char *buf)
{ {
#define UPREFIX "Unknown error: "
int len;
#ifdef NLS
int save_errno;
nl_catd catd;
catd = catopen("libc", 0);
#endif
if (num >= 0 && num < sys_nerr) {
#ifdef NLS
strlcpy(buf, catgets(catd, 1, num,
(char *)sys_errlist[num]), NL_TEXTMAX);
#else
return(sys_errlist[num]);
#endif
} else {
#ifdef NLS
len = strlcpy(buf, catgets(catd, 1, 0xffff, UPREFIX), NL_TEXTMAX);
#else
len = strlcpy(buf, UPREFIX, NL_TEXTMAX);
#endif
__itoa(num, buf, len, NL_TEXTMAX);
errno = EINVAL;
}
#ifdef NLS
save_errno = errno;
catclose(catd);
errno = save_errno;
#endif
return buf;
(void)strerror_r(num, buf, NL_TEXTMAX);
return (buf);
} }

+ 4
- 10
src/lib/libc/string/strerror.c View File

@ -28,23 +28,17 @@
*/ */
#if defined(LIBC_SCCS) && !defined(lint) #if defined(LIBC_SCCS) && !defined(lint)
static char *rcsid = "$OpenBSD: strerror.c,v 1.5 2003/06/11 21:08:16 deraadt Exp $";
static char *rcsid = "$OpenBSD: strerror.c,v 1.6 2004/05/03 05:07:34 espie Exp $";
#endif /* LIBC_SCCS and not lint */ #endif /* LIBC_SCCS and not lint */
#include <string.h> #include <string.h>
#include <limits.h> #include <limits.h>
/*
* Since perror() is not allowed to change the contents of strerror()'s
* static buffer, both functions supply their own buffers to the
* internal function __strerror().
*/
extern char *__strerror(int, char *);
char * char *
strerror(int num) strerror(int num)
{ {
static char buf[NL_TEXTMAX]; static char buf[NL_TEXTMAX];
return __strerror(num, buf);
(void)strerror_r(num, buf, sizeof(buf));
return (buf);
} }

+ 100
- 10
src/lib/libc/string/strerror_r.c View File

@ -1,30 +1,120 @@
/* $OpenBSD: strerror_r.c,v 1.1 2002/11/21 20:45:05 marc Exp $ */
/* $OpenBSD: strerror_r.c,v 1.2 2004/05/03 05:07:34 espie Exp $ */
/* Public Domain <marc@snafu.org> */ /* Public Domain <marc@snafu.org> */
#if defined(LIBC_SCCS) && !defined(lint) #if defined(LIBC_SCCS) && !defined(lint)
static char *rcsid = "$OpenBSD: strerror_r.c,v 1.1 2002/11/21 20:45:05 marc Exp $";
static char *rcsid = "$OpenBSD: strerror_r.c,v 1.2 2004/05/03 05:07:34 espie Exp $";
#endif /* LIBC_SCCS and not lint */ #endif /* LIBC_SCCS and not lint */
#ifdef NLS
#define catclose _catclose
#define catgets _catgets
#define catopen _catopen
#include <nl_types.h>
#endif
#define sys_errlist _sys_errlist
#define sys_nerr _sys_nerr
#include <errno.h> #include <errno.h>
#include <limits.h> #include <limits.h>
#include <string.h> #include <string.h>
extern char *__strerror(int, char *);
static size_t
__digits10(unsigned int num)
{
size_t i = 0;
do {
num /= 10;
i++;
} while (num != 0);
return i;
}
static void
__itoa(int num, char *buffer, size_t start, size_t end)
{
size_t pos;
unsigned int a;
int neg;
if (num < 0) {
a = -num;
neg = 1;
}
else {
a = num;
neg = 0;
}
pos = start + __digits10(a);
if (neg)
pos++;
if (pos < end)
buffer[pos] = '\0';
else {
if (end)
buffer[--end] = '\0'; /* XXX */
}
pos--;
do {
if (pos < end)
buffer[pos] = (a % 10) + '0';
pos--;
a /= 10;
} while (a != 0);
if (neg)
if (pos < end)
buffer[pos] = '-';
}
#define UPREFIX "Unknown error: "
int int
strerror_r(int errnum, char *strerrbuf, size_t buflen) strerror_r(int errnum, char *strerrbuf, size_t buflen)
{ {
int save_errno; int save_errno;
int ret_errno; int ret_errno;
char buf[NL_TEXTMAX];
size_t len;
#ifdef NLS
nl_catd catd;
#endif
save_errno = errno; save_errno = errno;
errno = 0;
__strerror(errnum, buf);
if (strlcpy(strerrbuf, buf, buflen) >= buflen)
errno = ERANGE;
ret_errno = errno;
errno = save_errno;
ret_errno = 0;
#ifdef NLS
catd = catopen("libc", 0);
#endif
if (errnum >= 0 && errnum < sys_nerr) {
#ifdef NLS
len = strlcpy(strerrbuf, catgets(catd, 1, errnum,
(char *)sys_errlist[errnum]), buflen);
#else
len = strlcpy(strerrbuf, sys_errlist[errnum], buflen);
#endif
if (len >= buflen)
ret_errno = ERANGE;
} else {
#ifdef NLS
len = strlcpy(strerrbuf, catgets(catd, 1, 0xffff, UPREFIX),
buflen);
#else
len = strlcpy(strerrbuf, UPREFIX, buflen);
#endif
__itoa(errnum, strerrbuf, len, buflen);
ret_errno = EINVAL;
}
#ifdef NLS
catclose(catd);
#endif
errno = ret_errno ? ret_errno : save_errno;
return (ret_errno); return (ret_errno);
} }

Loading…
Cancel
Save