3939 * Portions Copyright (c) 1994, Regents of the University of California
4040 * Portions taken from FreeBSD.
4141 *
42- * $PostgreSQL: pgsql/src/bin/initdb/initdb.c,v 1.42 2004/07/12 01:54 :10 momjian Exp $
42+ * $PostgreSQL: pgsql/src/bin/initdb/initdb.c,v 1.43 2004/07/14 17:55 :10 petere Exp $
4343 *
4444 *-------------------------------------------------------------------------
4545 */
5252#include <locale.h>
5353#include <signal.h>
5454#include <errno.h>
55+ #ifdef HAVE_LANGINFO_H
56+ # include <langinfo.h>
57+ #endif
5558
5659#include "libpq/pqsignal.h"
5760#include "mb/pg_wchar.h"
@@ -600,29 +603,221 @@ get_id(void)
600603 return xstrdup (pw -> pw_name );
601604}
602605
606+ static char *
607+ encodingid_to_string (int enc )
608+ {
609+ char result [20 ];
610+
611+ sprintf (result , "%d" , enc );
612+ return xstrdup (result );
613+ }
614+
603615/*
604616 * get the encoding id for a given encoding name
605617 */
606618static char *
607619get_encoding_id (char * encoding_name )
608620{
609621 int enc ;
610- char result [20 ];
611622
612623 if (encoding_name && * encoding_name )
613624 {
614625 if ((enc = pg_char_to_encoding (encoding_name )) >= 0 &&
615626 pg_valid_server_encoding (encoding_name ) >= 0 )
616627 {
617- sprintf (result , "%d" , enc );
618- return xstrdup (result );
628+ return encodingid_to_string (enc );
619629 }
620630 }
621631 fprintf (stderr , _ ("%s: \"%s\" is not a valid server encoding name\n" ),
622632 progname , encoding_name ? encoding_name : "(null)" );
623633 exit (1 );
624634}
625635
636+ #ifdef HAVE_LANGINFO_H
637+ /*
638+ * Checks whether the encoding selected for PostgreSQL and the
639+ * encoding used by the system locale match.
640+ */
641+
642+ struct encoding_match
643+ {
644+ enum pg_enc pg_enc_code ;
645+ char * system_enc_name ;
646+ };
647+
648+ struct encoding_match encoding_match_list [] = {
649+ { PG_EUC_JP , "EUC-JP" },
650+ { PG_EUC_JP , "eucJP" },
651+ { PG_EUC_JP , "IBM-eucJP" },
652+ { PG_EUC_JP , "sdeckanji" },
653+
654+ { PG_EUC_CN , "EUC-CN" },
655+ { PG_EUC_CN , "eucCN" },
656+ { PG_EUC_CN , "IBM-eucCN" },
657+ { PG_EUC_CN , "GB2312" },
658+ { PG_EUC_CN , "dechanzi" },
659+
660+ { PG_EUC_KR , "EUC-KR" },
661+ { PG_EUC_KR , "eucKR" },
662+ { PG_EUC_KR , "IBM-eucKR" },
663+ { PG_EUC_KR , "deckorean" },
664+ { PG_EUC_KR , "5601" },
665+
666+ { PG_EUC_TW , "EUC-TW" },
667+ { PG_EUC_TW , "eucTW" },
668+ { PG_EUC_TW , "IBM-eucTW" },
669+ { PG_EUC_TW , "cns11643" },
670+
671+ #ifdef NOT_VERIFIED
672+ { PG_JOHAB , "???" },
673+ #endif
674+
675+ { PG_UTF8 , "UTF-8" },
676+ { PG_UTF8 , "utf8" },
677+
678+ { PG_LATIN1 , "ISO-8859-1" },
679+ { PG_LATIN1 , "ISO8859-1" },
680+ { PG_LATIN1 , "iso88591" },
681+
682+ { PG_LATIN2 , "ISO-8859-2" },
683+ { PG_LATIN2 , "ISO8859-2" },
684+ { PG_LATIN2 , "iso88592" },
685+
686+ { PG_LATIN3 , "ISO-8859-3" },
687+ { PG_LATIN3 , "ISO8859-3" },
688+ { PG_LATIN3 , "iso88593" },
689+
690+ { PG_LATIN4 , "ISO-8859-4" },
691+ { PG_LATIN4 , "ISO8859-4" },
692+ { PG_LATIN4 , "iso88594" },
693+
694+ { PG_LATIN5 , "ISO-8859-9" },
695+ { PG_LATIN5 , "ISO8859-9" },
696+ { PG_LATIN5 , "iso88599" },
697+
698+ { PG_LATIN6 , "ISO-8859-10" },
699+ { PG_LATIN6 , "ISO8859-10" },
700+ { PG_LATIN6 , "iso885910" },
701+
702+ { PG_LATIN7 , "ISO-8859-13" },
703+ { PG_LATIN7 , "ISO8859-13" },
704+ { PG_LATIN7 , "iso885913" },
705+
706+ { PG_LATIN8 , "ISO-8859-14" },
707+ { PG_LATIN8 , "ISO8859-14" },
708+ { PG_LATIN8 , "iso885914" },
709+
710+ { PG_LATIN9 , "ISO-8859-15" },
711+ { PG_LATIN9 , "ISO8859-15" },
712+ { PG_LATIN9 , "iso885915" },
713+
714+ { PG_LATIN10 , "ISO-8859-16" },
715+ { PG_LATIN10 , "ISO8859-16" },
716+ { PG_LATIN10 , "iso885916" },
717+
718+ { PG_WIN1256 , "CP1256" },
719+ { PG_TCVN , "CP1258" },
720+ #ifdef NOT_VERIFIED
721+ { PG_WIN874 , "???" },
722+ #endif
723+ { PG_KOI8R , "KOI8-R" },
724+ { PG_WIN1251 , "CP1251" },
725+ { PG_ALT , "CP866" },
726+
727+ { PG_ISO_8859_5 , "ISO-8859-5" },
728+ { PG_ISO_8859_5 , "ISO8859-5" },
729+ { PG_ISO_8859_5 , "iso88595" },
730+
731+ { PG_ISO_8859_6 , "ISO-8859-6" },
732+ { PG_ISO_8859_6 , "ISO8859-6" },
733+ { PG_ISO_8859_6 , "iso88596" },
734+
735+ { PG_ISO_8859_7 , "ISO-8859-7" },
736+ { PG_ISO_8859_7 , "ISO8859-7" },
737+ { PG_ISO_8859_7 , "iso88597" },
738+
739+ { PG_ISO_8859_8 , "ISO-8859-8" },
740+ { PG_ISO_8859_8 , "ISO8859-8" },
741+ { PG_ISO_8859_8 , "iso88598" },
742+
743+ { PG_SQL_ASCII , NULL } /* end marker */
744+ };
745+
746+ static char *
747+ get_encoding_from_locale (const char * ctype )
748+ {
749+ char * save ;
750+ char * sys ;
751+
752+ save = setlocale (LC_CTYPE , NULL );
753+ if (!save )
754+ return NULL ;
755+ save = xstrdup (save );
756+
757+ setlocale (LC_CTYPE , ctype );
758+ sys = nl_langinfo (CODESET );
759+ sys = xstrdup (sys );
760+
761+ setlocale (LC_CTYPE , save );
762+ free (save );
763+
764+ return sys ;
765+ }
766+
767+ static void
768+ check_encodings_match (int pg_enc , const char * ctype )
769+ {
770+ char * sys ;
771+ int i ;
772+
773+ sys = get_encoding_from_locale (ctype );
774+
775+ for (i = 0 ; encoding_match_list [i ].system_enc_name ; i ++ )
776+ {
777+ if (pg_enc == encoding_match_list [i ].pg_enc_code
778+ && strcasecmp (sys , encoding_match_list [i ].system_enc_name ) == 0 )
779+ {
780+ free (sys );
781+ return ;
782+ }
783+ }
784+
785+ fprintf (stderr ,
786+ _ ("%s: warning: encoding mismatch\n" ), progname );
787+ fprintf (stderr ,
788+ _ ("The encoding you selected (%s) and the encoding that the selected\n"
789+ "locale uses (%s) are not known to match. This may lead to\n"
790+ "misbehavior in various character string processing functions. To fix\n"
791+ "this situation, rerun %s and either do not specify an encoding\n"
792+ "explicitly, or choose a matching combination.\n" ),
793+ pg_encoding_to_char (pg_enc ), sys , progname );
794+
795+ free (sys );
796+ return ;
797+ }
798+
799+ static int
800+ find_matching_encoding (const char * ctype )
801+ {
802+ char * sys ;
803+ int i ;
804+
805+ sys = get_encoding_from_locale (ctype );
806+
807+ for (i = 0 ; encoding_match_list [i ].system_enc_name ; i ++ )
808+ {
809+ if (strcasecmp (sys , encoding_match_list [i ].system_enc_name ) == 0 )
810+ {
811+ free (sys );
812+ return encoding_match_list [i ].pg_enc_code ;
813+ }
814+ }
815+
816+ free (sys );
817+ return -1 ;
818+ }
819+ #endif /* HAVE_LANGINFO_H */
820+
626821/*
627822 * get short version of VERSION
628823 */
@@ -2027,13 +2222,11 @@ main(int argc, char *argv[])
20272222 fprintf (stderr ,
20282223 "VERSION=%s\n"
20292224 "PGDATA=%s\nshare_path=%s\nPGPATH=%s\n"
2030- "ENCODING=%s\nENCODINGID=%s\n"
20312225 "POSTGRES_SUPERUSERNAME=%s\nPOSTGRES_BKI=%s\n"
20322226 "POSTGRES_DESCR=%s\nPOSTGRESQL_CONF_SAMPLE=%s\n"
20332227 "PG_HBA_SAMPLE=%s\nPG_IDENT_SAMPLE=%s\n" ,
20342228 PG_VERSION ,
20352229 pg_data , share_path , bin_path ,
2036- encoding , encodingid ,
20372230 effective_user , bki_file ,
20382231 desc_file , conf_file ,
20392232 hba_file , ident_file );
@@ -2051,21 +2244,20 @@ main(int argc, char *argv[])
20512244 check_input (features_file );
20522245 check_input (system_views_file );
20532246
2247+ setlocales ();
2248+
20542249 printf (_ ("The files belonging to this database system will be owned "
20552250 "by user \"%s\".\n"
20562251 "This user must also own the server process.\n\n" ),
20572252 effective_user );
20582253
2059- setlocales ();
2060-
20612254 if (strcmp (lc_ctype , lc_collate ) == 0 &&
20622255 strcmp (lc_ctype , lc_time ) == 0 &&
20632256 strcmp (lc_ctype , lc_numeric ) == 0 &&
20642257 strcmp (lc_ctype , lc_monetary ) == 0 &&
20652258 strcmp (lc_ctype , lc_messages ) == 0 )
20662259 {
2067- printf (_ ("The database cluster will be initialized with locale %s.\n\n" ),
2068- lc_ctype );
2260+ printf (_ ("The database cluster will be initialized with locale %s.\n" ), lc_ctype );
20692261 }
20702262 else
20712263 {
@@ -2075,7 +2267,7 @@ main(int argc, char *argv[])
20752267 " MESSAGES: %s\n"
20762268 " MONETARY: %s\n"
20772269 " NUMERIC: %s\n"
2078- " TIME: %s\n\n " ),
2270+ " TIME: %s\n" ),
20792271 lc_collate ,
20802272 lc_ctype ,
20812273 lc_messages ,
@@ -2084,6 +2276,34 @@ main(int argc, char *argv[])
20842276 lc_time );
20852277 }
20862278
2279+ #ifdef HAVE_LANGINFO_H
2280+ if (strcmp (lc_ctype , "C" ) != 0 && strcmp (lc_ctype , "POSIX" ) != 0 )
2281+ {
2282+ if (strlen (encoding ) == 0 )
2283+ {
2284+ int tmp ;
2285+ tmp = find_matching_encoding (lc_ctype );
2286+ if (tmp == -1 )
2287+ {
2288+ fprintf (stderr , _ ("%s: could not find suitable encoding for locale \"%s\"\n" ), progname , lc_ctype );
2289+ fprintf (stderr , _ ("Rerun %s with the -E option.\n" ), progname );
2290+ fprintf (stderr , _ ("Try \"%s --help\" for more information.\n" ), progname );
2291+ exit (1 );
2292+ }
2293+ else
2294+ {
2295+ encodingid = encodingid_to_string (tmp );
2296+ printf (_ ("The default database encoding has accordingly been set to %s.\n" ),
2297+ pg_encoding_to_char (tmp ));
2298+ }
2299+ }
2300+ else
2301+ check_encodings_match (atoi (encodingid ), lc_ctype );
2302+ }
2303+ #endif /* HAVE_LANGINFO_H */
2304+
2305+ printf ("\n" );
2306+
20872307 umask (077 );
20882308
20892309 /*
0 commit comments