summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorAndrey A. Chernov <ache@FreeBSD.org>2002-08-07 06:24:14 +0000
committerAndrey A. Chernov <ache@FreeBSD.org>2002-08-07 06:24:14 +0000
commitac70628eeba8c6baf4c76895fec9e083cbef8b9b (patch)
treefbe6db19ddcb43057af8b8335705b22eb932c490 /lib
parent6a858cb676dae2ec3d28b5b640e844fcfe5da34f (diff)
Notes
Diffstat (limited to 'lib')
-rw-r--r--lib/libc/locale/ldpart.c35
-rw-r--r--lib/libc/locale/rune.37
-rw-r--r--lib/libc/locale/setlocale.32
-rw-r--r--lib/libc/locale/setlocale.c176
-rw-r--r--lib/libc/locale/setrunelocale.c47
5 files changed, 169 insertions, 98 deletions
diff --git a/lib/libc/locale/ldpart.c b/lib/libc/locale/ldpart.c
index 7f9fa2944e40..345812003755 100644
--- a/lib/libc/locale/ldpart.c
+++ b/lib/libc/locale/ldpart.c
@@ -22,13 +22,15 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
- *
- * $FreeBSD$
*/
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/syslimits.h>
+#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
@@ -47,11 +49,11 @@ __part_load_locale(const char *name,
const char *category_filename,
int locale_buf_size_max,
int locale_buf_size_min,
- const char **dst_localebuf) {
-
+ const char **dst_localebuf)
+{
static char locale_buf_C[] = "C";
static int num_lines;
-
+ int saverr;
int fd;
char *lbuf;
char *p;
@@ -65,8 +67,7 @@ __part_load_locale(const char *name,
save_using_locale = *using_locale;
*using_locale = 0;
- if (name == NULL)
- goto no_locale;
+ /* 'name' must be already checked. */
if (!strcmp(name, "C") || !strcmp(name, "POSIX"))
return 0;
@@ -86,8 +87,8 @@ __part_load_locale(const char *name,
*/
namesize = strlen(name) + 1;
- if (!_PathLocale)
- goto no_locale;
+ /* 'PathLocale' must be already set & checked. */
+
/* Range checking not needed, 'name' size is limited */
strcpy(filename, _PathLocale);
strcat(filename, "/");
@@ -99,8 +100,10 @@ __part_load_locale(const char *name,
goto no_locale;
if (_fstat(fd, &st) != 0)
goto bad_locale;
- if (st.st_size <= 0)
+ if (st.st_size <= 0) {
+ errno = EFTYPE;
goto bad_locale;
+ }
bufsize = namesize + st.st_size;
locale_buf = NULL;
lbuf = (lbuf == NULL || lbuf == locale_buf_C) ?
@@ -117,15 +120,19 @@ __part_load_locale(const char *name,
/*
* Parse the locale file into localebuf.
*/
- if (plim[-1] != '\n')
+ if (plim[-1] != '\n') {
+ errno = EFTYPE;
goto bad_lbuf;
+ }
num_lines = split_lines(p, plim);
if (num_lines >= locale_buf_size_max)
num_lines = locale_buf_size_max;
else if (num_lines >= locale_buf_size_min)
num_lines = locale_buf_size_min;
- else
+ else {
+ errno = EFTYPE;
goto reset_locale;
+ }
set_from_buf(lbuf, num_lines, dst_localebuf);
/*
* Record the successful parse in the cache.
@@ -139,9 +146,9 @@ reset_locale:
locale_buf = locale_buf_C;
save_using_locale = 0;
bad_lbuf:
- free(lbuf);
+ saverr = errno; free(lbuf); errno = saverr;
bad_locale:
- (void)_close(fd);
+ saverr = errno; (void)_close(fd); errno = saverr;
no_locale:
*using_locale = save_using_locale;
return -1;
diff --git a/lib/libc/locale/rune.3 b/lib/libc/locale/rune.3
index 7c83ebc619c2..7c37c40b91ff 100644
--- a/lib/libc/locale/rune.3
+++ b/lib/libc/locale/rune.3
@@ -217,16 +217,13 @@ function returns one of the following values:
.It Er 0
.Fn setrunelocale
was successful.
-.It Bq Er EFAULT
+.It Bq Er EINVAL
.Fa locale
-was
-.Dv NULL .
+name was incorrect.
.It Bq Er ENOENT
The locale could not be found.
.It Bq Er EFTYPE
The file found was not a valid file.
-.It Bq Er EINVAL
-The encoding indicated by the locale was unknown.
.El
.Pp
The
diff --git a/lib/libc/locale/setlocale.3 b/lib/libc/locale/setlocale.3
index 77628b84b674..a1bb367bd7b1 100644
--- a/lib/libc/locale/setlocale.3
+++ b/lib/libc/locale/setlocale.3
@@ -282,6 +282,8 @@ which may be altered by later calls to
.Fn setlocale
or
.Fn localeconv .
+.Sh ERRORS
+No errors are defined.
.Sh FILES
.Bl -tag -width /usr/share/locale/locale/category -compact
.It Pa $PATH_LOCALE/ Ns Em locale/category
diff --git a/lib/libc/locale/setlocale.c b/lib/libc/locale/setlocale.c
index ae64d82d506a..6b249a9fa89b 100644
--- a/lib/libc/locale/setlocale.c
+++ b/lib/libc/locale/setlocale.c
@@ -35,17 +35,15 @@
* SUCH DAMAGE.
*/
-#ifdef LIBC_RCS
-static const char rcsid[] =
- "$FreeBSD$";
-#endif
-
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)setlocale.c 8.1 (Berkeley) 7/4/93";
#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
#include <sys/types.h>
#include <sys/stat.h>
+#include <errno.h>
#include <limits.h>
#include <locale.h>
#include <rune.h>
@@ -93,21 +91,24 @@ static char saved_categories[_LC_LAST][ENCODING_LEN + 1];
static char current_locale_string[_LC_LAST * (ENCODING_LEN + 1/*"/"*/ + 1)];
-static char *currentlocale __P((void));
-static char *loadlocale __P((int));
+static char *currentlocale(void);
+static int wrap_setrunelocale(char *);
+static char *loadlocale(int);
char *
setlocale(category, locale)
int category;
const char *locale;
{
- int i, j, len;
+ int i, j, len, saverr;
char *env, *r;
- if (category < LC_ALL || category >= _LC_LAST)
+ if (category < LC_ALL || category >= _LC_LAST) {
+ errno = EINVAL;
return (NULL);
+ }
- if (!locale)
+ if (locale == NULL)
return (category != LC_ALL ?
current_categories[category] : currentlocale());
@@ -123,47 +124,73 @@ setlocale(category, locale)
if (!*locale) {
env = getenv("LC_ALL");
- if (category != LC_ALL && (!env || !*env))
+ if (category != LC_ALL && (env == NULL || !*env))
env = getenv(categories[category]);
- if (!env || !*env)
+ if (env == NULL || !*env)
env = getenv("LANG");
- if (!env || !*env || strchr(env, '/'))
+ if (env == NULL || !*env)
env = "C";
- (void)strlcpy(new_categories[category], env, ENCODING_LEN + 1);
+ if (strlen(env) > ENCODING_LEN) {
+ errno = EINVAL;
+ return (NULL);
+ }
+ (void)strcpy(new_categories[category], env);
+
if (category == LC_ALL) {
for (i = 1; i < _LC_LAST; ++i) {
- if (!(env = getenv(categories[i])) || !*env)
+ if ((env = getenv(categories[i])) == NULL ||
+ !*env)
env = new_categories[LC_ALL];
- (void)strlcpy(new_categories[i], env, ENCODING_LEN + 1);
+ else if (strlen(env) > ENCODING_LEN) {
+ errno = EINVAL;
+ return (NULL);
+ }
+ (void)strcpy(new_categories[i], env);
}
}
- } else if (category != LC_ALL)
- (void)strlcpy(new_categories[category], locale, ENCODING_LEN + 1);
- else {
+ } else if (category != LC_ALL) {
+ if (strlen(locale) > ENCODING_LEN) {
+ errno = EINVAL;
+ return (NULL);
+ }
+ (void)strcpy(new_categories[category], locale);
+ } else {
if ((r = strchr(locale, '/')) == NULL) {
+ if (strlen(locale) > ENCODING_LEN) {
+ errno = EINVAL;
+ return (NULL);
+ }
for (i = 1; i < _LC_LAST; ++i)
- (void)strlcpy(new_categories[i], locale, ENCODING_LEN + 1);
+ (void)strcpy(new_categories[i], locale);
} else {
- for (i = 1; r[1] == '/'; ++r);
- if (!r[1])
+ for (i = 1; r[1] == '/'; ++r)
+ ;
+ if (!r[1]) {
+ errno = EINVAL;
return (NULL); /* Hmm, just slashes... */
+ }
do {
if (i == _LC_LAST)
break; /* Too many slashes... */
- len = r - locale > ENCODING_LEN ? ENCODING_LEN : r - locale;
- (void)strlcpy(new_categories[i], locale, len + 1);
+ if ((len = r - locale) > ENCODING_LEN) {
+ errno = EINVAL;
+ return (NULL);
+ }
+ (void)strlcpy(new_categories[i], locale,
+ len + 1);
i++;
locale = r;
while (*locale == '/')
- ++locale;
- while (*++r && *r != '/');
+ ++locale;
+ while (*++r && *r != '/')
+ ;
} while (*locale);
while (i < _LC_LAST) {
(void)strcpy(new_categories[i],
- new_categories[i-1]);
+ new_categories[i-1]);
i++;
}
}
@@ -175,12 +202,13 @@ setlocale(category, locale)
for (i = 1; i < _LC_LAST; ++i) {
(void)strcpy(saved_categories[i], current_categories[i]);
if (loadlocale(i) == NULL) {
+ saverr = errno;
for (j = 1; j < i; j++) {
(void)strcpy(new_categories[j],
- saved_categories[j]);
- /* XXX can fail too */
+ saved_categories[j]);
(void)loadlocale(j);
}
+ errno = saverr;
return (NULL);
}
}
@@ -197,14 +225,28 @@ currentlocale()
for (i = 2; i < _LC_LAST; ++i)
if (strcmp(current_categories[1], current_categories[i])) {
for (i = 2; i < _LC_LAST; ++i) {
- (void) strcat(current_locale_string, "/");
- (void) strcat(current_locale_string, current_categories[i]);
+ (void)strcat(current_locale_string, "/");
+ (void)strcat(current_locale_string,
+ current_categories[i]);
}
break;
}
return (current_locale_string);
}
+static int
+wrap_setrunelocale(locale)
+ char *locale;
+{
+ int ret = setrunelocale(locale);
+
+ if (ret != 0) {
+ errno = ret;
+ return (-1);
+ }
+ return (0);
+}
+
static char *
loadlocale(category)
int category;
@@ -212,6 +254,15 @@ loadlocale(category)
char *ret;
char *new = new_categories[category];
char *old = current_categories[category];
+ int (*func)();
+ int saverr;
+
+ if ((new[0] == '.' &&
+ (new[1] == '\0' || (new[1] == '.' && new[2] == '\0'))) ||
+ strchr(new, '/') != NULL) {
+ errno = EINVAL;
+ return (NULL);
+ }
if (_PathLocale == NULL) {
char *p = getenv("PATH_LOCALE");
@@ -222,8 +273,10 @@ loadlocale(category)
#endif
) {
if (strlen(p) + 1/*"/"*/ + ENCODING_LEN +
- 1/*"/"*/ + CATEGORY_LEN >= PATH_MAX)
+ 1/*"/"*/ + CATEGORY_LEN >= PATH_MAX) {
+ errno = ENAMETOOLONG;
return (NULL);
+ }
_PathLocale = strdup(p);
if (_PathLocale == NULL)
return (NULL);
@@ -231,35 +284,42 @@ loadlocale(category)
_PathLocale = _PATH_LOCALE;
}
- if (strcmp(new, old) == 0)
- return (old);
-
- if (category == LC_CTYPE) {
- ret = setrunelocale(new) ? NULL : new;
- if (!ret)
- (void)setrunelocale(old);
- else
- (void)strcpy(old, new);
- return (ret);
+ switch (category) {
+ case LC_CTYPE:
+ func = wrap_setrunelocale;
+ break;
+ case LC_COLLATE:
+ func = __collate_load_tables;
+ break;
+ case LC_TIME:
+ func = __time_load_locale;
+ break;
+ case LC_NUMERIC:
+ func = __numeric_load_locale;
+ break;
+ case LC_MONETARY:
+ func = __monetary_load_locale;
+ break;
+ case LC_MESSAGES:
+ func = __messages_load_locale;
+ break;
+ default:
+ errno = EINVAL;
+ return (NULL);
}
-#define LOAD_CATEGORY(CAT, FUNC) \
- if (category == CAT) { \
- ret = (FUNC(new) < 0) ? NULL : new; \
- if (!ret) \
- (void)FUNC(old); \
- else \
- (void)strcpy(old, new); \
- return (ret); \
- }
+ if (strcmp(new, old) == 0)
+ return (old);
- LOAD_CATEGORY(LC_COLLATE, __collate_load_tables);
- LOAD_CATEGORY(LC_TIME, __time_load_locale);
- LOAD_CATEGORY(LC_NUMERIC, __numeric_load_locale);
- LOAD_CATEGORY(LC_MONETARY, __monetary_load_locale);
- LOAD_CATEGORY(LC_MESSAGES, __messages_load_locale);
+ ret = func(new) != 0 ? NULL : new;
+ if (ret == NULL) {
+ saverr = errno;
+ if (func(old) != 0 && func("C") == 0)
+ (void)strcpy(old, "C");
+ errno = saverr;
+ } else
+ (void)strcpy(old, new);
- /* Just in case...*/
- return (NULL);
+ return (ret);
}
diff --git a/lib/libc/locale/setrunelocale.c b/lib/libc/locale/setrunelocale.c
index 55d6ba90b566..a42c02086836 100644
--- a/lib/libc/locale/setrunelocale.c
+++ b/lib/libc/locale/setrunelocale.c
@@ -32,10 +32,11 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
- *
- * $FreeBSD$
*/
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
#include <rune.h>
#include <errno.h>
#include <limits.h>
@@ -45,12 +46,12 @@
#include <unistd.h>
#include "setlocale.h"
-extern int _none_init __P((_RuneLocale *));
-extern int _UTF2_init __P((_RuneLocale *));
-extern int _EUC_init __P((_RuneLocale *));
-extern int _BIG5_init __P((_RuneLocale *));
-extern int _MSKanji_init __P((_RuneLocale *));
-extern _RuneLocale *_Read_RuneMagi __P((FILE *));
+extern int _none_init(_RuneLocale *);
+extern int _UTF2_init(_RuneLocale *);
+extern int _EUC_init(_RuneLocale *);
+extern int _BIG5_init(_RuneLocale *);
+extern int _MSKanji_init(_RuneLocale *);
+extern _RuneLocale *_Read_RuneMagi(FILE *);
int
setrunelocale(encoding)
@@ -60,15 +61,19 @@ setrunelocale(encoding)
char name[PATH_MAX];
_RuneLocale *rl;
- if (!encoding || strlen(encoding) > ENCODING_LEN)
- return(EFAULT);
+ if (!encoding || !*encoding || strlen(encoding) > ENCODING_LEN ||
+ (encoding[0] == '.' &&
+ (encoding[1] == '\0' ||
+ (encoding[1] == '.' && encoding[2] == '\0'))) ||
+ strchr(encoding, '/') != NULL)
+ return (EINVAL);
/*
* The "C" and "POSIX" locale are always here.
*/
if (!strcmp(encoding, "C") || !strcmp(encoding, "POSIX")) {
_CurrentRuneLocale = &_DefaultRuneLocale;
- return(0);
+ return (0);
}
if (_PathLocale == NULL) {
@@ -81,7 +86,7 @@ setrunelocale(encoding)
) {
if (strlen(p) + 1/*"/"*/ + ENCODING_LEN +
1/*"/"*/ + CATEGORY_LEN >= PATH_MAX)
- return(EFAULT);
+ return (ENAMETOOLONG);
_PathLocale = strdup(p);
if (_PathLocale == NULL)
return (errno);
@@ -95,27 +100,27 @@ setrunelocale(encoding)
(void) strcat(name, "/LC_CTYPE");
if ((fp = fopen(name, "r")) == NULL)
- return(ENOENT);
+ return (errno);
if ((rl = _Read_RuneMagi(fp)) == 0) {
fclose(fp);
- return(EFTYPE);
+ return (EFTYPE);
}
fclose(fp);
if (!rl->encoding[0])
- return(EINVAL);
+ return (EFTYPE);
else if (!strcmp(rl->encoding, "NONE"))
- return(_none_init(rl));
+ return (_none_init(rl));
else if (!strcmp(rl->encoding, "UTF2"))
- return(_UTF2_init(rl));
+ return (_UTF2_init(rl));
else if (!strcmp(rl->encoding, "EUC"))
- return(_EUC_init(rl));
+ return (_EUC_init(rl));
else if (!strcmp(rl->encoding, "BIG5"))
- return(_BIG5_init(rl));
+ return (_BIG5_init(rl));
else if (!strcmp(rl->encoding, "MSKanji"))
- return(_MSKanji_init(rl));
+ return (_MSKanji_init(rl));
else
- return(EINVAL);
+ return (EFTYPE);
}