LOCALE_HOME for strtime(3)

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

LOCALE_HOME for strtime(3)

Jan Stary
The OpenBSD libc tends to ignore the LC_* except LC_CTYPE.
However, strftime(3) seems to support a LOCALE_HOME thing,
where the user overrides LC_TIME with his own names of months etc.
Looking at http://cvsweb.openbsd.org/src/lib/libc/time/strftime.c ,
it has been there since the beginning.

The manpage does not mention it; on the contrary,

  The OpenBSD implementation always uses the C locale and ignores
  the global locale, the thread-specific locale, and the locale argument.

and

  On systems other than OpenBSD, the LC_TIME locale(1) category can
  cause erratic output; see CAVEATS in setlocale(3) for details.

Is that code intentionally there?
The diff below removes it.

        Jan


Index: lib/libc/time/strftime.c
===================================================================
RCS file: /cvs/src/lib/libc/time/strftime.c,v
retrieving revision 1.32
diff -u -p -r1.32 strftime.c
--- lib/libc/time/strftime.c 29 Jun 2019 16:12:21 -0000 1.32
+++ lib/libc/time/strftime.c 15 Jul 2020 21:40:10 -0000
@@ -48,16 +48,7 @@ struct lc_time_T {
  const char * date_fmt;
 };
 
-#ifdef LOCALE_HOME
-#include "sys/stat.h"
-static struct lc_time_T localebuf;
-static struct lc_time_T * _loc(void);
-#define Locale _loc()
-#endif /* defined LOCALE_HOME */
-#ifndef LOCALE_HOME
 #define Locale (&C_time_locale)
