Imported Upstream version 1.8.7
[debian/sudo] / plugins / sudoers / locale.c
1 /*
2  * Copyright (c) 2012-2013 Todd C. Miller <Todd.Miller@courtesan.com>
3  *
4  * Permission to use, copy, modify, and distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16
17 #include <config.h>
18
19 #include <sys/types.h>
20 #include <stdio.h>
21 #ifdef STDC_HEADERS
22 # include <stdlib.h>
23 # include <stddef.h>
24 #else
25 # ifdef HAVE_STDLIB_H
26 #  include <stdlib.h>
27 # endif
28 #endif /* STDC_HEADERS */
29 #ifdef HAVE_STRING_H
30 # include <string.h>
31 #endif /* HAVE_STRING_H */
32 #ifdef HAVE_STRINGS_H
33 # include <strings.h>
34 #endif /* HAVE_STRINGS_H */
35 #ifdef HAVE_STDBOOL_H
36 # include <stdbool.h>
37 #else
38 # include "compat/stdbool.h"
39 #endif /* HAVE_STDBOOL_H */
40
41 #include "missing.h"
42 #include "error.h"
43 #include "alloc.h"
44 #include "logging.h"
45 #include "gettext.h"
46
47 static int current_locale = SUDOERS_LOCALE_USER;
48 static char *user_locale;
49 static char *sudoers_locale;
50
51 int
52 sudoers_getlocale(void)
53 {
54     return current_locale;
55 }
56
57 void
58 sudoers_initlocale(const char *ulocale, const char *slocale)
59 {
60     if (ulocale != NULL) {
61         efree(user_locale);
62         user_locale = estrdup(ulocale);
63     }
64     if (slocale != NULL) {
65         efree(sudoers_locale);
66         sudoers_locale = estrdup(slocale);
67     }
68 }
69
70 /*
71  * Set locale to user or sudoers value.
72  * Returns true on success and false on failure,
73  * If prevlocale is non-NULL it will be filled in with the
74  * old SUDOERS_LOCALE_* value.
75  */
76 bool
77 sudoers_setlocale(int newlocale, int *prevlocale)
78 {
79     char *res = NULL;
80
81     switch (newlocale) {
82         case SUDOERS_LOCALE_USER:
83             if (prevlocale)
84                 *prevlocale = current_locale;
85             if (current_locale != SUDOERS_LOCALE_USER) {
86                 current_locale = SUDOERS_LOCALE_USER;
87                 res = setlocale(LC_ALL, user_locale ? user_locale : "");
88                 if (res != NULL && user_locale == NULL)
89                     user_locale = estrdup(setlocale(LC_ALL, NULL));
90             }
91             break;
92         case SUDOERS_LOCALE_SUDOERS:
93             if (prevlocale)
94                 *prevlocale = current_locale;
95             if (current_locale != SUDOERS_LOCALE_SUDOERS) {
96                 current_locale = SUDOERS_LOCALE_SUDOERS;
97                 res = setlocale(LC_ALL, sudoers_locale ? sudoers_locale : "C");
98                 if (res == NULL && sudoers_locale != NULL) {
99                     if (strcmp(sudoers_locale, "C") != 0) {
100                         efree(sudoers_locale);
101                         sudoers_locale = estrdup("C");
102                         res = setlocale(LC_ALL, "C");
103                     }
104                 }
105             }
106             break;
107     }
108     return res ? true : false;
109 }
110
111 static int warning_locale;
112
113 void
114 warning_set_locale(void)
115 {
116     sudoers_setlocale(SUDOERS_LOCALE_USER, &warning_locale);
117 }
118
119 void
120 warning_restore_locale(void)
121 {
122     sudoers_setlocale(warning_locale, NULL);
123 }