]> git.saurik.com Git - apple/libc.git/blobdiff - string/FreeBSD/strerror.c
Libc-1081.1.3.tar.gz
[apple/libc.git] / string / FreeBSD / strerror.c
index b1c491312d0aa49e1beb558a68ba48fa7e112155..46144e36ba583e5df72736082e3f3324f36cf606 100644 (file)
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
  * 4. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
 static char sccsid[] = "@(#)strerror.c 8.1 (Berkeley) 6/4/93";
 #endif /* LIBC_SCCS and not lint */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/lib/libc/string/strerror.c,v 1.13 2003/05/01 19:03:14 nectar Exp $");
+__FBSDID("$FreeBSD: src/lib/libc/string/strerror.c,v 1.16 2007/01/09 00:28:12 imp Exp $");
 
+#if defined(NLS)
+#include <nl_types.h>
+#endif
+
+#include <limits.h>
 #include <errno.h>
-#include <stdio.h>
 #include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
 
-#define        UPREFIX         "Unknown error"
+#define        UPREFIX         "Unknown error"
 
 /*
  * Define a buffer size big enough to describe a 64-bit signed integer
  * converted to ASCII decimal (19 bytes), with an optional leading sign
- * (1 byte); finally, we get the prefix and a trailing NUL from UPREFIX.
+ * (1 byte); finally, we get the prefix, delimiter (": ") and a trailing
+ * NUL from UPREFIX.
  */
-#define        EBUFSIZE        (20 + sizeof(UPREFIX))
+#define        EBUFSIZE        (20 + 2 + sizeof(UPREFIX))
 
+#ifndef BUILDING_VARIANT
 /*
  * Doing this by hand instead of linking with stdio(3) avoids bloat for
  * statically linked binaries.
  */
-static void
-errstr(int num, char *buf, size_t len)
+__private_extern__ void
+__errstr(int num, char *uprefix, char *buf, size_t len)
 {
        char *t;
        unsigned int uerr;
@@ -69,31 +73,75 @@ errstr(int num, char *buf, size_t len)
        } while (uerr /= 10);
        if (num < 0)
                *--t = '-';
-       strlcpy(buf, UPREFIX, len);
+       *--t = ' ';
+       *--t = ':';
+       strlcpy(buf, uprefix, len);
        strlcat(buf, t, len);
 }
 
 int
 strerror_r(int errnum, char *strerrbuf, size_t buflen)
 {
+       int retval = 0;
+#if defined(NLS)
+       int saved_errno = errno;
+       nl_catd catd;
+       catd = catopen("libc", NL_CAT_LOCALE);
+#endif
 
-       if (errnum < 1 || errnum >= sys_nerr) {
-               errstr(errnum, strerrbuf, buflen);
-               return (EINVAL);
+       if (errnum < 0 || errnum >= sys_nerr) {
+               __errstr(errnum,
+#if defined(NLS)
+                       catgets(catd, 1, 0xffff, UPREFIX),
+#else
+                       UPREFIX,
+#endif
+                       strerrbuf, buflen);
+               retval = EINVAL;
+       } else {
+               if (strlcpy(strerrbuf,
+#if defined(NLS)
+                       catgets(catd, 1, errnum, sys_errlist[errnum]),
+#else
+                       sys_errlist[errnum],
+#endif
+                       buflen) >= buflen)
+               retval = ERANGE;
        }
-       if (strlcpy(strerrbuf, sys_errlist[errnum], buflen) >= buflen)
-               return (ERANGE);
-       return (0);
+
+#if defined(NLS)
+       catclose(catd);
+       errno = saved_errno;
+#endif
+
+       return (retval);
 }
 
+__private_extern__ char *__strerror_ebuf = NULL;
+#else /* BUILDING_VARIANT */
+__private_extern__ void __errstr(int, char *, size_t);
+
+extern char *__strerror_ebuf;
+#endif /* !BUILDING_VARIANT */
+
 char *
 strerror(int num)
 {
-       static char ebuf[EBUFSIZE];
+       // Dynamically allocate a big buffer to receive the text then shrink it
+       // down to the actual size needed.
+       size_t ebufsiz = NL_TEXTMAX;
 
-       if (num > 0 && num < sys_nerr)
-               return ((char *)sys_errlist[num]);
-       errno = EINVAL;
-       errstr(num, ebuf, sizeof(ebuf));
-       return (ebuf);
+       if (__strerror_ebuf == NULL) {
+               __strerror_ebuf = calloc(1, ebufsiz);
+               if (__strerror_ebuf == NULL) {
+                       return NULL;
+               }
+       }
+       
+       if (strerror_r(num, __strerror_ebuf, ebufsiz) != 0) {
+#if !__DARWIN_UNIX03
+               errno = EINVAL;
+#endif
+       }
+       return __strerror_ebuf;
 }