summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.global.in4
-rw-r--r--src/backend/commands/dbcommands.c30
-rw-r--r--src/bin/initdb/initdb.c268
-rw-r--r--src/include/port.h5
-rw-r--r--src/port/Makefile33
-rw-r--r--src/port/chklocale.c246
6 files changed, 347 insertions, 239 deletions
diff --git a/src/Makefile.global.in b/src/Makefile.global.in
index 3f81b9e786..cbe2634091 100644
--- a/src/Makefile.global.in
+++ b/src/Makefile.global.in
@@ -1,5 +1,5 @@
# -*-makefile-*-
-# $PostgreSQL: pgsql/src/Makefile.global.in,v 1.238 2007/08/20 08:53:12 petere Exp $
+# $PostgreSQL: pgsql/src/Makefile.global.in,v 1.239 2007/09/28 22:25:49 tgl Exp $
#------------------------------------------------------------------------------
# All PostgreSQL makefiles include this file and use the variables it sets,
@@ -423,7 +423,7 @@ endif
#
# substitute implementations of C library routines (see src/port/)
-LIBOBJS = @LIBOBJS@ copydir.o dirmod.o exec.o noblock.o path.o pipe.o pgsleep.o pgstrcasecmp.o qsort.o qsort_arg.o sprompt.o thread.o
+LIBOBJS = @LIBOBJS@
LIBS := -lpgport $(LIBS)
# add location of libpgport.a to LDFLAGS
diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c
index f627480362..094f51b5cc 100644
--- a/src/backend/commands/dbcommands.c
+++ b/src/backend/commands/dbcommands.c
@@ -13,13 +13,14 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/dbcommands.c,v 1.198 2007/09/03 18:46:29 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/dbcommands.c,v 1.199 2007/09/28 22:25:49 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#include <fcntl.h>
+#include <locale.h>
#include <unistd.h>
#include <sys/stat.h>
@@ -96,6 +97,7 @@ createdb(const CreatedbStmt *stmt)
const char *dbtemplate = NULL;
int encoding = -1;
int dbconnlimit = -1;
+ int ctype_encoding;
/* Extract options from the statement node tree */
foreach(option, stmt->options)
@@ -254,6 +256,32 @@ createdb(const CreatedbStmt *stmt)
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("invalid server encoding %d", encoding)));
+ /*
+ * Check whether encoding matches server locale settings. We allow
+ * mismatch in two cases:
+ *
+ * 1. ctype_encoding = SQL_ASCII, which means either that the locale
+ * is C/POSIX which works with any encoding, or that we couldn't determine
+ * the locale's encoding and have to trust the user to get it right.
+ *
+ * 2. selected encoding is SQL_ASCII, but only if you're a superuser.
+ * This is risky but we have historically allowed it --- notably, the
+ * regression tests require it.
+ *
+ * Note: if you change this policy, fix initdb to match.
+ */
+ ctype_encoding = pg_get_encoding_from_locale(NULL);
+
+ if (!(ctype_encoding == encoding ||
+ ctype_encoding == PG_SQL_ASCII ||
+ (encoding == PG_SQL_ASCII && superuser())))
+ ereport(ERROR,
+ (errmsg("encoding %s does not match server's locale %s",
+ pg_encoding_to_char(encoding),
+ setlocale(LC_CTYPE, NULL)),
+ errdetail("The server's LC_CTYPE setting requires encoding %s.",
+ pg_encoding_to_char(ctype_encoding))));
+
/* Resolve default tablespace for new database */
if (dtablespacename && dtablespacename->arg)
{
diff --git a/src/bin/initdb/initdb.c b/src/bin/initdb/initdb.c
index 52f50f195b..1216bbd67c 100644
--- a/src/bin/initdb/initdb.c
+++ b/src/bin/initdb/initdb.c
@@ -42,7 +42,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
* Portions taken from FreeBSD.
*
- * $PostgreSQL: pgsql/src/bin/initdb/initdb.c,v 1.142 2007/09/28 15:25:44 tgl Exp $
+ * $PostgreSQL: pgsql/src/bin/initdb/initdb.c,v 1.143 2007/09/28 22:25:49 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -54,9 +54,6 @@
#include <unistd.h>
#include <locale.h>
#include <signal.h>
-#ifdef HAVE_LANGINFO_H
-#include <langinfo.h>
-#endif
#include <time.h>
#include "libpq/pqsignal.h"
@@ -720,197 +717,6 @@ get_encoding_id(char *encoding_name)
exit(1);
}
-#if defined(HAVE_LANGINFO_H) && defined(CODESET)
-/*
- * Checks whether the encoding selected for PostgreSQL and the
- * encoding used by the system locale match.
- */
-
-struct encoding_match
-{
- enum pg_enc pg_enc_code;
- const char *system_enc_name;
-};
-
-static const struct encoding_match encoding_match_list[] = {
- {PG_EUC_JP, "EUC-JP"},
- {PG_EUC_JP, "eucJP"},
- {PG_EUC_JP, "IBM-eucJP"},
- {PG_EUC_JP, "sdeckanji"},
-
- {PG_EUC_CN, "EUC-CN"},
- {PG_EUC_CN, "eucCN"},
- {PG_EUC_CN, "IBM-eucCN"},
- {PG_EUC_CN, "GB2312"},
- {PG_EUC_CN, "dechanzi"},
-
- {PG_EUC_KR, "EUC-KR"},
- {PG_EUC_KR, "eucKR"},
- {PG_EUC_KR, "IBM-eucKR"},
- {PG_EUC_KR, "deckorean"},
- {PG_EUC_KR, "5601"},
-
- {PG_EUC_TW, "EUC-TW"},
- {PG_EUC_TW, "eucTW"},
- {PG_EUC_TW, "IBM-eucTW"},
- {PG_EUC_TW, "cns11643"},
-
-#ifdef NOT_VERIFIED
- {PG_JOHAB, "???"},
-#endif
-
- {PG_UTF8, "UTF-8"},
- {PG_UTF8, "utf8"},
-
- {PG_LATIN1, "ISO-8859-1"},
- {PG_LATIN1, "ISO8859-1"},
- {PG_LATIN1, "iso88591"},
-
- {PG_LATIN2, "ISO-8859-2"},
- {PG_LATIN2, "ISO8859-2"},
- {PG_LATIN2, "iso88592"},
-
- {PG_LATIN3, "ISO-8859-3"},
- {PG_LATIN3, "ISO8859-3"},
- {PG_LATIN3, "iso88593"},
-
- {PG_LATIN4, "ISO-8859-4"},
- {PG_LATIN4, "ISO8859-4"},
- {PG_LATIN4, "iso88594"},
-
- {PG_LATIN5, "ISO-8859-9"},
- {PG_LATIN5, "ISO8859-9"},
- {PG_LATIN5, "iso88599"},
-
- {PG_LATIN6, "ISO-8859-10"},
- {PG_LATIN6, "ISO8859-10"},
- {PG_LATIN6, "iso885910"},
-
- {PG_LATIN7, "ISO-8859-13"},
- {PG_LATIN7, "ISO8859-13"},
- {PG_LATIN7, "iso885913"},
-
- {PG_LATIN8, "ISO-8859-14"},
- {PG_LATIN8, "ISO8859-14"},
- {PG_LATIN8, "iso885914"},
-
- {PG_LATIN9, "ISO-8859-15"},
- {PG_LATIN9, "ISO8859-15"},
- {PG_LATIN9, "iso885915"},
-
- {PG_LATIN10, "ISO-8859-16"},
- {PG_LATIN10, "ISO8859-16"},
- {PG_LATIN10, "iso885916"},
-
- {PG_WIN1252, "CP1252"},
- {PG_WIN1253, "CP1253"},
- {PG_WIN1254, "CP1254"},
- {PG_WIN1255, "CP1255"},
- {PG_WIN1256, "CP1256"},
- {PG_WIN1257, "CP1257"},
- {PG_WIN1258, "CP1258"},
-#ifdef NOT_VERIFIED
- {PG_WIN874, "???"},
-#endif
- {PG_KOI8R, "KOI8-R"},
- {PG_WIN1251, "CP1251"},
- {PG_WIN866, "CP866"},
-
- {PG_ISO_8859_5, "ISO-8859-5"},
- {PG_ISO_8859_5, "ISO8859-5"},
- {PG_ISO_8859_5, "iso88595"},
-
- {PG_ISO_8859_6, "ISO-8859-6"},
- {PG_ISO_8859_6, "ISO8859-6"},
- {PG_ISO_8859_6, "iso88596"},
-
- {PG_ISO_8859_7, "ISO-8859-7"},
- {PG_ISO_8859_7, "ISO8859-7"},
- {PG_ISO_8859_7, "iso88597"},
-
- {PG_ISO_8859_8, "ISO-8859-8"},
- {PG_ISO_8859_8, "ISO8859-8"},
- {PG_ISO_8859_8, "iso88598"},
-
- {PG_SQL_ASCII, NULL} /* end marker */
-};
-
-static char *
-get_encoding_from_locale(const char *ctype)
-{
- char *save;
- char *sys;
-
- save = setlocale(LC_CTYPE, NULL);
- if (!save)
- return NULL;
- save = xstrdup(save);
-
- setlocale(LC_CTYPE, ctype);
- sys = nl_langinfo(CODESET);
- sys = xstrdup(sys);
-
- setlocale(LC_CTYPE, save);
- free(save);
-
- return sys;
-}
-
-static void
-check_encodings_match(int pg_enc, const char *ctype)
-{
- char *sys;
- int i;
-
- sys = get_encoding_from_locale(ctype);
-
- for (i = 0; encoding_match_list[i].system_enc_name; i++)
- {
- if (pg_enc == encoding_match_list[i].pg_enc_code
- && pg_strcasecmp(sys, encoding_match_list[i].system_enc_name) == 0)
- {
- free(sys);
- return;
- }
- }
-
- fprintf(stderr,
- _("%s: warning: encoding mismatch\n"), progname);
- fprintf(stderr,
- _("The encoding you selected (%s) and the encoding that the selected\n"
- "locale uses (%s) are not known to match. This might lead to\n"
- "misbehavior in various character string processing functions. To fix\n"
- "this situation, rerun %s and either do not specify an encoding\n"
- "explicitly, or choose a matching combination.\n"),
- pg_encoding_to_char(pg_enc), sys, progname);
-
- free(sys);
- return;
-}
-
-static int
-find_matching_encoding(const char *ctype)
-{
- char *sys;
- int i;
-
- sys = get_encoding_from_locale(ctype);
-
- for (i = 0; encoding_match_list[i].system_enc_name; i++)
- {
- if (pg_strcasecmp(sys, encoding_match_list[i].system_enc_name) == 0)
- {
- free(sys);
- return encoding_match_list[i].pg_enc_code;
- }
- }
-
- free(sys);
- return -1;
-}
-#endif /* HAVE_LANGINFO_H && CODESET */
-
-
/*
* Support for determining the best default text search configuration.
* We key this off LC_CTYPE, after stripping its encoding indicator if any.
@@ -2909,10 +2715,6 @@ main(int argc, char *argv[])
if (strlen(username) == 0)
username = effective_user;
-
- if (strlen(encoding))
- encodingid = get_encoding_id(encoding);
-
set_input(&bki_file, "postgres.bki");
set_input(&desc_file, "postgres.description");
set_input(&shdesc_file, "postgres.shdescription");
@@ -2988,32 +2790,58 @@ main(int argc, char *argv[])
lc_time);
}
-#if defined(HAVE_LANGINFO_H) && defined(CODESET)
- if (strcmp(lc_ctype, "C") != 0 && strcmp(lc_ctype, "POSIX") != 0)
+ if (strlen(encoding) == 0)
{
- if (strlen(encoding) == 0)
- {
- int tmp;
+ int ctype_enc;
- tmp = find_matching_encoding(lc_ctype);
- if (tmp == -1)
- {
- fprintf(stderr, _("%s: could not find suitable encoding for locale \"%s\"\n"), progname, lc_ctype);
- fprintf(stderr, _("Rerun %s with the -E option.\n"), progname);
- fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
- exit(1);
- }
- else
- {
- encodingid = encodingid_to_string(tmp);
- printf(_("The default database encoding has accordingly been set to %s.\n"),
- pg_encoding_to_char(tmp));
- }
+ ctype_enc = pg_get_encoding_from_locale(lc_ctype);
+
+ if (ctype_enc == PG_SQL_ASCII &&
+ !(pg_strcasecmp(lc_ctype, "C") == 0 ||
+ pg_strcasecmp(lc_ctype, "POSIX") == 0))
+ {
+ fprintf(stderr, _("%s: could not find suitable encoding for locale \"%s\"\n"),
+ progname, lc_ctype);
+ fprintf(stderr, _("Rerun %s with the -E option.\n"), progname);
+ fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
+ progname);
+ exit(1);
}
else
- check_encodings_match(atoi(encodingid), lc_ctype);
+ {
+ encodingid = encodingid_to_string(ctype_enc);
+ printf(_("The default database encoding has accordingly been set to %s.\n"),
+ pg_encoding_to_char(ctype_enc));
+ }
+ }
+ else
+ {
+ int user_enc;
+ int ctype_enc;
+
+ encodingid = get_encoding_id(encoding);
+ user_enc = atoi(encodingid);
+
+ ctype_enc = pg_get_encoding_from_locale(lc_ctype);
+
+ /* We allow selection of SQL_ASCII --- see notes in createdb() */
+ if (!(ctype_enc == user_enc ||
+ ctype_enc == PG_SQL_ASCII ||
+ user_enc == PG_SQL_ASCII))
+ {
+ fprintf(stderr, _("%s: encoding mismatch\n"), progname);
+ fprintf(stderr,
+ _("The encoding you selected (%s) and the encoding that the\n"
+ "selected locale uses (%s) do not match. This would lead to\n"
+ "misbehavior in various character string processing functions.\n"
+ "Rerun %s and either do not specify an encoding explicitly,\n"
+ "or choose a matching combination.\n"),
+ pg_encoding_to_char(user_enc),
+ pg_encoding_to_char(ctype_enc),
+ progname);
+ exit(1);
+ }
}
-#endif /* HAVE_LANGINFO_H && CODESET */
if (strlen(default_text_search_config) == 0)
{
diff --git a/src/include/port.h b/src/include/port.h
index 77709d45b7..2e46f7cdbc 100644
--- a/src/include/port.h
+++ b/src/include/port.h
@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/port.h,v 1.112 2007/07/12 23:28:49 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/port.h,v 1.113 2007/09/28 22:25:49 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -391,4 +391,7 @@ typedef int (*qsort_arg_comparator) (const void *a, const void *b, void *arg);
extern void qsort_arg(void *base, size_t nel, size_t elsize,
qsort_arg_comparator cmp, void *arg);
+/* port/chklocale.c */
+extern int pg_get_encoding_from_locale(const char *ctype);
+
#endif /* PG_PORT_H */
diff --git a/src/port/Makefile b/src/port/Makefile
index 5ab4dd0a78..b1131599e3 100644
--- a/src/port/Makefile
+++ b/src/port/Makefile
@@ -14,8 +14,12 @@
# libpgport_srv.a - contains object files without FRONTEND defined,
# for use only by the backend binaries
#
+# LIBOBJS is set by configure (via Makefile.global) to be the list of
+# object files that are conditionally needed depending on platform.
+# OBJS adds additional object files that are always compiled.
+#
# IDENTIFICATION
-# $PostgreSQL: pgsql/src/port/Makefile,v 1.34 2007/02/09 15:56:00 petere Exp $
+# $PostgreSQL: pgsql/src/port/Makefile,v 1.35 2007/09/28 22:25:49 tgl Exp $
#
#-------------------------------------------------------------------------
@@ -26,8 +30,10 @@ include $(top_builddir)/src/Makefile.global
override CPPFLAGS := -I$(top_builddir)/src/port -DFRONTEND $(CPPFLAGS)
LIBS += $(PTHREAD_LIBS)
-# Replace all object files so they use FRONTEND define
-LIBOBJS_SRV = $(LIBOBJS:%.o=%_srv.o)
+OBJS = $(LIBOBJS) chklocale.o copydir.o dirmod.o exec.o noblock.o path.o pipe.o pgsleep.o pgstrcasecmp.o qsort.o qsort_arg.o sprompt.o thread.o
+
+# foo_srv.o and foo.o are both built from foo.c, but only foo.o has -DFRONTEND
+OBJS_SRV = $(OBJS:%.o=%_srv.o)
all: libpgport.a libpgport_srv.a
@@ -41,32 +47,29 @@ installdirs:
uninstall:
rm -f '$(DESTDIR)$(libdir)/libpgport.a'
-libpgport.a: $(LIBOBJS)
+libpgport.a: $(OBJS)
$(AR) $(AROPT) $@ $^
+# thread.o needs PTHREAD_CFLAGS (but thread_srv.o does not)
thread.o: thread.c
$(CC) $(CFLAGS) $(CPPFLAGS) $(PTHREAD_CFLAGS) -c $<
-path.o: path.c pg_config_paths.h
-
-path_srv.o: path.c pg_config_paths.h
-
#
# Server versions of object files
#
-libpgport_srv.a: $(LIBOBJS_SRV)
+libpgport_srv.a: $(OBJS_SRV)
$(AR) $(AROPT) $@ $^
%_srv.o: %.c
$(CC) $(CFLAGS) $(subst -DFRONTEND,, $(CPPFLAGS)) -c $< -o $@
-# No thread flags for server version
-thread_srv.o: thread.c
- $(CC) $(CFLAGS) $(subst -DFRONTEND,, $(CPPFLAGS)) -c $< -o $@
-
# Dependency is to ensure that path changes propagate
-#
+
+path.o: path.c pg_config_paths.h
+
+path_srv.o: path.c pg_config_paths.h
+
# We create a separate file rather than put these in pg_config.h
# because many of these values come from makefiles and are not
# available to configure.
@@ -84,4 +87,4 @@ pg_config_paths.h: $(top_builddir)/src/Makefile.global
echo "#define MANDIR \"$(mandir)\"" >>$@
clean distclean maintainer-clean:
- rm -f libpgport.a libpgport_srv.a $(LIBOBJS) $(LIBOBJS_SRV) pg_config_paths.h
+ rm -f libpgport.a libpgport_srv.a $(OBJS) $(OBJS_SRV) pg_config_paths.h
diff --git a/src/port/chklocale.c b/src/port/chklocale.c
new file mode 100644
index 0000000000..399438fe77
--- /dev/null
+++ b/src/port/chklocale.c
@@ -0,0 +1,246 @@
+/*-------------------------------------------------------------------------
+ *
+ * chklocale.c
+ * Functions for handling locale-related info
+ *
+ *
+ * Copyright (c) 1996-2007, PostgreSQL Global Development Group
+ *
+ *
+ * IDENTIFICATION
+ * $PostgreSQL: pgsql/src/port/chklocale.c,v 1.1 2007/09/28 22:25:49 tgl Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef FRONTEND
+#include "postgres.h"
+#else
+#include "postgres_fe.h"
+#endif
+
+#include <locale.h>
+#ifdef HAVE_LANGINFO_H
+#include <langinfo.h>
+#endif
+
+#include "mb/pg_wchar.h"
+
+
+#if defined(HAVE_LANGINFO_H) && defined(CODESET)
+
+/*
+ * This table needs to recognize all the CODESET spellings for supported
+ * backend encodings. We don't need to handle frontend-only encodings.
+ * Note that we search the table with pg_strcasecmp(), so variant
+ * capitalizations don't need their own entries.
+ */
+struct encoding_match
+{
+ enum pg_enc pg_enc_code;
+ const char *system_enc_name;
+};
+
+static const struct encoding_match encoding_match_list[] = {
+ {PG_EUC_JP, "EUC-JP"},
+ {PG_EUC_JP, "eucJP"},
+ {PG_EUC_JP, "IBM-eucJP"},
+ {PG_EUC_JP, "sdeckanji"},
+
+ {PG_EUC_CN, "EUC-CN"},
+ {PG_EUC_CN, "eucCN"},
+ {PG_EUC_CN, "IBM-eucCN"},
+ {PG_EUC_CN, "GB2312"},
+ {PG_EUC_CN, "dechanzi"},
+
+ {PG_EUC_KR, "EUC-KR"},
+ {PG_EUC_KR, "eucKR"},
+ {PG_EUC_KR, "IBM-eucKR"},
+ {PG_EUC_KR, "deckorean"},
+ {PG_EUC_KR, "5601"},
+
+ {PG_EUC_TW, "EUC-TW"},
+ {PG_EUC_TW, "eucTW"},
+ {PG_EUC_TW, "IBM-eucTW"},
+ {PG_EUC_TW, "cns11643"},
+
+ {PG_UTF8, "UTF-8"},
+ {PG_UTF8, "utf8"},
+
+ {PG_LATIN1, "ISO-8859-1"},
+ {PG_LATIN1, "ISO8859-1"},
+ {PG_LATIN1, "iso88591"},
+
+ {PG_LATIN2, "ISO-8859-2"},
+ {PG_LATIN2, "ISO8859-2"},
+ {PG_LATIN2, "iso88592"},
+
+ {PG_LATIN3, "ISO-8859-3"},
+ {PG_LATIN3, "ISO8859-3"},
+ {PG_LATIN3, "iso88593"},
+
+ {PG_LATIN4, "ISO-8859-4"},
+ {PG_LATIN4, "ISO8859-4"},
+ {PG_LATIN4, "iso88594"},
+
+ {PG_LATIN5, "ISO-8859-9"},
+ {PG_LATIN5, "ISO8859-9"},
+ {PG_LATIN5, "iso88599"},
+
+ {PG_LATIN6, "ISO-8859-10"},
+ {PG_LATIN6, "ISO8859-10"},
+ {PG_LATIN6, "iso885910"},
+
+ {PG_LATIN7, "ISO-8859-13"},
+ {PG_LATIN7, "ISO8859-13"},
+ {PG_LATIN7, "iso885913"},
+
+ {PG_LATIN8, "ISO-8859-14"},
+ {PG_LATIN8, "ISO8859-14"},
+ {PG_LATIN8, "iso885914"},
+
+ {PG_LATIN9, "ISO-8859-15"},
+ {PG_LATIN9, "ISO8859-15"},
+ {PG_LATIN9, "iso885915"},
+
+ {PG_LATIN10, "ISO-8859-16"},
+ {PG_LATIN10, "ISO8859-16"},
+ {PG_LATIN10, "iso885916"},
+
+ {PG_KOI8R, "KOI8-R"},
+
+ {PG_WIN1252, "CP1252"},
+ {PG_WIN1253, "CP1253"},
+ {PG_WIN1254, "CP1254"},
+ {PG_WIN1255, "CP1255"},
+ {PG_WIN1256, "CP1256"},
+ {PG_WIN1257, "CP1257"},
+ {PG_WIN1258, "CP1258"},
+#ifdef NOT_VERIFIED
+ {PG_WIN874, "???"},
+#endif
+ {PG_WIN1251, "CP1251"},
+ {PG_WIN866, "CP866"},
+
+ {PG_ISO_8859_5, "ISO-8859-5"},
+ {PG_ISO_8859_5, "ISO8859-5"},
+ {PG_ISO_8859_5, "iso88595"},
+
+ {PG_ISO_8859_6, "ISO-8859-6"},
+ {PG_ISO_8859_6, "ISO8859-6"},
+ {PG_ISO_8859_6, "iso88596"},
+
+ {PG_ISO_8859_7, "ISO-8859-7"},
+ {PG_ISO_8859_7, "ISO8859-7"},
+ {PG_ISO_8859_7, "iso88597"},
+
+ {PG_ISO_8859_8, "ISO-8859-8"},
+ {PG_ISO_8859_8, "ISO8859-8"},
+ {PG_ISO_8859_8, "iso88598"},
+
+ {PG_SQL_ASCII, NULL} /* end marker */
+};
+
+
+/*
+ * Given a setting for LC_CTYPE, return the Postgres ID of the associated
+ * encoding, if we can determine it.
+ *
+ * Pass in NULL to get the encoding for the current locale setting.
+ *
+ * If the result is PG_SQL_ASCII, callers should treat it as being compatible
+ * with any desired encoding. We return this if the locale is C/POSIX or we
+ * can't determine the encoding.
+ */
+int
+pg_get_encoding_from_locale(const char *ctype)
+{
+ char *sys;
+ int i;
+
+ if (ctype)
+ {
+ char *save;
+
+ save = setlocale(LC_CTYPE, NULL);
+ if (!save)
+ return PG_SQL_ASCII; /* setlocale() broken? */
+ /* must copy result, or it might change after setlocale */
+ save = strdup(save);
+ if (!save)
+ return PG_SQL_ASCII; /* out of memory; unlikely */
+
+ if (!setlocale(LC_CTYPE, ctype))
+ {
+ free(save);
+ return PG_SQL_ASCII; /* bogus ctype passed in? */
+ }
+
+ sys = nl_langinfo(CODESET);
+ if (sys)
+ sys = strdup(sys);
+
+ setlocale(LC_CTYPE, save);
+ free(save);
+ }
+ else
+ {
+ /* much easier... */
+ ctype = setlocale(LC_CTYPE, NULL);
+ if (!ctype)
+ return PG_SQL_ASCII; /* setlocale() broken? */
+ sys = nl_langinfo(CODESET);
+ if (sys)
+ sys = strdup(sys);
+ }
+
+ if (!sys)
+ return PG_SQL_ASCII; /* out of memory; unlikely */
+
+ if (pg_strcasecmp(ctype, "C") == 0 || pg_strcasecmp(ctype, "POSIX") == 0)
+ {
+ free(sys);
+ return PG_SQL_ASCII;
+ }
+
+ for (i = 0; encoding_match_list[i].system_enc_name; i++)
+ {
+ if (pg_strcasecmp(sys, encoding_match_list[i].system_enc_name) == 0)
+ {
+ free(sys);
+ return encoding_match_list[i].pg_enc_code;
+ }
+ }
+
+ /*
+ * We print a warning if we got a CODESET string but couldn't recognize
+ * it. This means we need another entry in the table.
+ */
+#ifdef FRONTEND
+ fprintf(stderr, _("could not determine encoding for locale \"%s\": codeset is \"%s\""),
+ ctype, sys);
+ /* keep newline separate so there's only one translatable string */
+ fputc('\n', stderr);
+#else
+ ereport(WARNING,
+ (errmsg("could not determine encoding for locale \"%s\": codeset is \"%s\"",
+ ctype, sys),
+ errdetail("Please report this to <pgsql-bugs@postgresql.org>.")));
+#endif
+
+ free(sys);
+ return PG_SQL_ASCII;
+}
+
+#else /* !(HAVE_LANGINFO_H && CODESET) */
+
+/*
+ * stub if no platform support
+ */
+int
+pg_get_encoding_from_locale(const char *ctype)
+{
+ return PG_SQL_ASCII;
+}
+
+#endif /* HAVE_LANGINFO_H && CODESET */