Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/jdk17u
Path: blob/master/src/java.base/unix/native/libjava/java_props_md.c
67848 views
1
/*
2
* Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
#if defined(__linux__) || defined(_ALLBSD_SOURCE)
27
#include <stdio.h>
28
#include <ctype.h>
29
#endif
30
#include <pwd.h>
31
#include <locale.h>
32
#ifndef ARCHPROPNAME
33
#error "The macro ARCHPROPNAME has not been defined"
34
#endif
35
#include <sys/utsname.h> /* For os_name and os_version */
36
#include <langinfo.h> /* For nl_langinfo */
37
#include <stdlib.h>
38
#include <string.h>
39
#include <sys/types.h>
40
#include <unistd.h>
41
#include <sys/param.h>
42
#include <time.h>
43
#include <errno.h>
44
45
#ifdef MACOSX
46
#include "java_props_macosx.h"
47
#endif
48
49
#if defined(_ALLBSD_SOURCE)
50
#if !defined(P_tmpdir)
51
#include <paths.h>
52
#define P_tmpdir _PATH_VARTMP
53
#endif
54
#endif
55
56
#include "locale_str.h"
57
#include "java_props.h"
58
59
#if !defined(_ALLBSD_SOURCE)
60
#ifdef __linux__
61
#ifndef CODESET
62
#define CODESET _NL_CTYPE_CODESET_NAME
63
#endif
64
#else
65
#ifdef ALT_CODESET_KEY
66
#define CODESET ALT_CODESET_KEY
67
#endif
68
#endif
69
#endif /* !_ALLBSD_SOURCE */
70
71
/* Take an array of string pairs (map of key->value) and a string (key).
72
* Examine each pair in the map to see if the first string (key) matches the
73
* string. If so, store the second string of the pair (value) in the value and
74
* return 1. Otherwise do nothing and return 0. The end of the map is
75
* indicated by an empty string at the start of a pair (key of "").
76
*/
77
static int
78
mapLookup(char* map[], const char* key, char** value) {
79
int i;
80
for (i = 0; strcmp(map[i], ""); i += 2){
81
if (!strcmp(key, map[i])){
82
*value = map[i + 1];
83
return 1;
84
}
85
}
86
return 0;
87
}
88
89
#ifndef P_tmpdir
90
#define P_tmpdir "/var/tmp"
91
#endif
92
93
static int ParseLocale(JNIEnv* env, int cat, char ** std_language, char ** std_script,
94
char ** std_country, char ** std_variant, char ** std_encoding) {
95
char *temp = NULL;
96
char *language = NULL, *country = NULL, *variant = NULL,
97
*encoding = NULL;
98
char *p, *encoding_variant, *old_temp, *old_ev;
99
char *lc;
100
101
/* Query the locale set for the category */
102
103
#ifdef MACOSX
104
lc = setupMacOSXLocale(cat); // malloc'd memory, need to free
105
#else
106
lc = setlocale(cat, NULL);
107
#endif
108
109
#ifndef __linux__
110
if (lc == NULL) {
111
return 0;
112
}
113
114
temp = malloc(strlen(lc) + 1);
115
if (temp == NULL) {
116
#ifdef MACOSX
117
free(lc); // malloced memory
118
#endif
119
JNU_ThrowOutOfMemoryError(env, NULL);
120
return 0;
121
}
122
123
if (cat == LC_CTYPE) {
124
/*
125
* Workaround for Solaris bug 4201684: Xlib doesn't like @euro
126
* locales. Since we don't depend on the libc @euro behavior,
127
* we just remove the qualifier.
128
* On Linux, the bug doesn't occur; on the other hand, @euro
129
* is needed there because it's a shortcut that also determines
130
* the encoding - without it, we wouldn't get ISO-8859-15.
131
* Therefore, this code section is Solaris-specific.
132
*/
133
strcpy(temp, lc);
134
p = strstr(temp, "@euro");
135
if (p != NULL) {
136
*p = '\0';
137
setlocale(LC_ALL, temp);
138
}
139
}
140
#else
141
if (lc == NULL || !strcmp(lc, "C") || !strcmp(lc, "POSIX")) {
142
lc = "en_US";
143
}
144
145
temp = malloc(strlen(lc) + 1);
146
if (temp == NULL) {
147
JNU_ThrowOutOfMemoryError(env, NULL);
148
return 0;
149
}
150
151
#endif
152
153
/*
154
* locale string format in Solaris is
155
* <language name>_<country name>.<encoding name>@<variant name>
156
* <country name>, <encoding name>, and <variant name> are optional.
157
*/
158
159
strcpy(temp, lc);
160
#ifdef MACOSX
161
free(lc); // malloced memory
162
#endif
163
/* Parse the language, country, encoding, and variant from the
164
* locale. Any of the elements may be missing, but they must occur
165
* in the order language_country.encoding@variant, and must be
166
* preceded by their delimiter (except for language).
167
*
168
* If the locale name (without .encoding@variant, if any) matches
169
* any of the names in the locale_aliases list, map it to the
170
* corresponding full locale name. Most of the entries in the
171
* locale_aliases list are locales that include a language name but
172
* no country name, and this facility is used to map each language
173
* to a default country if that's possible. It's also used to map
174
* the Solaris locale aliases to their proper Java locale IDs.
175
*/
176
177
encoding_variant = malloc(strlen(temp)+1);
178
if (encoding_variant == NULL) {
179
free(temp);
180
JNU_ThrowOutOfMemoryError(env, NULL);
181
return 0;
182
}
183
184
if ((p = strchr(temp, '.')) != NULL) {
185
strcpy(encoding_variant, p); /* Copy the leading '.' */
186
*p = '\0';
187
} else if ((p = strchr(temp, '@')) != NULL) {
188
strcpy(encoding_variant, p); /* Copy the leading '@' */
189
*p = '\0';
190
} else {
191
*encoding_variant = '\0';
192
}
193
194
if (mapLookup(locale_aliases, temp, &p)) {
195
old_temp = temp;
196
temp = realloc(temp, strlen(p)+1);
197
if (temp == NULL) {
198
free(old_temp);
199
free(encoding_variant);
200
JNU_ThrowOutOfMemoryError(env, NULL);
201
return 0;
202
}
203
strcpy(temp, p);
204
old_ev = encoding_variant;
205
encoding_variant = realloc(encoding_variant, strlen(temp)+1);
206
if (encoding_variant == NULL) {
207
free(old_ev);
208
free(temp);
209
JNU_ThrowOutOfMemoryError(env, NULL);
210
return 0;
211
}
212
// check the "encoding_variant" again, if any.
213
if ((p = strchr(temp, '.')) != NULL) {
214
strcpy(encoding_variant, p); /* Copy the leading '.' */
215
*p = '\0';
216
} else if ((p = strchr(temp, '@')) != NULL) {
217
strcpy(encoding_variant, p); /* Copy the leading '@' */
218
*p = '\0';
219
}
220
}
221
222
language = temp;
223
if ((country = strchr(temp, '_')) != NULL) {
224
*country++ = '\0';
225
}
226
227
p = encoding_variant;
228
if ((encoding = strchr(p, '.')) != NULL) {
229
p[encoding++ - p] = '\0';
230
p = encoding;
231
}
232
if ((variant = strchr(p, '@')) != NULL) {
233
p[variant++ - p] = '\0';
234
}
235
236
/* Normalize the language name */
237
if (std_language != NULL) {
238
*std_language = "en";
239
if (language != NULL && mapLookup(language_names, language, std_language) == 0) {
240
*std_language = malloc(strlen(language)+1);
241
strcpy(*std_language, language);
242
}
243
}
244
245
/* Normalize the country name */
246
if (std_country != NULL && country != NULL) {
247
if (mapLookup(country_names, country, std_country) == 0) {
248
*std_country = malloc(strlen(country)+1);
249
strcpy(*std_country, country);
250
}
251
}
252
253
/* Normalize the script and variant name. Note that we only use
254
* variants listed in the mapping array; others are ignored.
255
*/
256
if (variant != NULL) {
257
if (std_script != NULL) {
258
mapLookup(script_names, variant, std_script);
259
}
260
261
if (std_variant != NULL) {
262
mapLookup(variant_names, variant, std_variant);
263
}
264
}
265
266
/* Normalize the encoding name. Note that we IGNORE the string
267
* 'encoding' extracted from the locale name above. Instead, we use the
268
* more reliable method of calling nl_langinfo(CODESET). This function
269
* returns an empty string if no encoding is set for the given locale
270
* (e.g., the C or POSIX locales); we use the default ISO 8859-1
271
* converter for such locales.
272
*/
273
if (std_encoding != NULL) {
274
/* OK, not so reliable - nl_langinfo() gives wrong answers on
275
* Euro locales, in particular. */
276
if (strcmp(p, "ISO8859-15") == 0)
277
p = "ISO8859-15";
278
else
279
p = nl_langinfo(CODESET);
280
281
/* Convert the bare "646" used on Solaris to a proper IANA name */
282
if (strcmp(p, "646") == 0)
283
p = "ISO646-US";
284
285
/* return same result nl_langinfo would return for en_UK,
286
* in order to use optimizations. */
287
*std_encoding = (*p != '\0') ? p : "ISO8859-1";
288
289
#ifdef __linux__
290
/*
291
* Remap the encoding string to a different value for japanese
292
* locales on linux so that customized converters are used instead
293
* of the default converter for "EUC-JP". The customized converters
294
* omit support for the JIS0212 encoding which is not supported by
295
* the variant of "EUC-JP" encoding used on linux
296
*/
297
if (strcmp(p, "EUC-JP") == 0) {
298
*std_encoding = "EUC-JP-LINUX";
299
}
300
#endif
301
302
#ifdef _AIX
303
if (strcmp(p, "big5") == 0) {
304
/* On AIX Traditional Chinese Big5 codeset is mapped to IBM-950 */
305
*std_encoding = "IBM-950";
306
} else if (strcmp(p, "IBM-943") == 0) {
307
/*
308
* On AIX, IBM-943 is mapped to IBM-943C in which symbol 'yen' and
309
* 'overline' are replaced with 'backslash' and 'tilde' from ASCII
310
* making first 96 code points same as ASCII.
311
*/
312
*std_encoding = "IBM-943C";
313
}
314
#endif
315
316
#ifdef MACOSX
317
/*
318
* For the case on MacOS X where encoding is set to US-ASCII, but we
319
* don't have any encoding hints from LANG/LC_ALL/LC_CTYPE, use UTF-8
320
* instead.
321
*
322
* The contents of ASCII files will still be read and displayed
323
* correctly, but so will files containing UTF-8 characters beyond the
324
* standard ASCII range.
325
*
326
* Specifically, this allows apps launched by double-clicking a .jar
327
* file to correctly read UTF-8 files using the default encoding (see
328
* 8011194).
329
*/
330
const char* env_lang = getenv("LANG");
331
const char* env_lc_all = getenv("LC_ALL");
332
const char* env_lc_ctype = getenv("LC_CTYPE");
333
334
if (strcmp(p,"US-ASCII") == 0 &&
335
(env_lang == NULL || strlen(env_lang) == 0) &&
336
(env_lc_all == NULL || strlen(env_lc_all) == 0) &&
337
(env_lc_ctype == NULL || strlen(env_lc_ctype) == 0)) {
338
*std_encoding = "UTF-8";
339
}
340
#endif
341
}
342
343
free(temp);
344
free(encoding_variant);
345
346
return 1;
347
}
348
349
/* This function gets called very early, before VM_CALLS are setup.
350
* Do not use any of the VM_CALLS entries!!!
351
*/
352
java_props_t *
353
GetJavaProperties(JNIEnv *env)
354
{
355
static java_props_t sprops;
356
char *v; /* tmp var */
357
358
if (sprops.user_dir) {
359
return &sprops;
360
}
361
362
/* tmp dir */
363
sprops.tmp_dir = P_tmpdir;
364
#ifdef MACOSX
365
/* darwin has a per-user temp dir */
366
static char tmp_path[PATH_MAX];
367
int pathSize = confstr(_CS_DARWIN_USER_TEMP_DIR, tmp_path, PATH_MAX);
368
if (pathSize > 0 && pathSize <= PATH_MAX) {
369
sprops.tmp_dir = tmp_path;
370
}
371
#endif /* MACOSX */
372
373
/* patches/service packs installed */
374
sprops.patch_level = NULL; // leave it undefined
375
376
#ifdef SI_ISALIST
377
/* supported instruction sets */
378
{
379
char list[258];
380
sysinfo(SI_ISALIST, list, sizeof(list));
381
sprops.cpu_isalist = strdup(list);
382
}
383
#else
384
sprops.cpu_isalist = NULL;
385
#endif
386
387
/* endianness of platform */
388
{
389
unsigned int endianTest = 0xff000000;
390
if (((char*)(&endianTest))[0] != 0)
391
sprops.cpu_endian = "big";
392
else
393
sprops.cpu_endian = "little";
394
}
395
396
/* os properties */
397
{
398
#ifdef MACOSX
399
setOSNameAndVersion(&sprops);
400
#else
401
struct utsname name;
402
uname(&name);
403
sprops.os_name = strdup(name.sysname);
404
#ifdef _AIX
405
{
406
char *os_version = malloc(strlen(name.version) +
407
strlen(name.release) + 2);
408
if (os_version != NULL) {
409
strcpy(os_version, name.version);
410
strcat(os_version, ".");
411
strcat(os_version, name.release);
412
}
413
sprops.os_version = os_version;
414
}
415
#else
416
sprops.os_version = strdup(name.release);
417
#endif /* _AIX */
418
#endif /* MACOSX */
419
420
sprops.os_arch = ARCHPROPNAME;
421
}
422
423
/* ABI property (optional) */
424
#ifdef JDK_ARCH_ABI_PROP_NAME
425
sprops.sun_arch_abi = JDK_ARCH_ABI_PROP_NAME;
426
#endif
427
428
/* Determine the language, country, variant, and encoding from the host,
429
* and store these in the user.language, user.country, user.variant and
430
* file.encoding system properties. */
431
setlocale(LC_ALL, "");
432
if (ParseLocale(env, LC_CTYPE,
433
&(sprops.format_language),
434
&(sprops.format_script),
435
&(sprops.format_country),
436
&(sprops.format_variant),
437
&(sprops.encoding))) {
438
ParseLocale(env, LC_MESSAGES,
439
&(sprops.display_language),
440
&(sprops.display_script),
441
&(sprops.display_country),
442
&(sprops.display_variant),
443
NULL);
444
} else {
445
sprops.display_language = "en";
446
sprops.encoding = "ISO8859-1";
447
}
448
449
/* ParseLocale failed with OOME */
450
JNU_CHECK_EXCEPTION_RETURN(env, NULL);
451
452
#ifdef MACOSX
453
sprops.sun_jnu_encoding = "UTF-8";
454
#else
455
sprops.sun_jnu_encoding = sprops.encoding;
456
#endif
457
if (isatty(STDOUT_FILENO) == 1) {
458
sprops.sun_stdout_encoding = sprops.encoding;
459
}
460
if (isatty(STDERR_FILENO) == 1) {
461
sprops.sun_stderr_encoding = sprops.encoding;
462
}
463
464
#ifdef _ALLBSD_SOURCE
465
#if BYTE_ORDER == _LITTLE_ENDIAN
466
sprops.unicode_encoding = "UnicodeLittle";
467
#else
468
sprops.unicode_encoding = "UnicodeBig";
469
#endif
470
#else /* !_ALLBSD_SOURCE */
471
#ifdef __linux__
472
#if __BYTE_ORDER == __LITTLE_ENDIAN
473
sprops.unicode_encoding = "UnicodeLittle";
474
#else
475
sprops.unicode_encoding = "UnicodeBig";
476
#endif
477
#else
478
sprops.unicode_encoding = "UnicodeBig";
479
#endif
480
#endif /* _ALLBSD_SOURCE */
481
482
/* user properties */
483
{
484
struct passwd *pwent = getpwuid(getuid());
485
sprops.user_name = pwent ? strdup(pwent->pw_name) : "?";
486
#ifdef MACOSX
487
setUserHome(&sprops);
488
#else
489
sprops.user_home = pwent ? strdup(pwent->pw_dir) : NULL;
490
#endif
491
if (sprops.user_home == NULL) {
492
sprops.user_home = "?";
493
}
494
}
495
496
/* User TIMEZONE
497
* We defer setting up timezone until it's actually necessary.
498
* Refer to TimeZone.getDefault(). The system property
499
* is able to be set by the command line interface -Duser.timezone.
500
*/
501
tzset(); /* for compatibility */
502
503
/* Current directory */
504
{
505
char buf[MAXPATHLEN];
506
errno = 0;
507
if (getcwd(buf, sizeof(buf)) == NULL)
508
JNU_ThrowByName(env, "java/lang/Error",
509
"Properties init: Could not determine current working directory.");
510
else
511
sprops.user_dir = strdup(buf);
512
}
513
514
sprops.file_separator = "/";
515
sprops.path_separator = ":";
516
sprops.line_separator = "\n";
517
518
#ifdef MACOSX
519
setProxyProperties(&sprops);
520
#endif
521
522
return &sprops;
523
}
524
525
jstring
526
GetStringPlatform(JNIEnv *env, nchar* cstr)
527
{
528
return JNU_NewStringPlatform(env, cstr);
529
}
530
531