summaryrefslogtreecommitdiffstats
path: root/bin/sh/var.c
diff options
context:
space:
mode:
authorjilles <jilles@FreeBSD.org>2010-05-05 21:48:40 +0000
committerjilles <jilles@FreeBSD.org>2010-05-05 21:48:40 +0000
commitf3856c6cf2fb115757967b7e32bdeb21bd27d1ee (patch)
tree01c037f5647b269e05a273c3cef3f8cb4478c6f9 /bin/sh/var.c
parenta5718881d81033624f276036560f07f69ceac0cc (diff)
downloadFreeBSD-src-f3856c6cf2fb115757967b7e32bdeb21bd27d1ee.zip
FreeBSD-src-f3856c6cf2fb115757967b7e32bdeb21bd27d1ee.tar.gz
sh: Apply locale vars on builtins, recognize LC_MESSAGES as a locale var.
This allows doing things like LC_ALL=C some_builtin to run a builtin under a different locale, just like is possible with external programs. The immediate reason is that this allows making printf(1) a builtin without breaking things like LC_NUMERIC=C printf '%f\n' 1.2 This change also affects special builtins, as even though the assignment is persistent, the export is only to the builtin (unless the variable was already exported). Note: for this to work for builtins that also exist as external programs such as /bin/test, the setlocale() call must be under #ifndef SHELL. The shell will do the setlocale() calls which may not agree with the environment variables.
Diffstat (limited to 'bin/sh/var.c')
-rw-r--r--bin/sh/var.c75
1 files changed, 68 insertions, 7 deletions
diff --git a/bin/sh/var.c b/bin/sh/var.c
index d46e2c3..75de239 100644
--- a/bin/sh/var.c
+++ b/bin/sh/var.c
@@ -122,6 +122,14 @@ STATIC const struct varinit varinit[] = {
STATIC struct var *vartab[VTABSIZE];
+STATIC const char *const locale_names[7] = {
+ "LC_COLLATE", "LC_CTYPE", "LC_MONETARY",
+ "LC_NUMERIC", "LC_TIME", "LC_MESSAGES", NULL
+};
+STATIC const int locale_categories[7] = {
+ LC_COLLATE, LC_CTYPE, LC_MONETARY, LC_NUMERIC, LC_TIME, LC_MESSAGES, 0
+};
+
STATIC struct var **hashvar(const char *);
STATIC int varequal(const char *, const char *);
STATIC int localevar(const char *);
@@ -258,11 +266,7 @@ setvar(const char *name, const char *val, int flags)
STATIC int
localevar(const char *s)
{
- static const char *lnames[7] = {
- "ALL", "COLLATE", "CTYPE", "MONETARY",
- "NUMERIC", "TIME", NULL
- };
- const char **ss;
+ const char *const *ss;
if (*s != 'L')
return 0;
@@ -270,8 +274,10 @@ localevar(const char *s)
return 1;
if (strncmp(s + 1, "C_", 2) != 0)
return 0;
- for (ss = lnames; *ss ; ss++)
- if (varequal(s + 3, *ss))
+ if (varequal(s + 3, "ALL"))
+ return 1;
+ for (ss = locale_names; *ss ; ss++)
+ if (varequal(s + 3, *ss + 3))
return 1;
return 0;
}
@@ -437,6 +443,61 @@ bltinlookup(const char *name, int doall)
}
+/*
+ * Set up locale for a builtin (LANG/LC_* assignments).
+ */
+void
+bltinsetlocale(void)
+{
+ struct strlist *lp;
+ int act = 0;
+ char *loc, *locdef;
+ int i;
+
+ for (lp = cmdenviron ; lp ; lp = lp->next) {
+ if (localevar(lp->text)) {
+ act = 1;
+ break;
+ }
+ }
+ if (!act)
+ return;
+ loc = bltinlookup("LC_ALL", 0);
+ INTOFF;
+ if (loc != NULL) {
+ setlocale(LC_ALL, loc);
+ INTON;
+ return;
+ }
+ locdef = bltinlookup("LANG", 0);
+ for (i = 0; locale_names[i] != NULL; i++) {
+ loc = bltinlookup(locale_names[i], 0);
+ if (loc == NULL)
+ loc = locdef;
+ if (loc != NULL)
+ setlocale(locale_categories[i], loc);
+ }
+ INTON;
+}
+
+/*
+ * Undo the effect of bltinlocaleset().
+ */
+void
+bltinunsetlocale(void)
+{
+ struct strlist *lp;
+
+ INTOFF;
+ for (lp = cmdenviron ; lp ; lp = lp->next) {
+ if (localevar(lp->text)) {
+ setlocale(LC_ALL, "");
+ return;
+ }
+ }
+ INTON;
+}
+
/*
* Generate a list of exported variables. This routine is used to construct
OpenPOWER on IntegriCloud