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
put_assignment(const char * name,const char * value,int double_quoted)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
show_current_locale(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
show_locales(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
usage(void)171 usage(void)
172 {
173 fprintf(stderr, "usage: %s [-a | -m | charmap]\n", __progname);
174 exit(1);
175 }
176
177 int
main(int argc,char * argv[])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