On Fri, May 31, 2013 at 06:01:14PM -0700, Matthew Dempsky wrote: > In your man page diff, you should make use of .Dv and .Ev to identify > the defines and environment variables. > > Instead of setting FD_CLOEXEC with fcntl(), just use O_CLOEXEC when opening. > > It looks like parse_lang() won't handle locales like "C.UTF-8" because > there's no '_'.
Fixed. > I think you should be able to implement the %l/%t/%c stuff without > needing to call strdup() for each one (e.g., by just doing a one time > pass over the locale string up front and noting where the '_' and '.' > chars are). Otherwise, you should report strdup() failures as ENOMEM > to the catopen() caller, I think. Nice, this makes the diff a lot smaller. Thanks! Also using dots in filenames as suggested by bluhm. Index: lib/libc/Makefile =================================================================== RCS file: /cvs/src/lib/libc/Makefile,v retrieving revision 1.31 diff -u -p -r1.31 Makefile --- lib/libc/Makefile 15 Aug 2012 18:08:22 -0000 1.31 +++ lib/libc/Makefile 1 Jun 2013 01:22:57 -0000 @@ -17,7 +17,11 @@ LDADD=-nodefaultlibs -lgcc LIBCSRCDIR=${.CURDIR} .include "${LIBCSRCDIR}/Makefile.inc" -NLS= C.msg Pig.msg da.msg de.msg es.msg fi.msg fr.msg nl.msg no.msg ru.msg sv.msg it.msg +NLS= C.msg Pig.msg da.ISO8859-1.msg da.UTF-8.msg de.ISO8859-1.msg \ + de.UTF-8.msg es.ISO8859-1.msg es.UTF-8.msg fi.ISO8859-1.msg \ + fi.UTF-8.msg fr.ISO8859-1.msg fr.UTF-8.msg it.UTF-8.msg \ + nl.ISO8859-1.msg nl.UTF-8.msg no.ISO8859-1.msg no.UTF-8.msg \ + ru-KOI8-R.msg ru.UTF-8.msg sv.ISO8859-1.msg sv.UTF-8.msg copy-to-libkern: copy-to-libkern-machind copy-to-libkern-machdep Index: lib/libc/nls/catopen.3 =================================================================== RCS file: /cvs/src/lib/libc/nls/catopen.3,v retrieving revision 1.6 diff -u -p -r1.6 catopen.3 --- lib/libc/nls/catopen.3 31 May 2007 19:19:30 -0000 1.6 +++ lib/libc/nls/catopen.3 1 Jun 2013 01:24:33 -0000 @@ -33,9 +33,18 @@ is used with substituted for .Ql \&%N . .Pp -The +If the +.Fa oflag +argument is +.Dv NL_CAT_LOCALE , +the +.Ev LC_MESSAGES +environment variable is used to select the message catalog. +If the .Fa oflag -argument is reserved for future use and should be set to zero. +argument is zero, the +.Ev LANG +environment variable is used to select the message catalog. .Sh RETURN VALUES Upon successful completion, .Fn catopen @@ -43,11 +52,6 @@ returns a message catalog descriptor. Otherwise, \-1 is returned and .Va errno is set to indicate the error. -.Sh ERRORS -.Bl -tag -width Er -.It Bq Er ENOMEM -Insufficient memory available. -.El .Sh SEE ALSO .Xr catclose 3 , .Xr catgets 3 @@ -55,4 +59,4 @@ Insufficient memory available. The .Fn catopen function conforms to -.St -xpg3 . +.St -p1003.1-2008 . Index: lib/libc/nls/catopen.c =================================================================== RCS file: /cvs/src/lib/libc/nls/catopen.c,v retrieving revision 1.14 diff -u -p -r1.14 catopen.c --- lib/libc/nls/catopen.c 12 Jul 2011 21:31:20 -0000 1.14 +++ lib/libc/nls/catopen.c 1 Jun 2013 02:11:10 -0000 @@ -41,7 +41,7 @@ #include <fcntl.h> #include <nl_types.h> -#define NLS_DEFAULT_PATH "/usr/share/nls/%L/%N.cat:/usr/share/nls/%N/%L" +#define NLS_DEFAULT_PATH "/usr/share/nls/%L/%N.cat:/usr/share/nls/%l.%c/%N.cat:/usr/share/nls/%l/%N.cat" #define NLS_DEFAULT_LANG "C" static nl_catd load_msgcat(const char *); @@ -53,7 +53,7 @@ _catopen(const char *name, int oflag) char tmppath[PATH_MAX]; char *nlspath; char *lang; - char *s, *t; + char *s, *t, *sep, *dot; const char *u; nl_catd catd; @@ -66,28 +66,66 @@ _catopen(const char *name, int oflag) if (issetugid() != 0 || (nlspath = getenv("NLSPATH")) == NULL) nlspath = NLS_DEFAULT_PATH; - if ((lang = getenv("LANG")) == NULL) + + lang = NULL; + if (oflag & NL_CAT_LOCALE) + lang = getenv("LC_MESSAGES"); + if (lang == NULL) + lang = getenv("LANG"); + if (lang == NULL) + lang = NLS_DEFAULT_LANG; + if (strcmp(lang, "POSIX") == 0) lang = NLS_DEFAULT_LANG; s = nlspath; - t = tmppath; + t = tmppath; + + /* + * Locale names are of the form language[_territory][.codeset]. + * See POSIX-1-2008 "8.2 Internationalization Variables" + */ + sep = strchr(lang, '_'); + dot = strrchr(lang, '.'); do { while (*s && *s != ':') { if (*s == '%') { switch (*(++s)) { - case 'L': /* locale */ + case 'L': /* LANG or LC_MESSAGES */ u = lang; while (*u && t < tmppath + PATH_MAX-1) *t++ = *u++; break; - case 'N': /* name */ + case 'N': /* value of name parameter */ u = name; while (*u && t < tmppath + PATH_MAX-1) *t++ = *u++; break; - case 'l': /* lang */ - case 't': /* territory */ - case 'c': /* codeset */ + case 'l': /* language part */ + u = lang; + while (*u && t < tmppath + PATH_MAX-1) { + *t++ = *u++; + if (sep && u >= sep) + break; + if (dot && u >= dot) + break; + } + break; + case 't': /* territory part */ + if (sep == NULL) + break; + u = sep + 1; + while (*u && t < tmppath + PATH_MAX-1) { + *t++ = *u++; + if (dot && u >= dot) + break; + } + break; + case 'c': /* codeset part */ + if (dot == NULL) + break; + u = dot + 1; + while (*u && t < tmppath + PATH_MAX-1) + *t++ = *u++; break; default: if (t < tmppath + PATH_MAX-1) @@ -121,7 +159,7 @@ load_msgcat(const char *path) void *data; int fd; - if ((fd = open(path, O_RDONLY)) == -1) + if ((fd = open(path, O_RDONLY|O_CLOEXEC)) == -1) return (nl_catd) -1; if (fstat(fd, &st) != 0) { Index: lib/libc/string/strerror_r.c =================================================================== RCS file: /cvs/src/lib/libc/string/strerror_r.c,v retrieving revision 1.7 diff -u -p -r1.7 strerror_r.c --- lib/libc/string/strerror_r.c 1 Mar 2007 16:29:09 -0000 1.7 +++ lib/libc/string/strerror_r.c 31 May 2013 19:30:13 -0000 @@ -75,7 +75,7 @@ __num2string(int num, int sign, int seti #ifdef NLS nl_catd catd; - catd = catopen("libc", 0); + catd = catopen("libc", NL_CAT_LOCALE); #endif if (0 <= num && num < max) {