summaryrefslogtreecommitdiffstats
path: root/usr.bin/locale
diff options
context:
space:
mode:
authorphantom <phantom@FreeBSD.org>2002-10-16 13:17:18 +0000
committerphantom <phantom@FreeBSD.org>2002-10-16 13:17:18 +0000
commitd6a3c23c588ada94f1fa8d1f4065ed4a03675cd9 (patch)
treee410125c140c0129c0aef4de84f1dfd7e0e0b61a /usr.bin/locale
parent8e05dc143adb02128f30edd4188901fb98ec5f22 (diff)
downloadFreeBSD-src-d6a3c23c588ada94f1fa8d1f4065ed4a03675cd9.zip
FreeBSD-src-d6a3c23c588ada94f1fa8d1f4065ed4a03675cd9.tar.gz
Add locale(1). I have used it for while as useful debugging tool
for locale related things. So, I think it could be useful for others. It's not yet implement (or implement in different manner) all POSIX things, but I think it's good enough for start. POSIX conformance related updates and manpage to follow relatively soon.
Diffstat (limited to 'usr.bin/locale')
-rw-r--r--usr.bin/locale/Makefile6
-rw-r--r--usr.bin/locale/locale.c214
2 files changed, 220 insertions, 0 deletions
diff --git a/usr.bin/locale/Makefile b/usr.bin/locale/Makefile
new file mode 100644
index 0000000..0f84009
--- /dev/null
+++ b/usr.bin/locale/Makefile
@@ -0,0 +1,6 @@
+# $FreeBSD$
+
+PROG = locale
+NOMAN=YES
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/locale/locale.c b/usr.bin/locale/locale.c
new file mode 100644
index 0000000..f7d82aa
--- /dev/null
+++ b/usr.bin/locale/locale.c
@@ -0,0 +1,214 @@
+/*-
+ * Copyright (c) 2002 Alexey Zelkin <phantom@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/types.h>
+#include <dirent.h>
+#include <locale.h>
+#include <rune.h> /* for _PATH_LOCALE */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stringlist.h>
+#include <unistd.h>
+
+/* Local prototypes */
+void usage(void);
+void get_locales_list(void);
+void list_locales(void);
+void display_locale_status(int);
+
+/* Global variables */
+static StringList *locales = NULL;
+
+int all_locales = 0;
+int verbose = 0;
+int env_used = 0;
+
+struct _lcinfo {
+ char *name;
+ int id;
+} lcinfo [] = {
+ "LANG", LC_ALL,
+ "LC_ALL", LC_ALL,
+ "LC_CTYPE", LC_CTYPE,
+ "LC_COLLATE", LC_COLLATE,
+ "LC_TIME", LC_TIME,
+ "LC_NUMERIC", LC_NUMERIC,
+ "LC_MONETARY", LC_MONETARY,
+ "LC_MESSAGES", LC_MESSAGES
+};
+#define NLCINFO (sizeof(lcinfo)/sizeof(lcinfo[0]))
+
+int
+main(int argc, char *argv[])
+{
+ char ch;
+
+ while ((ch = getopt(argc, argv, "av")) != -1)
+ switch (ch) {
+ case 'a':
+ all_locales = 1;
+ break;
+ case 'v':
+ verbose = 1;
+ break;
+ default:
+ usage();
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (all_locales) {
+ list_locales();
+ exit(0);
+ }
+
+ display_locale_status(verbose);
+ return (0);
+}
+
+void
+usage(void)
+{
+ printf("\nUsage: locale [ -a ] [ -v ]\n");
+ exit(1);
+}
+
+void
+list_locales(void)
+{
+ int i;
+
+ get_locales_list();
+ for (i = 0; i < locales->sl_cur; i++) {
+ printf("%s\n", locales->sl_str[i]);
+ }
+}
+
+void
+probe_var(char *varname, int id)
+{
+ char *value, *res1, *res2;
+
+ value = getenv(varname);
+ if (value == NULL) {
+ printf("%s = (null)\n", varname);
+ return;
+ }
+
+ if (sl_find(locales, value) == NULL)
+ res1 = "invalid";
+ else
+ res1 = "valid";
+
+ if (strcmp(value, setlocale(id, value)) != 0)
+ res2 = "invalid";
+ else
+ res2 = "valid";
+
+ printf("%s = \"%s\"\t\t(name is %s, content is %s)\n",
+ varname, value, res1, res2);
+}
+
+void
+display_locale_status(int verbose)
+{
+ int i;
+
+ setlocale(LC_ALL, "");
+
+ if (verbose) {
+ get_locales_list();
+ if (env_used)
+ printf("WARNING: PATH_LOCALE environment variable is set!");
+ }
+
+ printf("Current status of locale settings:\n\n");
+ for (i = 1; i < NLCINFO; i++) { /* start with 1 to avoid 'LANG' */
+ printf("%s = \"%s\"\n",
+ lcinfo[i].name,
+ setlocale(lcinfo[i].id, ""));
+ }
+
+ /*
+ * If verbose flag is set, add environment information
+ */
+ if (verbose) {
+ printf("\nCurrent environment variables (and status):\n\n");
+ for (i = 0; i < NLCINFO; i++)
+ probe_var(lcinfo[i].name, lcinfo[i].id);
+ }
+}
+
+static char *
+get_locale_path(void)
+{
+ char *localedir;
+
+ localedir = getenv("PATH_LOCALE");
+ if (localedir == NULL)
+ localedir = _PATH_LOCALE;
+ else
+ env_used = 1;
+ return (localedir);
+}
+
+static int
+scmp(const void *s1, const void *s2)
+{
+ return strcmp(*(const char **)s1, *(const char **)s2);
+}
+
+void
+get_locales_list()
+{
+ DIR *dirp;
+ struct dirent *dp;
+ char *dirname;
+
+ if (locales != NULL)
+ return;
+
+ locales = sl_init();
+ if (locales == NULL)
+ err(1, "could not allocate memory");
+
+ dirname = get_locale_path();
+ dirp = opendir(dirname);
+ if (dirp == NULL)
+ err(1, "could not open directory '%s'", dirname);
+
+ while ((dp = readdir(dirp)) != NULL) {
+ if (*dp->d_name == '.')
+ continue;
+ sl_add(locales, strdup(dp->d_name));
+ }
+ closedir(dirp);
+
+ qsort(locales->sl_str, locales->sl_cur, sizeof(char *), scmp);
+}
OpenPOWER on IntegriCloud