1 /* $OpenBSD: locale.c,v 1.13 2020/04/17 10:45:04 schwarze Exp $ */ 2 /* 3 * Copyright (c) 2013 Stefan Sperling <stsp@openbsd.org> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <err.h> 19 #include <langinfo.h> 20 #include <locale.h> 21 #include <stdio.h> 22 #include <stdlib.h> 23 #include <string.h> 24 #include <unistd.h> 25 26 extern char *__progname; 27 28 struct category_name { 29 int category; 30 const char *name; 31 } categories[] = { 32 { LC_COLLATE, "LC_COLLATE" }, 33 { LC_CTYPE, "LC_CTYPE" }, 34 { LC_MONETARY, "LC_MONETARY" }, 35 { LC_NUMERIC, "LC_NUMERIC" }, 36 { LC_TIME, "LC_TIME" }, 37 { LC_MESSAGES, "LC_MESSAGES" }, 38 { 0, NULL}, 39 }; 40 41 static void 42 put_assignment(const char *name, const char *value, int double_quoted) 43 { 44 char c; 45 46 fputs(name, stdout); 47 putchar('='); 48 if (double_quoted) 49 putchar('"'); 50 if (value != NULL) 51 while ((c = *value++) != '\0') 52 switch (c) { 53 case ' ': case '\t': case '\n': case '\'': 54 case '(': case ')': case '<': case '>': 55 case '&': case ';': case '|': case '~': 56 if (!double_quoted) 57 case '"': case '\\': case '$': case '`': 58 putchar('\\'); 59 default: 60 putchar(c); 61 break; 62 } 63 if (double_quoted) 64 putchar('"'); 65 putchar('\n'); 66 } 67 68 static void 69 show_current_locale(void) 70 { 71 char *lang, *lc_all; 72 int i; 73 74 lang = getenv("LANG"); 75 lc_all = getenv("LC_ALL"); 76 77 put_assignment("LANG", lang, 0); 78 for (i = 0; categories[i].name != NULL; i++) { 79 if (lc_all == NULL && getenv(categories[i].name)) 80 put_assignment(categories[i].name, 81 getenv(categories[i].name), 0); 82 else 83 put_assignment(categories[i].name, 84 setlocale(categories[i].category, NULL), 1); 85 } 86 put_assignment("LC_ALL", lc_all, 0); 87 } 88 89 const char * const some_locales[] = { 90 "C", 91 "C.UTF-8", 92 "POSIX", 93 "POSIX.UTF-8", 94 "Pig.UTF-8", 95 "ar_SD.UTF-8", 96 "ar_SY.UTF-8", 97 "ca_ES.UTF-8", 98 "cs_CZ.UTF-8", 99 "da_DK.UTF-8", 100 "de_AT.UTF-8", 101 "de_CH.UTF-8", 102 "de_DE.UTF-8", 103 "el_GR.UTF-8", 104 "en_AU.UTF-8", 105 "en_CA.UTF-8", 106 "en_GB.UTF-8", 107 "en_US.UTF-8", 108 "es_AR.UTF-8", 109 "es_BO.UTF-8", 110 "es_CH.UTF-8", 111 "es_CO.UTF-8", 112 "es_CR.UTF-8", 113 "es_CU.UTF-8", 114 "es_DO.UTF-8", 115 "es_EC.UTF-8", 116 "es_ES.UTF-8", 117 "es_GQ.UTF-8", 118 "es_GT.UTF-8", 119 "es_HN.UTF-8", 120 "es_MX.UTF-8", 121 "es_NI.UTF-8", 122 "es_PA.UTF-8", 123 "es_PE.UTF-8", 124 "es_PR.UTF-8", 125 "es_PY.UTF-8", 126 "es_SV.UTF-8", 127 "es_US.UTF-8", 128 "es_UY.UTF-8", 129 "es_VE.UTF-8", 130 "fa_IR.UTF-8", 131 "fi_FI.UTF-8", 132 "fr_BE.UTF-8", 133 "fr_CA.UTF-8", 134 "fr_CH.UTF-8", 135 "fr_FR.UTF-8", 136 "hu_HU.UTF-8", 137 "hy_AM.UTF-8", 138 "is_IS.UTF-8", 139 "it_CH.UTF-8", 140 "it_IT.UTF-8", 141 "ja_JP.UTF-8", 142 "ko_KR.UTF-8", 143 "lt_LT.UTF-8", 144 "nl_BE.UTF-8", 145 "nl_NL.UTF-8", 146 "no_NO.UTF-8", 147 "pl_PL.UTF-8", 148 "pt_PT.UTF-8", 149 "ro_RO.UTF-8", 150 "ru_RU.UTF-8", 151 "sk_SK.UTF-8", 152 "sl_SI.UTF-8", 153 "sv_SE.UTF-8", 154 "tr_TR.UTF-8", 155 "uk_UA.UTF-8", 156 "zh_CN.UTF-8", 157 "zh_TW.UTF-8", 158 NULL 159 }; 160 161 static void 162 show_locales(void) 163 { 164 int i = 0; 165 166 while (some_locales[i]) 167 puts(some_locales[i++]); 168 } 169 170 static void 171 usage(void) 172 { 173 fprintf(stderr, "usage: %s [-a | -m | charmap]\n", __progname); 174 exit(1); 175 } 176 177 int 178 main(int argc, char *argv[]) 179 { 180 int opt, aflag = 0, mflag = 0; 181 182 setlocale(LC_ALL, ""); 183 184 if (pledge("stdio", NULL) == -1) 185 err(1, "pledge"); 186 187 if (argc == 1) { 188 show_current_locale(); 189 return 0; 190 } 191 192 while ((opt = getopt(argc, argv, "am")) != -1) { 193 switch (opt) { 194 case 'a': 195 aflag = 1; 196 break; 197 case 'm': 198 mflag = 1; 199 break; 200 default: 201 usage(); 202 } 203 } 204 argc -= optind; 205 argv += optind; 206 207 if (aflag + mflag + argc > 1) 208 usage(); 209 else if (aflag) 210 show_locales(); 211 else if (mflag) 212 printf("UTF-8\n"); 213 else if (strcmp(*argv, "charmap") == 0) 214 printf("%s\n", nl_langinfo(CODESET)); 215 else 216 usage(); 217 218 return 0; 219 } 220