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) {