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 :10momjian Exp $
42+ * $PostgreSQL: pgsql/src/bin/initdb/initdb.c,v 1.43 2004/07/14 17:55 :10petere 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)
600603return 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{
609621int enc ;
610- char result [20 ];
611622
612623if (encoding_name && * encoding_name )
613624{
614625if ((enc = pg_char_to_encoding (encoding_name )) >=0 &&
615626pg_valid_server_encoding (encoding_name ) >=0 )
616627{
617- sprintf (result ,"%d" ,enc );
618- return xstrdup (result );
628+ return encodingid_to_string (enc );
619629}
620630}
621631fprintf (stderr ,_ ("%s: \"%s\" is not a valid server encoding name\n" ),
622632progname ,encoding_name ?encoding_name :"(null)" );
623633exit (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[])
20272222fprintf (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" ,
20342228PG_VERSION ,
20352229pg_data ,share_path ,bin_path ,
2036- encoding ,encodingid ,
20372230effective_user ,bki_file ,
20382231desc_file ,conf_file ,
20392232hba_file ,ident_file );
@@ -2051,21 +2244,20 @@ main(int argc, char *argv[])
20512244check_input (features_file );
20522245check_input (system_views_file );
20532246
2247+ setlocales ();
2248+
20542249printf (_ ("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" ),
20572252effective_user );
20582253
2059- setlocales ();
2060-
20612254if (strcmp (lc_ctype ,lc_collate )== 0 &&
20622255strcmp (lc_ctype ,lc_time )== 0 &&
20632256strcmp (lc_ctype ,lc_numeric )== 0 &&
20642257strcmp (lc_ctype ,lc_monetary )== 0 &&
20652258strcmp (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}
20702262else
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" ),
20792271lc_collate ,
20802272lc_ctype ,
20812273lc_messages ,
@@ -2084,6 +2276,34 @@ main(int argc, char *argv[])
20842276lc_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+
20872307umask (077 );
20882308
20892309/*