1 |
|
|
/* $OpenBSD: _get_locname.c,v 1.1 2017/09/05 03:16:13 schwarze Exp $ */ |
2 |
|
|
/* |
3 |
|
|
* Copyright (c) 2017 Ingo Schwarze <schwarze@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 <errno.h> |
19 |
|
|
#include <locale.h> |
20 |
|
|
#include <paths.h> |
21 |
|
|
#include <stdio.h> |
22 |
|
|
#include <stdlib.h> |
23 |
|
|
#include <string.h> |
24 |
|
|
|
25 |
|
|
#include "rune.h" |
26 |
|
|
#include "rune_local.h" |
27 |
|
|
|
28 |
|
|
/* |
29 |
|
|
* Supplement the input with locale(1) variables from the |
30 |
|
|
* environment, validate it, and initialize UTF-8 when needed. |
31 |
|
|
* Return NULL on error, "" if unset (for LC_ALL only), |
32 |
|
|
* or the name of the locale that takes effect. |
33 |
|
|
*/ |
34 |
|
|
const char * |
35 |
|
|
_get_locname(int category, const char *locname) |
36 |
|
|
{ |
37 |
|
|
static const char *const catname[_LC_LAST - 1] = { |
38 |
|
|
"LC_COLLATE", "LC_CTYPE", "LC_MONETARY", |
39 |
|
|
"LC_NUMERIC", "LC_TIME", "LC_MESSAGES" |
40 |
|
|
}; |
41 |
|
|
|
42 |
|
|
FILE *fp; |
43 |
|
|
const char *cp; |
44 |
|
|
int save_errno; |
45 |
|
|
|
46 |
|
|
/* For empty input, inspect the environment. */ |
47 |
|
|
if (*locname == '\0') |
48 |
|
|
locname = getenv("LC_ALL"); |
49 |
|
|
|
50 |
|
|
if (category != LC_ALL) { |
51 |
|
|
if (locname == NULL || *locname == '\0') |
52 |
|
|
locname = getenv(catname[category - 1]); |
53 |
|
|
if (locname == NULL || *locname == '\0') |
54 |
|
|
locname = getenv("LANG"); |
55 |
|
|
} |
56 |
|
|
|
57 |
|
|
/* |
58 |
|
|
* If still empty, treat LC_ALL as unset, but |
59 |
|
|
* fall back to the default locale for other categories. |
60 |
|
|
*/ |
61 |
|
|
if (locname == NULL || *locname == '\0') |
62 |
|
|
locname = category == LC_ALL ? "" : "C"; |
63 |
|
|
|
64 |
|
|
/* Accept and ignore all language and territory prefixes. */ |
65 |
|
|
if ((cp = strrchr(locname, '.')) == NULL) |
66 |
|
|
return locname; |
67 |
|
|
|
68 |
|
|
/* Reject all encodings except ASCII and UTF-8. */ |
69 |
|
|
if (strcmp(cp + 1, "UTF-8") != 0) |
70 |
|
|
return NULL; |
71 |
|
|
|
72 |
|
|
/* Initialize the UTF-8 character encoding locale, if needed. */ |
73 |
|
|
if (_Utf8RuneLocale != NULL) |
74 |
|
|
return locname; |
75 |
|
|
save_errno = errno; |
76 |
|
|
if ((fp = fopen(_PATH_LOCALE "/UTF-8/LC_CTYPE", "re")) != NULL) { |
77 |
|
|
_Utf8RuneLocale = _Read_RuneMagi(fp); |
78 |
|
|
fclose(fp); |
79 |
|
|
} |
80 |
|
|
errno = save_errno; |
81 |
|
|
return _Utf8RuneLocale == NULL ? NULL : locname; |
82 |
|
|
} |