Line data Source code
1 : /* 2 : Mosh: the mobile shell 3 : Copyright 2012 Keith Winstein 4 : 5 : This program is free software: you can redistribute it and/or modify 6 : it under the terms of the GNU General Public License as published by 7 : the Free Software Foundation, either version 3 of the License, or 8 : (at your option) any later version. 9 : 10 : This program is distributed in the hope that it will be useful, 11 : but WITHOUT ANY WARRANTY; without even the implied warranty of 12 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 : GNU General Public License for more details. 14 : 15 : You should have received a copy of the GNU General Public License 16 : along with this program. If not, see <http://www.gnu.org/licenses/>. 17 : 18 : In addition, as a special exception, the copyright holders give 19 : permission to link the code of portions of this program with the 20 : OpenSSL library under certain conditions as described in each 21 : individual source file, and distribute linked combinations including 22 : the two. 23 : 24 : You must obey the GNU General Public License in all respects for all 25 : of the code used other than OpenSSL. If you modify file(s) with this 26 : exception, you may extend this exception to your version of the 27 : file(s), but you are not obligated to do so. If you do not wish to do 28 : so, delete this exception statement from your version. If you delete 29 : this exception statement from all source files in the program, then 30 : also delete it here. 31 : */ 32 : 33 : #include "config.h" 34 : 35 : #include <string.h> 36 : #include <stdlib.h> 37 : #include <stdio.h> 38 : #include <locale.h> 39 : #include <errno.h> 40 : #include <string> 41 : 42 : #if HAVE_LANGINFO_H 43 : #include <langinfo.h> 44 : #endif 45 : 46 : #include "locale_utils.h" 47 : 48 : 49 0 : const std::string LocaleVar::str( void ) const 50 : { 51 0 : if ( name.empty() ) { 52 0 : return std::string( "[no charset variables]" ); 53 : } 54 0 : return name + "=" + value; 55 : } 56 : 57 0 : const LocaleVar get_ctype( void ) 58 : { 59 : /* Reimplement the search logic, just for diagnostics */ 60 0 : if ( const char *all = getenv( "LC_ALL" ) ) { 61 0 : return LocaleVar( "LC_ALL", all ); 62 0 : } else if ( const char *ctype = getenv( "LC_CTYPE" ) ) { 63 0 : return LocaleVar( "LC_CTYPE", ctype ); 64 0 : } else if ( const char *lang = getenv( "LANG" ) ) { 65 0 : return LocaleVar( "LANG", lang ); 66 : } 67 0 : return LocaleVar( "", "" ); 68 : } 69 : 70 952 : const char *locale_charset( void ) 71 : { 72 952 : static const char ASCII_name[] = "US-ASCII"; 73 : 74 : /* Produce more pleasant name of US-ASCII */ 75 952 : const char *ret = nl_langinfo( CODESET ); 76 : 77 952 : if ( strcmp( ret, "ANSI_X3.4-1968" ) == 0 ) { 78 0 : ret = ASCII_name; 79 : } 80 : 81 952 : return ret; 82 : } 83 : 84 952 : bool is_utf8_locale( void ) { 85 : /* Verify locale calls for UTF-8 */ 86 952 : if ( strcmp( locale_charset(), "UTF-8" ) != 0 && 87 0 : strcmp( locale_charset(), "utf-8" ) != 0 ) { 88 0 : return false; 89 : } 90 : return true; 91 : } 92 : 93 952 : void set_native_locale( void ) { 94 : /* Adopt native locale */ 95 952 : if ( NULL == setlocale( LC_ALL, "" ) ) { 96 0 : int saved_errno = errno; 97 0 : if ( saved_errno == ENOENT ) { 98 0 : LocaleVar ctype( get_ctype() ); 99 0 : fprintf( stderr, "The locale requested by %s isn't available here.\n", ctype.str().c_str() ); 100 0 : if ( !ctype.name.empty() ) { 101 0 : fprintf( stderr, "Running `locale-gen %s' may be necessary.\n\n", 102 : ctype.value.c_str() ); 103 : } 104 0 : } else { 105 0 : errno = saved_errno; 106 0 : perror( "setlocale" ); 107 : } 108 : } 109 952 : } 110 : 111 0 : void clear_locale_variables( void ) { 112 0 : unsetenv( "LANG" ); 113 0 : unsetenv( "LANGUAGE" ); 114 0 : unsetenv( "LC_CTYPE" ); 115 0 : unsetenv( "LC_NUMERIC" ); 116 0 : unsetenv( "LC_TIME" ); 117 0 : unsetenv( "LC_COLLATE" ); 118 0 : unsetenv( "LC_MONETARY" ); 119 0 : unsetenv( "LC_MESSAGES" ); 120 0 : unsetenv( "LC_PAPER" ); 121 0 : unsetenv( "LC_NAME" ); 122 0 : unsetenv( "LC_ADDRESS" ); 123 0 : unsetenv( "LC_TELEPHONE" ); 124 0 : unsetenv( "LC_MEASUREMENT" ); 125 0 : unsetenv( "LC_IDENTIFICATION" ); 126 0 : unsetenv( "LC_ALL" ); 127 0 : }