-#endif /* !defined LOCALE_HOME */
-
 static const struct lc_time_T C_time_locale = {
  {
  "Jan", "Feb", "Mar", "Apr", "May", "Jun",
@@ -124,9 +115,6 @@ strftime(char *s, size_t maxsize, const
  int warn;
 
  tzset();
-#ifdef LOCALE_HOME
- localebuf.mon[0] = 0;
-#endif /* defined LOCALE_HOME */
  warn = IN_NONE;
  p = _fmt(((format == NULL) ? "%c" : format), t, s, s + maxsize, &warn);
  if (p == s + maxsize) {
@@ -558,135 +546,3 @@ _yconv(int a, int b, int convert_top, in
  pt = _conv(((trail < 0) ? -trail : trail), "%02d", pt, ptlim);
  return pt;
 }
-
-#ifdef LOCALE_HOME
-static struct lc_time_T *
-_loc(void)
-{
- static const char locale_home[] = LOCALE_HOME;
- static const char lc_time[] = "LC_TIME";
- static char * locale_buf;
-
- int fd;
- int oldsun; /* "...ain't got nothin' to do..." */
- int len;
- char * lbuf;
- char * nlbuf;
- char * name;
- char * p;
- const char ** ap;
- const char * plim;
- char filename[PATH_MAX];
- struct stat st;
- size_t namesize;
- size_t bufsize;
-
- /*
- ** Use localebuf.mon[0] to signal whether locale is already set up.
- */
- if (localebuf.mon[0])
- return &localebuf;
- name = setlocale(LC_TIME, (char *) NULL);
- if (name == NULL || *name == '\0')
- goto no_locale;
- /*
- ** If the locale name is the same as our cache, use the cache.
- */
- lbuf = locale_buf;
- if (lbuf != NULL && strcmp(name, lbuf) == 0) {
- p = lbuf;
- for (ap = (const char **) &localebuf;
- ap < (const char **) (&localebuf + 1);
- ++ap)
- *ap = p += strlen(p) + 1;
- return &localebuf;
- }
- /*
- ** Slurp the locale file into the cache.
- */
- namesize = strlen(name) + 1;
- if (sizeof filename <
- ((sizeof locale_home) + namesize + (sizeof lc_time)))
- goto no_locale;
- oldsun = 0;
- len = snprintf(filename, sizeof filename, "%s/%s/%s", locale_home,
-    name, lc_time);
- if (len < 0 || len >= sizeof filename)
- goto no_locale;
- fd = open(filename, O_RDONLY);
- if (fd == -1) {
- /*
- ** Old Sun systems have a different naming and data convention.
- */
- oldsun = 1;
- len = snprintf(filename, sizeof filename, "%s/%s/%s",
- locale_home, lc_time, name);
- if (len < 0 || len >= sizeof filename)
- goto no_locale;
- fd = open(filename, O_RDONLY);
- if (fd  == -1)
- goto no_locale;
- }
- if (fstat(fd, &st) == -1)
- goto bad_locale;
- if (st.st_size <= 0)
- goto bad_locale;
- bufsize = namesize + st.st_size;
- locale_buf = NULL;
- nlbuf = realloc(lbuf, bufsize);
- if (nlbuf == NULL) {
- free(lbuf);
- lbuf = NULL;
- goto bad_locale;
- }
- lbuf = nlbuf;
- (void) strlcpy(lbuf, name, bufsize);
- p = lbuf + namesize;
- plim = p + st.st_size;
- if (read(fd, p, st.st_size) != st.st_size)
- goto bad_lbuf;
- if (close(fd) != 0)
- goto bad_lbuf;
- /*
- ** Parse the locale file into localebuf.
- */
- if (plim[-1] != '\n')
- goto bad_lbuf;
- for (ap = (const char **) &localebuf;
- ap < (const char **) (&localebuf + 1);
- ++ap) {
- if (p == plim)
- goto bad_lbuf;
- *ap = p;
- while (*p != '\n')
- ++p;
- *p++ = '\0';
- }
- if (oldsun) {
- /*
- ** SunOS 4 used an obsolescent format; see localdtconv(3).
- ** c_fmt had the ``short format for dates and times together''
- ** (SunOS 4 date, "%a %b %e %T %Z %Y" in the C locale);
- ** date_fmt had the ``long format for dates''
- ** (SunOS 4 strftime %C, "%A, %B %e, %Y" in the C locale).
- ** Discard the latter in favor of the former.
- */
- localebuf.date_fmt = localebuf.c_fmt;
- }
- /*
- ** Record the successful parse in the cache.
- */
- locale_buf = lbuf;
-
- return &localebuf;
-
-bad_lbuf:
- free(lbuf);
-bad_locale:
- (void) close(fd);
-no_locale:
- localebuf = C_time_locale;
- locale_buf = NULL;
- return &localebuf;
-}
-#endif /* defined LOCALE_HOME */

Reply | Threaded
Open this post in threaded view
|

Re: LOCALE_HOME for strtime(3)

Todd C. Miller-3
Upstream tzcode removed the LOCALE_HOME bits in 2014.  There's no
reason for us to keep it.

 - todd

Reply | Threaded
Open this post in threaded view
|

Re: LOCALE_HOME for strtime(3)

Jan Stary
On Jul 15 15:48:41, [hidden email] wrote:
> Upstream tzcode removed the LOCALE_HOME bits in 2014.  There's no
> reason for us to keep it.

With that removed, the header file can go too.

        Jan


Index: lib/libc/time/strftime.c
===================================================================
RCS file: /cvs/src/lib/libc/time/strftime.c,v
retrieving revision 1.32
diff -u -p -r1.32 strftime.c
--- lib/libc/time/strftime.c 29 Jun 2019 16:12:21 -0000 1.32
+++ lib/libc/time/strftime.c 16 Jul 2020 07:20:23 -0000
@@ -29,7 +29,6 @@
 */
 
 #include <fcntl.h>
-#include <locale.h>
 #include <stdio.h>
 
 #include "private.h"
@@ -48,16 +47,7 @@ struct lc_time_T {
  const char * date_fmt;
 };
 
-#ifdef LOCALE_HOME
-#include "sys/stat.h"
-static struct lc_time_T localebuf;
-static struct lc_time_T * _loc(void);
-#define Locale _loc()
-#endif /* defined LOCALE_HOME */
-#ifndef LOCALE_HOME
 #define Locale (&C_time_locale)
-#endif /* !defined LOCALE_HOME */
-
 static const struct lc_time_T C_time_locale = {
  {
  "Jan", "Feb", "Mar", "Apr", "May", "Jun",
@@ -124,9 +114,6 @@ strftime(char *s, size_t maxsize, const
  int warn;
 
  tzset();
-#ifdef LOCALE_HOME
- localebuf.mon[0] = 0;
-#endif /* defined LOCALE_HOME */
  warn = IN_NONE;
  p = _fmt(((format == NULL) ? "%c" : format), t, s, s + maxsize, &warn);
  if (p == s + maxsize) {
@@ -558,135 +545,3 @@ _yconv(int a, int b, int convert_top, in
  pt = _conv(((trail < 0) ? -trail : trail), "%02d", pt, ptlim);
  return pt;
 }
-
-#ifdef LOCALE_HOME
-static struct lc_time_T *
-_loc(void)
-{
- static const char locale_home[] = LOCALE_HOME;
- static const char lc_time[] = "LC_TIME";
- static char * locale_buf;
-
- int fd;
- int oldsun; /* "...ain't got nothin' to do..." */
- int len;
- char * lbuf;
- char * nlbuf;
- char * name;
- char * p;
- const char ** ap;
- const char * plim;
- char filename[PATH_MAX];
- struct stat st;
- size_t namesize;
- size_t bufsize;
-
- /*
- ** Use localebuf.mon[0] to signal whether locale is already set up.
- */
- if (localebuf.mon[0])
- return &localebuf;
- name = setlocale(LC_TIME, (char *) NULL);
- if (name == NULL || *name == '\0')
- goto no_locale;
- /*
- ** If the locale name is the same as our cache, use the cache.
- */
- lbuf = locale_buf;
- if (lbuf != NULL && strcmp(name, lbuf) == 0) {
- p = lbuf;
- for (ap = (const char **) &localebuf;
- ap < (const char **) (&localebuf + 1);
- ++ap)
- *ap = p += strlen(p) + 1;
- return &localebuf;
- }
- /*
- ** Slurp the locale file into the cache.
- */
- namesize = strlen(name) + 1;
- if (sizeof filename <
- ((sizeof locale_home) + namesize + (sizeof lc_time)))
- goto no_locale;
- oldsun = 0;
- len = snprintf(filename, sizeof filename, "%s/%s/%s", locale_home,
-    name, lc_time);
- if (len < 0 || len >= sizeof filename)
- goto no_locale;
- fd = open(filename, O_RDONLY);
- if (fd == -1) {
- /*
- ** Old Sun systems have a different naming and data convention.
- */
- oldsun = 1;
- len = snprintf(filename, sizeof filename, "%s/%s/%s",
- locale_home, lc_time, name);
- if (len < 0 || len >= sizeof filename)
- goto no_locale;
- fd = open(filename, O_RDONLY);
- if (fd  == -1)
- goto no_locale;
- }
- if (fstat(fd, &st) == -1)
- goto bad_locale;
- if (st.st_size <= 0)
- goto bad_locale;
- bufsize = namesize + st.st_size;
- locale_buf = NULL;
- nlbuf = realloc(lbuf, bufsize);
- if (nlbuf == NULL) {
- free(lbuf);
- lbuf = NULL;
- goto bad_locale;
- }
- lbuf = nlbuf;
- (void) strlcpy(lbuf, name, bufsize);
- p = lbuf + namesize;
- plim = p + st.st_size;
- if (read(fd, p, st.st_size) != st.st_size)
- goto bad_lbuf;
- if (close(fd) != 0)
- goto bad_lbuf;
- /*
- ** Parse the locale file into localebuf.
- */
- if (plim[-1] != '\n')
- goto bad_lbuf;
- for (ap = (const char **) &localebuf;
- ap < (const char **) (&localebuf + 1);
- ++ap) {
- if (p == plim)
- goto bad_lbuf;
- *ap = p;
- while (*p != '\n')
- ++p;
- *p++ = '\0';
- }
- if (oldsun) {
- /*
- ** SunOS 4 used an obsolescent format; see localdtconv(3).
- ** c_fmt had the ``short format for dates and times together''
- ** (SunOS 4 date, "%a %b %e %T %Z %Y" in the C locale);
- ** date_fmt had the ``long format for dates''
- ** (SunOS 4 strftime %C, "%A, %B %e, %Y" in the C locale).
- ** Discard the latter in favor of the former.
- */
- localebuf.date_fmt = localebuf.c_fmt;
- }
- /*
- ** Record the successful parse in the cache.
- */
- locale_buf = lbuf;
-
- return &localebuf;
-
-bad_lbuf:
- free(lbuf);
-bad_locale:
- (void) close(fd);
-no_locale:
- localebuf = C_time_locale;
- locale_buf = NULL;
- return &localebuf;
-}
-#endif /* defined LOCALE_HOME */

Reply | Threaded
Open this post in threaded view
|

Re: LOCALE_HOME for strtime(3)

Jan Stary
ping

On Jul 16 09:23:22, [hidden email] wrote:

> On Jul 15 15:48:41, [hidden email] wrote:
> > Upstream tzcode removed the LOCALE_HOME bits in 2014.  There's no
> > reason for us to keep it.
>
> With that removed, the header file can go too.
>
> Jan
>
>
> Index: lib/libc/time/strftime.c
> ===================================================================
> RCS file: /cvs/src/lib/libc/time/strftime.c,v
> retrieving revision 1.32
> diff -u -p -r1.32 strftime.c
> --- lib/libc/time/strftime.c 29 Jun 2019 16:12:21 -0000 1.32
> +++ lib/libc/time/strftime.c 16 Jul 2020 07:20:23 -0000
> @@ -29,7 +29,6 @@
>  */
>  
>  #include <fcntl.h>
> -#include <locale.h>
>  #include <stdio.h>
>  
>  #include "private.h"
> @@ -48,16 +47,7 @@ struct lc_time_T {
>   const char * date_fmt;
>  };
>  
> -#ifdef LOCALE_HOME
> -#include "sys/stat.h"
> -static struct lc_time_T localebuf;
> -static struct lc_time_T * _loc(void);
> -#define Locale _loc()
> -#endif /* defined LOCALE_HOME */
> -#ifndef LOCALE_HOME
>  #define Locale (&C_time_locale)
> -#endif /* !defined LOCALE_HOME */
> -
>  static const struct lc_time_T C_time_locale = {
>   {
>   "Jan", "Feb", "Mar", "Apr", "May", "Jun",
> @@ -124,9 +114,6 @@ strftime(char *s, size_t maxsize, const
>   int warn;
>  
>   tzset();
> -#ifdef LOCALE_HOME
> - localebuf.mon[0] = 0;
> -#endif /* defined LOCALE_HOME */
>   warn = IN_NONE;
>   p = _fmt(((format == NULL) ? "%c" : format), t, s, s + maxsize, &warn);
>   if (p == s + maxsize) {
> @@ -558,135 +545,3 @@ _yconv(int a, int b, int convert_top, in
>   pt = _conv(((trail < 0) ? -trail : trail), "%02d", pt, ptlim);
>   return pt;
>  }
> -
> -#ifdef LOCALE_HOME
> -static struct lc_time_T *
> -_loc(void)
> -{
> - static const char locale_home[] = LOCALE_HOME;
> - static const char lc_time[] = "LC_TIME";
> - static char * locale_buf;
> -
> - int fd;
> - int oldsun; /* "...ain't got nothin' to do..." */
> - int len;
> - char * lbuf;
> - char * nlbuf;
> - char * name;
> - char * p;
> - const char ** ap;
> - const char * plim;
> - char filename[PATH_MAX];
> - struct stat st;
> - size_t namesize;
> - size_t bufsize;
> -
> - /*
> - ** Use localebuf.mon[0] to signal whether locale is already set up.
> - */
> - if (localebuf.mon[0])
> - return &localebuf;
> - name = setlocale(LC_TIME, (char *) NULL);
> - if (name == NULL || *name == '\0')
> - goto no_locale;
> - /*
> - ** If the locale name is the same as our cache, use the cache.
> - */
> - lbuf = locale_buf;
> - if (lbuf != NULL && strcmp(name, lbuf) == 0) {
> - p = lbuf;
> - for (ap = (const char **) &localebuf;
> - ap < (const char **) (&localebuf + 1);
> - ++ap)
> - *ap = p += strlen(p) + 1;
> - return &localebuf;
> - }
> - /*
> - ** Slurp the locale file into the cache.
> - */
> - namesize = strlen(name) + 1;
> - if (sizeof filename <
> - ((sizeof locale_home) + namesize + (sizeof lc_time)))
> - goto no_locale;
> - oldsun = 0;
> - len = snprintf(filename, sizeof filename, "%s/%s/%s", locale_home,
> -    name, lc_time);
> - if (len < 0 || len >= sizeof filename)
> - goto no_locale;
> - fd = open(filename, O_RDONLY);
> - if (fd == -1) {
> - /*
> - ** Old Sun systems have a different naming and data convention.
> - */
> - oldsun = 1;
> - len = snprintf(filename, sizeof filename, "%s/%s/%s",
> - locale_home, lc_time, name);
> - if (len < 0 || len >= sizeof filename)
> - goto no_locale;
> - fd = open(filename, O_RDONLY);
> - if (fd  == -1)
> - goto no_locale;
> - }
> - if (fstat(fd, &st) == -1)
> - goto bad_locale;
> - if (st.st_size <= 0)
> - goto bad_locale;
> - bufsize = namesize + st.st_size;
> - locale_buf = NULL;
> - nlbuf = realloc(lbuf, bufsize);
> - if (nlbuf == NULL) {
> - free(lbuf);
> - lbuf = NULL;
> - goto bad_locale;
> - }
> - lbuf = nlbuf;
> - (void) strlcpy(lbuf, name, bufsize);
> - p = lbuf + namesize;
> - plim = p + st.st_size;
> - if (read(fd, p, st.st_size) != st.st_size)
> - goto bad_lbuf;
> - if (close(fd) != 0)
> - goto bad_lbuf;
> - /*
> - ** Parse the locale file into localebuf.
> - */
> - if (plim[-1] != '\n')
> - goto bad_lbuf;
> - for (ap = (const char **) &localebuf;
> - ap < (const char **) (&localebuf + 1);
> - ++ap) {
> - if (p == plim)
> - goto bad_lbuf;
> - *ap = p;
> - while (*p != '\n')
> - ++p;
> - *p++ = '\0';
> - }
> - if (oldsun) {
> - /*
> - ** SunOS 4 used an obsolescent format; see localdtconv(3).
> - ** c_fmt had the ``short format for dates and times together''
> - ** (SunOS 4 date, "%a %b %e %T %Z %Y" in the C locale);
> - ** date_fmt had the ``long format for dates''
> - ** (SunOS 4 strftime %C, "%A, %B %e, %Y" in the C locale).
> - ** Discard the latter in favor of the former.
> - */
> - localebuf.date_fmt = localebuf.c_fmt;
> - }
> - /*
> - ** Record the successful parse in the cache.
> - */
> - locale_buf = lbuf;
> -
> - return &localebuf;
> -
> -bad_lbuf:
> - free(lbuf);
> -bad_locale:
> - (void) close(fd);
> -no_locale:
> - localebuf = C_time_locale;
> - locale_buf = NULL;
> - return &localebuf;
> -}
> -#endif /* defined LOCALE_HOME */
>
>

Reply | Threaded
Open this post in threaded view
|

Re: LOCALE_HOME for strtime(3)

Todd C. Miller-3
On Sat, 01 Aug 2020 17:29:11 +0200, Jan Stary wrote:

> ping

This was already committed.

revision 1.33
date: 2020/07/16 20:08:12;  author: millert;  state: Exp;  lines: +1 -146;  commitid: LVVrFB1zB8C0gLBS;
Remove obsolete LOCALE_HOME code we have never used (and never will).
Upstream removed it in 2004.  From Jan Stary.