Re: Relocatable locale - Mailing list pgsql-patches

From Bruce Momjian
Subject Re: Relocatable locale
Date
Msg-id 200406030006.i5306oI25269@candle.pha.pa.us
Whole thread Raw
In response to Re: Relocatable locale  (Bruce Momjian <pgman@candle.pha.pa.us>)
Responses Re: Relocatable locale  (Peter Eisentraut <peter_e@gmx.net>)
List pgsql-patches
With no one coming up with a better idea, this applied patch adds PGETC
(for pg_service.conf) and PGLOCALE (for locale dir) environment variable
processing to libpq.

The patch also adds code to our client apps so we set the environment
variable directly based on our binary location, unless it is already
set. This will allow our applications to emit proper locale messages
that are generated in libpq.

---------------------------------------------------------------------------

Bruce Momjian wrote:
> Andrew Dunstan wrote:
> >
> >
> > Bruce Momjian wrote:
> >
> > >Peter Eisentraut wrote:
> > >
> > >
> > >>Andrew Dunstan wrote:
> > >>
> > >>
> > >>>I'm confused. Can you explain the problem more clearly, please? Do we
> > >>>need to distinguish known apps with a known (relative) message
> > >>>location, from unknown libpq clients?
> > >>>
> > >>>
> > >>The problem boils down to the fact that libpq needs to find its data
> > >>files (in this case locale data, but it could be anything), but it
> > >>doesn't know its own location, so it can't use a relative path
> > >>reference as has been proposed.
> > >>
> > >>
> > >
> > >I am wondering if we should use environment variables, and have our apps
> > >use putenv() to set it to the proper relative path.
> > >
> > >
> >
> > It seems a bit roundabout, but might make sense. Maybe they shouldn't
> > override any value already present in the environment, just set it if
> > there is nothing there? Then the library could use the environment if
> > set, or fall back on a hardcoded path.
>
> Yes, that is what I was thinking.  Call it PGLOCALEDIR.
>
> --
>   Bruce Momjian                        |  http://candle.pha.pa.us
>   pgman@candle.pha.pa.us               |  (610) 359-1001
>   +  If your life is a hard drive,     |  13 Roberts Road
>   +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073
>
> ---------------------------(end of broadcast)---------------------------
> TIP 8: explain analyze is your friend
>

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073
Index: doc/src/sgml/libpq.sgml
===================================================================
RCS file: /cvsroot/pgsql-server/doc/src/sgml/libpq.sgml,v
retrieving revision 1.155
diff -c -c -r1.155 libpq.sgml
*** doc/src/sgml/libpq.sgml    14 May 2004 18:04:02 -0000    1.155
--- doc/src/sgml/libpq.sgml    2 Jun 2004 23:59:33 -0000
***************
*** 3582,3587 ****
--- 3582,3605 ----
  (Equivalent to <literal>SET geqo TO ...</literal>.)
  </para>
  </listitem>
+ <listitem>
+ <para>
+ <indexterm>
+  <primary><envar>PGETC</envar></primary>
+ </indexterm>
+ <envar>PGETC</envar>
+ sets the directory containing the <filename>pg_service.conf</> file.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <indexterm>
+  <primary><envar>PGLOCALE</envar></primary>
+ </indexterm>
+ <envar>PGLOCALE</envar>
+ sets the directory containing the <literal>locale</> files.
+ </para>
+ </listitem>
  </itemizedlist>

  Refer to the <acronym>SQL</acronym> command <command>SET</command>
Index: src/backend/main/main.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/backend/main/main.c,v
retrieving revision 1.85
diff -c -c -r1.85 main.c
*** src/backend/main/main.c    29 May 2004 22:48:19 -0000    1.85
--- src/backend/main/main.c    2 Jun 2004 23:59:41 -0000
***************
*** 152,158 ****
       * allow startup error messages to be localized.
       */

!     set_pglocale(argv[0], "postgres");

  #ifdef WIN32

--- 152,158 ----
       * allow startup error messages to be localized.
       */

!     set_pglocale_pgservice(argv[0], "postgres");

  #ifdef WIN32

Index: src/bin/initdb/initdb.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/bin/initdb/initdb.c,v
retrieving revision 1.34
diff -c -c -r1.34 initdb.c
*** src/bin/initdb/initdb.c    1 Jun 2004 02:53:59 -0000    1.34
--- src/bin/initdb/initdb.c    2 Jun 2004 23:59:53 -0000
***************
*** 1788,1794 ****
      {"global", "pg_xlog", "pg_clog", "base", "base/1"};

      progname = get_progname(argv[0]);
