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

Reply via email to