[BACK]Return to locale.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / locale

File: [local] / src / usr.bin / locale / locale.c (download)

Revision 1.13, Fri Apr 17 10:45:04 2020 UTC (4 years, 1 month ago) by schwarze
Branch: MAIN
CVS Tags: OPENBSD_7_5_BASE, OPENBSD_7_5, OPENBSD_7_4_BASE, OPENBSD_7_4, OPENBSD_7_3_BASE, OPENBSD_7_3, OPENBSD_7_2_BASE, OPENBSD_7_2, OPENBSD_7_1_BASE, OPENBSD_7_1, OPENBSD_7_0_BASE, OPENBSD_7_0, OPENBSD_6_9_BASE, OPENBSD_6_9, OPENBSD_6_8_BASE, OPENBSD_6_8, OPENBSD_6_7_BASE, OPENBSD_6_7, HEAD
Changes since 1.12: +8 -3 lines

implement the "charmap" argument as required by POSIX;
OK stsp@ millert@

/*	$OpenBSD: locale.c,v 1.13 2020/04/17 10:45:04 schwarze Exp $	*/
/*
 * Copyright (c) 2013 Stefan Sperling <stsp@openbsd.org>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include <err.h>
#include <langinfo.h>
#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

extern char		*__progname;

struct category_name {
	int category;
	const char *name;
} categories[] = {
	{ LC_COLLATE,	"LC_COLLATE" },
	{ LC_CTYPE,	"LC_CTYPE" },
	{ LC_MONETARY,	"LC_MONETARY" },
	{ LC_NUMERIC,	"LC_NUMERIC" },
	{ LC_TIME,	"LC_TIME" },
	{ LC_MESSAGES,	"LC_MESSAGES" },
	{ 0, 		NULL},
};

static void
put_assignment(const char *name, const char *value, int double_quoted)
{
	char c;

	fputs(name, stdout);
	putchar('=');
	if (double_quoted)
		putchar('"');
	if (value != NULL)
		while ((c = *value++) != '\0')
			switch (c) {
			case ' ': case '\t': case '\n': case '\'':
			case '(': case ')': case '<': case '>':
			case '&': case ';': case '|': case '~':
				if (!double_quoted)
			case '"': case '\\': case '$': case '`': 
					putchar('\\');
			default:
				putchar(c);
				break;
			}
	if (double_quoted)
		putchar('"');
	putchar('\n');
}

static void
show_current_locale(void)
{
	char *lang, *lc_all;
	int i;

	lang = getenv("LANG");
	lc_all = getenv("LC_ALL");

	put_assignment("LANG", lang, 0);
	for (i = 0; categories[i].name != NULL; i++) {
		if (lc_all == NULL && getenv(categories[i].name))
			put_assignment(categories[i].name,
			    getenv(categories[i].name), 0);
		else
			put_assignment(categories[i].name,
			    setlocale(categories[i].category, NULL), 1);
	}
	put_assignment("LC_ALL", lc_all, 0);
}

const char * const some_locales[] = {
	"C",
	"C.UTF-8",
	"POSIX",
	"POSIX.UTF-8",
	"Pig.UTF-8",
	"ar_SD.UTF-8",
	"ar_SY.UTF-8",
	"ca_ES.UTF-8",
	"cs_CZ.UTF-8",
	"da_DK.UTF-8",
	"de_AT.UTF-8",
	"de_CH.UTF-8",
	"de_DE.UTF-8",
	"el_GR.UTF-8",
	"en_AU.UTF-8",
	"en_CA.UTF-8",
	"en_GB.UTF-8",
	"en_US.UTF-8",
	"es_AR.UTF-8",
	"es_BO.UTF-8",
	"es_CH.UTF-8",
	"es_CO.UTF-8",
	"es_CR.UTF-8",
	"es_CU.UTF-8",
	"es_DO.UTF-8",
	"es_EC.UTF-8",
	"es_ES.UTF-8",
	"es_GQ.UTF-8",
	"es_GT.UTF-8",
	"es_HN.UTF-8",
	"es_MX.UTF-8",
	"es_NI.UTF-8",
	"es_PA.UTF-8",
	"es_PE.UTF-8",
	"es_PR.UTF-8",
	"es_PY.UTF-8",
	"es_SV.UTF-8",
	"es_US.UTF-8",
	"es_UY.UTF-8",
	"es_VE.UTF-8",
	"fa_IR.UTF-8",
	"fi_FI.UTF-8",
	"fr_BE.UTF-8",
	"fr_CA.UTF-8",
	"fr_CH.UTF-8",
	"fr_FR.UTF-8",
	"hu_HU.UTF-8",
	"hy_AM.UTF-8",
	"is_IS.UTF-8",
	"it_CH.UTF-8",
	"it_IT.UTF-8",
	"ja_JP.UTF-8",
	"ko_KR.UTF-8",
	"lt_LT.UTF-8",
	"nl_BE.UTF-8",
	"nl_NL.UTF-8",
	"no_NO.UTF-8",
	"pl_PL.UTF-8",
	"pt_PT.UTF-8",
	"ro_RO.UTF-8",
	"ru_RU.UTF-8",
	"sk_SK.UTF-8",
	"sl_SI.UTF-8",
	"sv_SE.UTF-8",
	"tr_TR.UTF-8",
	"uk_UA.UTF-8",
	"zh_CN.UTF-8",
	"zh_TW.UTF-8",
	NULL
};

static void
show_locales(void)
{
	int i = 0;

	while (some_locales[i])
		puts(some_locales[i++]);
}

static void
usage(void)
{
	fprintf(stderr, "usage: %s [-a | -m | charmap]\n", __progname);
	exit(1);
}

int
main(int argc, char *argv[])
{
	int opt, aflag = 0, mflag = 0;

	setlocale(LC_ALL, "");

	if (pledge("stdio", NULL) == -1)
		err(1, "pledge");

	if (argc == 1) {
		show_current_locale();
		return 0;
	}

	while ((opt = getopt(argc, argv, "am")) != -1) {
		switch (opt) {
		case 'a':
			aflag = 1;
			break;
		case 'm':
			mflag = 1;
			break;
		default:
			usage();
		}
	}
	argc -= optind;
	argv += optind;

	if (aflag + mflag + argc > 1)
		usage();
	else if (aflag)
		show_locales();
	else if (mflag)
		printf("UTF-8\n");
	else if (strcmp(*argv, "charmap") == 0)
		printf("%s\n", nl_langinfo(CODESET));
	else
		usage();

	return 0;
}