!     set_pglocale(argv[0], "initdb");

      if (argc > 1)
      {
--- 1788,1794 ----
      {"global", "pg_xlog", "pg_clog", "base", "base/1"};

      progname = get_progname(argv[0]);
!     set_pglocale_pgservice(argv[0], "initdb");

      if (argc > 1)
      {
Index: src/bin/pg_controldata/pg_controldata.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/bin/pg_controldata/pg_controldata.c,v
retrieving revision 1.16
diff -c -c -r1.16 pg_controldata.c
*** src/bin/pg_controldata/pg_controldata.c    25 May 2004 01:00:23 -0000    1.16
--- src/bin/pg_controldata/pg_controldata.c    2 Jun 2004 23:59:53 -0000
***************
*** 77,83 ****
      char       *strftime_fmt = "%c";
      const char *progname;

!     set_pglocale(argv[0], "pg_controldata");

      progname = get_progname(argv[0]);

--- 77,83 ----
      char       *strftime_fmt = "%c";
      const char *progname;

!     set_pglocale_pgservice(argv[0], "pg_controldata");

      progname = get_progname(argv[0]);

Index: src/bin/pg_ctl/pg_ctl.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/bin/pg_ctl/pg_ctl.c,v
retrieving revision 1.5
diff -c -c -r1.5 pg_ctl.c
*** src/bin/pg_ctl/pg_ctl.c    1 Jun 2004 22:03:18 -0000    1.5
--- src/bin/pg_ctl/pg_ctl.c    2 Jun 2004 23:59:54 -0000
***************
*** 824,830 ****
  #endif

      progname = get_progname(argv[0]);
!     set_pglocale(argv[0], "pg_ctl");

      /*
       * save argv[0] so do_start() can look for the postmaster if
--- 824,830 ----
  #endif

      progname = get_progname(argv[0]);
!     set_pglocale_pgservice(argv[0], "pg_ctl");

      /*
       * save argv[0] so do_start() can look for the postmaster if
Index: src/bin/pg_dump/pg_dump.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/bin/pg_dump/pg_dump.c,v
retrieving revision 1.372
diff -c -c -r1.372 pg_dump.c
*** src/bin/pg_dump/pg_dump.c    26 May 2004 18:24:22 -0000    1.372
--- src/bin/pg_dump/pg_dump.c    3 Jun 2004 00:00:00 -0000
***************
*** 242,248 ****
      };
      int            optindex;

!     set_pglocale(argv[0], "pg_dump");

      g_verbose = false;

--- 242,248 ----
      };
      int            optindex;

!     set_pglocale_pgservice(argv[0], "pg_dump");

      g_verbose = false;

Index: src/bin/pg_dump/pg_dumpall.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/bin/pg_dump/pg_dumpall.c,v
retrieving revision 1.35
diff -c -c -r1.35 pg_dumpall.c
*** src/bin/pg_dump/pg_dumpall.c    25 May 2004 01:00:24 -0000    1.35
--- src/bin/pg_dump/pg_dumpall.c    3 Jun 2004 00:00:00 -0000
***************
*** 101,107 ****

      int            optindex;

!     set_pglocale(argv[0], "pg_dump");

      progname = get_progname(argv[0]);

--- 101,107 ----

      int            optindex;

!     set_pglocale_pgservice(argv[0], "pg_dump");

      progname = get_progname(argv[0]);

Index: src/bin/pg_dump/pg_restore.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/bin/pg_dump/pg_restore.c,v
retrieving revision 1.57
diff -c -c -r1.57 pg_restore.c
*** src/bin/pg_dump/pg_restore.c    25 May 2004 01:00:24 -0000    1.57
--- src/bin/pg_dump/pg_restore.c    3 Jun 2004 00:00:01 -0000
***************
*** 121,127 ****
          {NULL, 0, NULL, 0}
      };

!     set_pglocale(argv[0], "pg_dump");

      opts = NewRestoreOptions();

--- 121,127 ----
          {NULL, 0, NULL, 0}
      };

!     set_pglocale_pgservice(argv[0], "pg_dump");

      opts = NewRestoreOptions();

Index: src/bin/pg_resetxlog/pg_resetxlog.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/bin/pg_resetxlog/pg_resetxlog.c,v
retrieving revision 1.19
diff -c -c -r1.19 pg_resetxlog.c
*** src/bin/pg_resetxlog/pg_resetxlog.c    25 May 2004 01:00:25 -0000    1.19
--- src/bin/pg_resetxlog/pg_resetxlog.c    3 Jun 2004 00:00:02 -0000
***************
*** 102,108 ****
      int            fd;
      char        path[MAXPGPATH];

!     set_pglocale(argv[0], "pg_resetxlog");

      progname = get_progname(argv[0]);

--- 102,108 ----
      int            fd;
      char        path[MAXPGPATH];

!     set_pglocale_pgservice(argv[0], "pg_resetxlog");

      progname = get_progname(argv[0]);

Index: src/bin/psql/startup.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/bin/psql/startup.c,v
retrieving revision 1.94
diff -c -c -r1.94 startup.c
*** src/bin/psql/startup.c    25 May 2004 01:00:26 -0000    1.94
--- src/bin/psql/startup.c    3 Jun 2004 00:00:02 -0000
***************
*** 102,108 ****
      char       *password = NULL;
      bool        need_pass;

!     set_pglocale(argv[0], "psql");

      pset.progname = get_progname(argv[0]);

--- 102,108 ----
      char       *password = NULL;
      bool        need_pass;

!     set_pglocale_pgservice(argv[0], "psql");

      pset.progname = get_progname(argv[0]);

Index: src/bin/scripts/clusterdb.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/bin/scripts/clusterdb.c,v
retrieving revision 1.8
diff -c -c -r1.8 clusterdb.c
*** src/bin/scripts/clusterdb.c    1 Jun 2004 02:54:09 -0000    1.8
--- src/bin/scripts/clusterdb.c    3 Jun 2004 00:00:02 -0000
***************
*** 58,64 ****
      char       *table = NULL;

      progname = get_progname(argv[0]);
!     set_pglocale(argv[0], "pgscripts");

      handle_help_version_opts(argc, argv, "clusterdb", help);

--- 58,64 ----
      char       *table = NULL;

      progname = get_progname(argv[0]);
!     set_pglocale_pgservice(argv[0], "pgscripts");

      handle_help_version_opts(argc, argv, "clusterdb", help);

Index: src/bin/scripts/createdb.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/bin/scripts/createdb.c,v
retrieving revision 1.10
diff -c -c -r1.10 createdb.c
*** src/bin/scripts/createdb.c    1 Jun 2004 02:54:09 -0000    1.10
--- src/bin/scripts/createdb.c    3 Jun 2004 00:00:03 -0000
***************
*** 60,66 ****
      PGresult   *result;

      progname = get_progname(argv[0]);
!     set_pglocale(argv[0], "pgscripts");

      handle_help_version_opts(argc, argv, "createdb", help);

--- 60,66 ----
      PGresult   *result;

      progname = get_progname(argv[0]);
!     set_pglocale_pgservice(argv[0], "pgscripts");

      handle_help_version_opts(argc, argv, "createdb", help);

Index: src/bin/scripts/createlang.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/bin/scripts/createlang.c,v
retrieving revision 1.11
diff -c -c -r1.11 createlang.c
*** src/bin/scripts/createlang.c    1 Jun 2004 02:54:09 -0000    1.11
--- src/bin/scripts/createlang.c    3 Jun 2004 00:00:05 -0000
***************
*** 61,67 ****
      PGresult   *result;

      progname = get_progname(argv[0]);
!     set_pglocale(argv[0], "pgscripts");

      handle_help_version_opts(argc, argv, "createlang", help);

--- 61,67 ----
      PGresult   *result;

      progname = get_progname(argv[0]);
!     set_pglocale_pgservice(argv[0], "pgscripts");

      handle_help_version_opts(argc, argv, "createlang", help);

Index: src/bin/scripts/createuser.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/bin/scripts/createuser.c,v
retrieving revision 1.12
diff -c -c -r1.12 createuser.c
*** src/bin/scripts/createuser.c    1 Jun 2004 02:54:09 -0000    1.12
--- src/bin/scripts/createuser.c    3 Jun 2004 00:00:05 -0000
***************
*** 63,69 ****
      PGresult   *result;

      progname = get_progname(argv[0]);
!     set_pglocale(argv[0], "pgscripts");

      handle_help_version_opts(argc, argv, "createuser", help);

--- 63,69 ----
      PGresult   *result;

      progname = get_progname(argv[0]);
!     set_pglocale_pgservice(argv[0], "pgscripts");

      handle_help_version_opts(argc, argv, "createuser", help);

Index: src/bin/scripts/dropdb.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/bin/scripts/dropdb.c,v
retrieving revision 1.11
diff -c -c -r1.11 dropdb.c
*** src/bin/scripts/dropdb.c    1 Jun 2004 02:54:09 -0000    1.11
--- src/bin/scripts/dropdb.c    3 Jun 2004 00:00:05 -0000
***************
*** 51,57 ****
      PGresult   *result;

      progname = get_progname(argv[0]);
!     set_pglocale(argv[0], "pgscripts");

      handle_help_version_opts(argc, argv, "dropdb", help);

--- 51,57 ----
      PGresult   *result;

      progname = get_progname(argv[0]);
!     set_pglocale_pgservice(argv[0], "pgscripts");

      handle_help_version_opts(argc, argv, "dropdb", help);

Index: src/bin/scripts/droplang.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/bin/scripts/droplang.c,v
retrieving revision 1.10
diff -c -c -r1.10 droplang.c
*** src/bin/scripts/droplang.c    1 Jun 2004 02:54:09 -0000    1.10
--- src/bin/scripts/droplang.c    3 Jun 2004 00:00:05 -0000
***************
*** 61,67 ****
      PGresult   *result;

      progname = get_progname(argv[0]);
!     set_pglocale(argv[0], "pgscripts");

      handle_help_version_opts(argc, argv, "droplang", help);

--- 61,67 ----
      PGresult   *result;

      progname = get_progname(argv[0]);
!     set_pglocale_pgservice(argv[0], "pgscripts");

      handle_help_version_opts(argc, argv, "droplang", help);

Index: src/bin/scripts/dropuser.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/bin/scripts/dropuser.c,v
retrieving revision 1.10
diff -c -c -r1.10 dropuser.c
*** src/bin/scripts/dropuser.c    1 Jun 2004 02:54:09 -0000    1.10
--- src/bin/scripts/dropuser.c    3 Jun 2004 00:00:05 -0000
***************
*** 51,57 ****
      PGresult   *result;

      progname = get_progname(argv[0]);
!     set_pglocale(argv[0], "pgscripts");

      handle_help_version_opts(argc, argv, "dropuser", help);

--- 51,57 ----
      PGresult   *result;

      progname = get_progname(argv[0]);
!     set_pglocale_pgservice(argv[0], "pgscripts");

      handle_help_version_opts(argc, argv, "dropuser", help);

Index: src/bin/scripts/vacuumdb.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/bin/scripts/vacuumdb.c,v
retrieving revision 1.8
diff -c -c -r1.8 vacuumdb.c
*** src/bin/scripts/vacuumdb.c    1 Jun 2004 02:54:09 -0000    1.8
--- src/bin/scripts/vacuumdb.c    3 Jun 2004 00:00:05 -0000
***************
*** 66,72 ****
      bool        verbose = false;

      progname = get_progname(argv[0]);
!     set_pglocale(argv[0], "pgscripts");

      handle_help_version_opts(argc, argv, "vacuumdb", help);

--- 66,72 ----
      bool        verbose = false;

      progname = get_progname(argv[0]);
!     set_pglocale_pgservice(argv[0], "pgscripts");

      handle_help_version_opts(argc, argv, "vacuumdb", help);

Index: src/include/port.h
===================================================================
RCS file: /cvsroot/pgsql-server/src/include/port.h,v
retrieving revision 1.39
diff -c -c -r1.39 port.h
*** src/include/port.h    27 May 2004 14:39:32 -0000    1.39
--- src/include/port.h    3 Jun 2004 00:00:06 -0000
***************
*** 32,38 ****
  extern void get_pkginclude_path(const char *my_exec_path, char *ret_path);
  extern void get_pkglib_path(const char *my_exec_path, char *ret_path);
  extern void get_locale_path(const char *my_exec_path, char *ret_path);
! extern void set_pglocale(const char *argv0, const char *app);

  /*
   *    is_absolute_path
--- 32,38 ----
  extern void get_pkginclude_path(const char *my_exec_path, char *ret_path);
  extern void get_pkglib_path(const char *my_exec_path, char *ret_path);
  extern void get_locale_path(const char *my_exec_path, char *ret_path);
! extern void set_pglocale_pgservice(const char *argv0, const char *app);

  /*
   *    is_absolute_path
Index: src/interfaces/libpq/fe-connect.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/interfaces/libpq/fe-connect.c,v
retrieving revision 1.271
diff -c -c -r1.271 fe-connect.c
*** src/interfaces/libpq/fe-connect.c    26 May 2004 18:35:51 -0000    1.271
--- src/interfaces/libpq/fe-connect.c    3 Jun 2004 00:00:13 -0000
***************
*** 2363,2379 ****



- #ifndef SYSCONFDIR
- #error "You must compile this file with SYSCONFDIR defined."
- #endif
-
  #define MAXBUFSIZE 256

  static int
  parseServiceInfo(PQconninfoOption *options, PQExpBuffer errorMessage)
  {
      char       *service = conninfo_getval(options, "service");
!     char       *serviceFile = SYSCONFDIR "/pg_service.conf";
      bool        group_found = false;
      int            linenr = 0,
                  i;
--- 2363,2375 ----



  #define MAXBUFSIZE 256

  static int
  parseServiceInfo(PQconninfoOption *options, PQExpBuffer errorMessage)
  {
      char       *service = conninfo_getval(options, "service");
!     char        serviceFile[MAXPGPATH];
      bool        group_found = false;
      int            linenr = 0,
                  i;
***************
*** 2385,2390 ****
--- 2381,2393 ----
       */
      if (service == NULL)
          service = getenv("PGSERVICE");
+
+     /*
+      *    This could be used by any application so we can't use the binary
+      *    location to find our config files.
+      */
+     snprintf(serviceFile, MAXPGPATH, "%s/pg_service.conf",
+              getenv("PGETC") ? getenv("PGETC") : SYSCONFDIR);

      if (service != NULL)
      {
Index: src/interfaces/libpq/fe-misc.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/interfaces/libpq/fe-misc.c,v
retrieving revision 1.106
diff -c -c -r1.106 fe-misc.c
*** src/interfaces/libpq/fe-misc.c    25 May 2004 01:00:29 -0000    1.106
--- src/interfaces/libpq/fe-misc.c    3 Jun 2004 00:00:13 -0000
***************
*** 1132,1138 ****
      {
          already_bound = 1;
          /* No relocatable lookup here because the binary could be anywhere */
!         bindtextdomain("libpq", LOCALEDIR);
      }

      return dgettext("libpq", msgid);
--- 1132,1138 ----
      {
          already_bound = 1;
          /* No relocatable lookup here because the binary could be anywhere */
!         bindtextdomain("libpq", getenv("PGLOCALE") ? getenv("PGLOCALE") : LOCALEDIR);
      }

      return dgettext("libpq", msgid);
Index: src/port/path.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/port/path.c,v
retrieving revision 1.16
diff -c -c -r1.16 path.c
*** src/port/path.c    26 May 2004 19:00:31 -0000    1.16
--- src/port/path.c    3 Jun 2004 00:00:13 -0000
***************
*** 222,253 ****


  /*
!  *    set_pglocale
   *
!  *    Set application-specific locale
   *
   *    This function takes an argv[0] rather than a full path.
   */
  void
! set_pglocale(const char *argv0, const char *app)
  {
- #ifdef ENABLE_NLS
      char path[MAXPGPATH];
      char my_exec_path[MAXPGPATH];
! #endif

      /* don't set LC_ALL in the backend */
      if (strcmp(app, "postgres") != 0)
          setlocale(LC_ALL, "");

- #ifdef ENABLE_NLS
      if (find_my_exec(argv0, my_exec_path) < 0)
          return;

      get_locale_path(my_exec_path, path);
      bindtextdomain(app, path);
      textdomain(app);
  #endif
  }


--- 222,268 ----


  /*
!  *    set_pglocale_pgservice
   *
!  *    Set application-specific locale and service directory
   *
   *    This function takes an argv[0] rather than a full path.
   */
  void
! set_pglocale_pgservice(const char *argv0, const char *app)
  {
      char path[MAXPGPATH];
      char my_exec_path[MAXPGPATH];
!     char env_path[MAXPGPATH + strlen("PGLOCALE=")]; /* longer than PGETC */

      /* don't set LC_ALL in the backend */
      if (strcmp(app, "postgres") != 0)
          setlocale(LC_ALL, "");

      if (find_my_exec(argv0, my_exec_path) < 0)
          return;

+ #ifdef ENABLE_NLS
      get_locale_path(my_exec_path, path);
      bindtextdomain(app, path);
      textdomain(app);
+
+     if (!getenv("PGLOCALE"))
+     {
+         /* set for libpq to use */
+         sprintf(env_path, "PGLOCALE=%s", path);
+         putenv(env_path);
+     }
  #endif
+
+     if (!getenv("PGETC"))
+     {
+         get_etc_path(my_exec_path, path);
+
+         /* set for libpq to use */
+         sprintf(env_path, "PGETC=%s", path);
+         putenv(env_path);
+     }
  }



pgsql-patches by date:

Previous
From: "Laurent Ballester"
Date:
Subject: Re: eventlog fix
Next
From: Bruce Momjian
Date:
Subject: Re: Compiling libpq with VisualC