strerror.c revision 220376
175584Sru/*-
275584Sru * Copyright (c) 1988, 1993
375584Sru *	The Regents of the University of California.  All rights reserved.
475584Sru *
575584Sru * Redistribution and use in source and binary forms, with or without
675584Sru * modification, are permitted provided that the following conditions
775584Sru * are met:
875584Sru * 1. Redistributions of source code must retain the above copyright
975584Sru *    notice, this list of conditions and the following disclaimer.
1075584Sru * 2. Redistributions in binary form must reproduce the above copyright
1175584Sru *    notice, this list of conditions and the following disclaimer in the
1275584Sru *    documentation and/or other materials provided with the distribution.
1375584Sru * 4. Neither the name of the University nor the names of its contributors
1475584Sru *    may be used to endorse or promote products derived from this software
1575584Sru *    without specific prior written permission.
1675584Sru *
1775584Sru * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
1875584Sru * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1975584Sru * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2075584Sru * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2175584Sru * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2275584Sru * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2375584Sru * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2475584Sru * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2575584Sru * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2675584Sru * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2775584Sru * SUCH DAMAGE.
2875584Sru */
2975584Sru
3075584Sru#if defined(LIBC_SCCS) && !defined(lint)
3175584Srustatic char sccsid[] = "@(#)strerror.c	8.1 (Berkeley) 6/4/93";
3275584Sru#endif /* LIBC_SCCS and not lint */
3375584Sru#include <sys/cdefs.h>
3475584Sru__FBSDID("$FreeBSD: head/lib/libc/string/strerror.c 220376 2011-04-05 21:56:05Z jilles $");
3575584Sru
3675584Sru#if defined(NLS)
3775584Sru#include <nl_types.h>
3875584Sru#endif
3975584Sru
4075584Sru#include <limits.h>
4175584Sru#include <errno.h>
4275584Sru#include <string.h>
4375584Sru#include <stdio.h>
4475584Sru
4575584Sru#define	UPREFIX		"Unknown error"
4675584Sru
4775584Sru/*
4875584Sru * Define a buffer size big enough to describe a 64-bit signed integer
4975584Sru * converted to ASCII decimal (19 bytes), with an optional leading sign
5075584Sru * (1 byte); finally, we get the prefix, delimiter (": ") and a trailing
5175584Sru * NUL from UPREFIX.
5275584Sru */
5375584Sru#define	EBUFSIZE	(20 + 2 + sizeof(UPREFIX))
5475584Sru
5575584Sru/*
5675584Sru * Doing this by hand instead of linking with stdio(3) avoids bloat for
5775584Sru * statically linked binaries.
5875584Sru */
5975584Srustatic void
6075584Sruerrstr(int num, char *uprefix, char *buf, size_t len)
6175584Sru{
6275584Sru	char *t;
6375584Sru	unsigned int uerr;
6475584Sru	char tmp[EBUFSIZE];
6575584Sru
6675584Sru	t = tmp + sizeof(tmp);
6775584Sru	*--t = '\0';
6875584Sru	uerr = (num >= 0) ? num : -num;
6975584Sru	do {
7075584Sru		*--t = "0123456789"[uerr % 10];
7175584Sru	} while (uerr /= 10);
7275584Sru	if (num < 0)
7375584Sru		*--t = '-';
7475584Sru	*--t = ' ';
7575584Sru	*--t = ':';
7675584Sru	strlcpy(buf, uprefix, len);
7775584Sru	strlcat(buf, t, len);
7875584Sru}
7975584Sru
8075584Sruint
8175584Srustrerror_r(int errnum, char *strerrbuf, size_t buflen)
8275584Sru{
8375584Sru	int retval = 0;
8475584Sru#if defined(NLS)
8575584Sru	int saved_errno = errno;
8675584Sru	nl_catd catd;
8775584Sru	catd = catopen("libc", NL_CAT_LOCALE);
8875584Sru#endif
8975584Sru
9075584Sru	if (errnum < 0 || errnum >= sys_nerr) {
9175584Sru		errstr(errnum,
9275584Sru#if defined(NLS)
9375584Sru			catgets(catd, 1, 0xffff, UPREFIX),
9475584Sru#else
9575584Sru			UPREFIX,
9675584Sru#endif
9775584Sru			strerrbuf, buflen);
9875584Sru		retval = EINVAL;
9975584Sru	} else {
10075584Sru		if (strlcpy(strerrbuf,
10175584Sru#if defined(NLS)
10275584Sru			catgets(catd, 1, errnum, sys_errlist[errnum]),
10375584Sru#else
10475584Sru			sys_errlist[errnum],
10575584Sru#endif
10675584Sru			buflen) >= buflen)
10775584Sru		retval = ERANGE;
10875584Sru	}
10975584Sru
11075584Sru#if defined(NLS)
11175584Sru	catclose(catd);
11275584Sru	errno = saved_errno;
11375584Sru#endif
11475584Sru
11575584Sru	return (retval);
11675584Sru}
11775584Sru
11875584Sruchar *
11975584Srustrerror(int num)
12075584Sru{
12175584Sru	static char ebuf[NL_TEXTMAX];
12275584Sru
12375584Sru	if (strerror_r(num, ebuf, sizeof(ebuf)) != 0)
12475584Sru	errno = EINVAL;
12575584Sru	return (ebuf);
12675584Sru}
12775584Sru