xref: /titanic_51/usr/src/cmd/localedef/localedef.c (revision 2da1cd3a39e2d3da7f9d15071ea9462919c011ac)
16b5e5868SGarrett D'Amore /*
26b5e5868SGarrett D'Amore  * This file and its contents are supplied under the terms of the
36b5e5868SGarrett D'Amore  * Common Development and Distribution License ("CDDL"), version 1.0.
45aec55ebSGarrett D'Amore  * You may only use this file in accordance with the terms of version
55aec55ebSGarrett D'Amore  * 1.0 of the CDDL.
66b5e5868SGarrett D'Amore  *
76b5e5868SGarrett D'Amore  * A full copy of the text of the CDDL should have accompanied this
86b5e5868SGarrett D'Amore  * source.  A copy of the CDDL is also available via the Internet at
96b5e5868SGarrett D'Amore  * http://www.illumos.org/license/CDDL.
106b5e5868SGarrett D'Amore  */
116b5e5868SGarrett D'Amore 
126b5e5868SGarrett D'Amore /*
136b5e5868SGarrett D'Amore  * Copyright 2010 Nexenta Systems, Inc.  All rights reserved.
14*2da1cd3aSGarrett D'Amore  * Copyright 2013 DEY Storage Systems, Inc.
156b5e5868SGarrett D'Amore  */
166b5e5868SGarrett D'Amore 
176b5e5868SGarrett D'Amore /*
186b5e5868SGarrett D'Amore  * POSIX localedef.
196b5e5868SGarrett D'Amore  */
206b5e5868SGarrett D'Amore 
216b5e5868SGarrett D'Amore #include <stdio.h>
226b5e5868SGarrett D'Amore #include <stdlib.h>
236b5e5868SGarrett D'Amore #include <errno.h>
246b5e5868SGarrett D'Amore #include <sys/types.h>
256b5e5868SGarrett D'Amore #include <sys/stat.h>
266b5e5868SGarrett D'Amore #include <string.h>
276b5e5868SGarrett D'Amore #include <unistd.h>
286b5e5868SGarrett D'Amore #include <libgen.h>
296b5e5868SGarrett D'Amore #include <stddef.h>
306b5e5868SGarrett D'Amore #include <unistd.h>
316b5e5868SGarrett D'Amore #include <limits.h>
326b5e5868SGarrett D'Amore #include <locale.h>
336b5e5868SGarrett D'Amore #include <dirent.h>
346b5e5868SGarrett D'Amore #include "localedef.h"
356b5e5868SGarrett D'Amore #include "parser.tab.h"
366b5e5868SGarrett D'Amore 
376b5e5868SGarrett D'Amore #ifndef	TEXT_DOMAIN
386b5e5868SGarrett D'Amore #define	TEXT_DOMAIN	"SYS_TEST"
396b5e5868SGarrett D'Amore #endif
406b5e5868SGarrett D'Amore 
416b5e5868SGarrett D'Amore int verbose = 0;
426b5e5868SGarrett D'Amore int undefok = 0;
436b5e5868SGarrett D'Amore int warnok = 0;
446b5e5868SGarrett D'Amore static char *locname = NULL;
456b5e5868SGarrett D'Amore static char locpath[PATH_MAX];
466b5e5868SGarrett D'Amore 
476b5e5868SGarrett D'Amore const char *
486b5e5868SGarrett D'Amore category_name(void)
496b5e5868SGarrett D'Amore {
506b5e5868SGarrett D'Amore 	switch (get_category()) {
516b5e5868SGarrett D'Amore 	case T_CHARMAP:
526b5e5868SGarrett D'Amore 		return ("CHARMAP");
53*2da1cd3aSGarrett D'Amore 	case T_WIDTH:
54*2da1cd3aSGarrett D'Amore 		return ("WIDTH");
556b5e5868SGarrett D'Amore 	case T_COLLATE:
566b5e5868SGarrett D'Amore 		return ("LC_COLLATE");
576b5e5868SGarrett D'Amore 	case T_CTYPE:
586b5e5868SGarrett D'Amore 		return ("LC_CTYPE");
596b5e5868SGarrett D'Amore 	case T_MESSAGES:
606b5e5868SGarrett D'Amore 		return ("LC_MESSAGES");
616b5e5868SGarrett D'Amore 	case T_MONETARY:
626b5e5868SGarrett D'Amore 		return ("LC_MONETARY");
636b5e5868SGarrett D'Amore 	case T_NUMERIC:
646b5e5868SGarrett D'Amore 		return ("LC_NUMERIC");
656b5e5868SGarrett D'Amore 	case T_TIME:
666b5e5868SGarrett D'Amore 		return ("LC_TIME");
676b5e5868SGarrett D'Amore 	default:
686b5e5868SGarrett D'Amore 		INTERR;
696b5e5868SGarrett D'Amore 		return (NULL);
706b5e5868SGarrett D'Amore 	}
716b5e5868SGarrett D'Amore }
726b5e5868SGarrett D'Amore 
736b5e5868SGarrett D'Amore static char *
746b5e5868SGarrett D'Amore category_file(void)
756b5e5868SGarrett D'Amore {
766b5e5868SGarrett D'Amore 	(void) snprintf(locpath, sizeof (locpath), "%s/%s/LCL_DATA",
776b5e5868SGarrett D'Amore 	    locname, category_name());
786b5e5868SGarrett D'Amore 	return (locpath);
796b5e5868SGarrett D'Amore }
806b5e5868SGarrett D'Amore 
816b5e5868SGarrett D'Amore FILE *
826b5e5868SGarrett D'Amore open_category(void)
836b5e5868SGarrett D'Amore {
846b5e5868SGarrett D'Amore 	FILE *file;
856b5e5868SGarrett D'Amore 
866b5e5868SGarrett D'Amore 	if (verbose) {
876b5e5868SGarrett D'Amore 		(void) printf(_("Writing category %s: "), category_name());
886b5e5868SGarrett D'Amore 		(void) fflush(stdout);
896b5e5868SGarrett D'Amore 	}
906b5e5868SGarrett D'Amore 
916b5e5868SGarrett D'Amore 	/* make the parent directory */
926b5e5868SGarrett D'Amore 	(void) mkdirp(dirname(category_file()), 0755);
936b5e5868SGarrett D'Amore 
946b5e5868SGarrett D'Amore 	/*
956b5e5868SGarrett D'Amore 	 * note that we have to regenerate the file name, as dirname
966b5e5868SGarrett D'Amore 	 * clobbered it.
976b5e5868SGarrett D'Amore 	 */
986b5e5868SGarrett D'Amore 	file = fopen(category_file(), "w");
996b5e5868SGarrett D'Amore 	if (file == NULL) {
1006b5e5868SGarrett D'Amore 		errf(strerror(errno));
1016b5e5868SGarrett D'Amore 		return (NULL);
1026b5e5868SGarrett D'Amore 	}
1036b5e5868SGarrett D'Amore 	return (file);
1046b5e5868SGarrett D'Amore }
1056b5e5868SGarrett D'Amore 
1066b5e5868SGarrett D'Amore void
1076b5e5868SGarrett D'Amore close_category(FILE *f)
1086b5e5868SGarrett D'Amore {
1096b5e5868SGarrett D'Amore 	if (fchmod(fileno(f), 0644) < 0) {
1106b5e5868SGarrett D'Amore 		(void) fclose(f);
1116b5e5868SGarrett D'Amore 		(void) unlink(category_file());
1126b5e5868SGarrett D'Amore 		errf(strerror(errno));
1136b5e5868SGarrett D'Amore 	}
1146b5e5868SGarrett D'Amore 	if (fclose(f) < 0) {
1156b5e5868SGarrett D'Amore 		(void) unlink(category_file());
1166b5e5868SGarrett D'Amore 		errf(strerror(errno));
1176b5e5868SGarrett D'Amore 	}
1186b5e5868SGarrett D'Amore 	if (verbose) {
1196b5e5868SGarrett D'Amore 		(void) fprintf(stdout, _("done.\n"));
1206b5e5868SGarrett D'Amore 		(void) fflush(stdout);
1216b5e5868SGarrett D'Amore 	}
1226b5e5868SGarrett D'Amore }
1236b5e5868SGarrett D'Amore 
1246b5e5868SGarrett D'Amore /*
1256b5e5868SGarrett D'Amore  * This function is used when copying the category from another
1266b5e5868SGarrett D'Amore  * locale.  Note that the copy is actually performed using a hard
1276b5e5868SGarrett D'Amore  * link for efficiency.
1286b5e5868SGarrett D'Amore  */
1296b5e5868SGarrett D'Amore void
1306b5e5868SGarrett D'Amore copy_category(char *src)
1316b5e5868SGarrett D'Amore {
1326b5e5868SGarrett D'Amore 	char	srcpath[PATH_MAX];
1336b5e5868SGarrett D'Amore 	int	rv;
1346b5e5868SGarrett D'Amore 
1356b5e5868SGarrett D'Amore 	(void) snprintf(srcpath, sizeof (srcpath), "%s/%s/LCL_DATA",
1366b5e5868SGarrett D'Amore 	    src, category_name());
1376b5e5868SGarrett D'Amore 	rv = access(srcpath, R_OK);
1386b5e5868SGarrett D'Amore 	if ((rv != 0) && (strchr(srcpath, '/') == NULL)) {
1396b5e5868SGarrett D'Amore 		/* Maybe we should try the system locale */
1406b5e5868SGarrett D'Amore 		(void) snprintf(srcpath, sizeof (srcpath),
1416b5e5868SGarrett D'Amore 		    "/usr/lib/locale/%s/%s/LCL_DATA", src, category_name());
1426b5e5868SGarrett D'Amore 		rv = access(srcpath, R_OK);
1436b5e5868SGarrett D'Amore 	}
1446b5e5868SGarrett D'Amore 
1456b5e5868SGarrett D'Amore 	if (rv != 0) {
1466b5e5868SGarrett D'Amore 		errf(_("source locale data unavailable"), src);
1476b5e5868SGarrett D'Amore 		return;
1486b5e5868SGarrett D'Amore 	}
1496b5e5868SGarrett D'Amore 
1506b5e5868SGarrett D'Amore 	if (verbose > 1) {
1516b5e5868SGarrett D'Amore 		(void) printf(_("Copying category %s from %s: "),
1526b5e5868SGarrett D'Amore 		    category_name(), src);
1536b5e5868SGarrett D'Amore 		(void) fflush(stdout);
1546b5e5868SGarrett D'Amore 	}
1556b5e5868SGarrett D'Amore 
1566b5e5868SGarrett D'Amore 	/* make the parent directory */
1576b5e5868SGarrett D'Amore 	(void) mkdirp(dirname(category_file()), 0755);
1586b5e5868SGarrett D'Amore 
1596b5e5868SGarrett D'Amore 	if (link(srcpath, category_file()) != 0) {
1606b5e5868SGarrett D'Amore 		errf(_("unable to copy locale data: %s"), strerror(errno));
1616b5e5868SGarrett D'Amore 		return;
1626b5e5868SGarrett D'Amore 	}
1636b5e5868SGarrett D'Amore 	if (verbose > 1) {
1646b5e5868SGarrett D'Amore 		(void) printf(_("done.\n"));
1656b5e5868SGarrett D'Amore 	}
1666b5e5868SGarrett D'Amore }
1676b5e5868SGarrett D'Amore 
1686b5e5868SGarrett D'Amore int
1696b5e5868SGarrett D'Amore putl_category(const char *s, FILE *f)
1706b5e5868SGarrett D'Amore {
1716b5e5868SGarrett D'Amore 	if (s && fputs(s, f) == EOF) {
1726b5e5868SGarrett D'Amore 		(void) fclose(f);
1736b5e5868SGarrett D'Amore 		(void) unlink(category_file());
1746b5e5868SGarrett D'Amore 		errf(strerror(errno));
1756b5e5868SGarrett D'Amore 		return (EOF);
1766b5e5868SGarrett D'Amore 	}
1776b5e5868SGarrett D'Amore 	if (fputc('\n', f) == EOF) {
1786b5e5868SGarrett D'Amore 		(void) fclose(f);
1796b5e5868SGarrett D'Amore 		(void) unlink(category_file());
1806b5e5868SGarrett D'Amore 		errf(strerror(errno));
1816b5e5868SGarrett D'Amore 		return (EOF);
1826b5e5868SGarrett D'Amore 	}
1836b5e5868SGarrett D'Amore 	return (0);
1846b5e5868SGarrett D'Amore }
1856b5e5868SGarrett D'Amore 
1866b5e5868SGarrett D'Amore int
1876b5e5868SGarrett D'Amore wr_category(void *buf, size_t sz, FILE *f)
1886b5e5868SGarrett D'Amore {
1896b5e5868SGarrett D'Amore 	if (!sz) {
1906b5e5868SGarrett D'Amore 		return (0);
1916b5e5868SGarrett D'Amore 	}
1926b5e5868SGarrett D'Amore 	if (fwrite(buf, sz, 1, f) < 1) {
1936b5e5868SGarrett D'Amore 		(void) fclose(f);
1946b5e5868SGarrett D'Amore 		(void) unlink(category_file());
1956b5e5868SGarrett D'Amore 		errf(strerror(errno));
1966b5e5868SGarrett D'Amore 		return (EOF);
1976b5e5868SGarrett D'Amore 	}
1986b5e5868SGarrett D'Amore 	return (0);
1996b5e5868SGarrett D'Amore }
2006b5e5868SGarrett D'Amore 
2016b5e5868SGarrett D'Amore int yyparse(void);
2026b5e5868SGarrett D'Amore 
2036b5e5868SGarrett D'Amore static void
2046b5e5868SGarrett D'Amore usage(void)
2056b5e5868SGarrett D'Amore {
2066b5e5868SGarrett D'Amore 	(void) fprintf(stderr,
207*2da1cd3aSGarrett D'Amore 	    _("Usage: localedef [options] localename\n"));
208*2da1cd3aSGarrett D'Amore 	(void) fprintf(stderr, ("[options] are:\n"));
209*2da1cd3aSGarrett D'Amore 	(void) fprintf(stderr, ("  -c          : ignore warnings\n"));
210*2da1cd3aSGarrett D'Amore 	(void) fprintf(stderr, ("  -v          : verbose output\n"));
211*2da1cd3aSGarrett D'Amore 	(void) fprintf(stderr, ("  -U          : ignore undefined symbols\n"));
212*2da1cd3aSGarrett D'Amore 	(void) fprintf(stderr, ("  -f charmap  : use given charmap file\n"));
213*2da1cd3aSGarrett D'Amore 	(void) fprintf(stderr, ("  -u encoding : assume encoding\n"));
214*2da1cd3aSGarrett D'Amore 	(void) fprintf(stderr, ("  -w widths   : use screen widths file\n"));
215*2da1cd3aSGarrett D'Amore 	(void) fprintf(stderr, ("  -i locsrc   : source file for locale\n"));
2166b5e5868SGarrett D'Amore 	exit(4);
2176b5e5868SGarrett D'Amore }
2186b5e5868SGarrett D'Amore 
2196b5e5868SGarrett D'Amore int
2206b5e5868SGarrett D'Amore main(int argc, char **argv)
2216b5e5868SGarrett D'Amore {
2226b5e5868SGarrett D'Amore 	int c;
2236b5e5868SGarrett D'Amore 	char *lfname = NULL;
2246b5e5868SGarrett D'Amore 	char *cfname = NULL;
225*2da1cd3aSGarrett D'Amore 	char *wfname = NULL;
2266b5e5868SGarrett D'Amore 	DIR *dir;
2276b5e5868SGarrett D'Amore 
2286b5e5868SGarrett D'Amore 	init_charmap();
2296b5e5868SGarrett D'Amore 	init_collate();
2306b5e5868SGarrett D'Amore 	init_ctype();
2316b5e5868SGarrett D'Amore 	init_messages();
2326b5e5868SGarrett D'Amore 	init_monetary();
2336b5e5868SGarrett D'Amore 	init_numeric();
2346b5e5868SGarrett D'Amore 	init_time();
2356b5e5868SGarrett D'Amore 
2366b5e5868SGarrett D'Amore 	yydebug = 0;
2376b5e5868SGarrett D'Amore 
2386b5e5868SGarrett D'Amore 	(void) setlocale(LC_ALL, "");
2396b5e5868SGarrett D'Amore 	(void) textdomain(TEXT_DOMAIN);
2406b5e5868SGarrett D'Amore 
241*2da1cd3aSGarrett D'Amore 	while ((c = getopt(argc, argv, "w:i:cf:u:vU")) != -1) {
2426b5e5868SGarrett D'Amore 		switch (c) {
2436b5e5868SGarrett D'Amore 		case 'v':
2446b5e5868SGarrett D'Amore 			verbose++;
2456b5e5868SGarrett D'Amore 			break;
2466b5e5868SGarrett D'Amore 		case 'i':
2476b5e5868SGarrett D'Amore 			lfname = optarg;
2486b5e5868SGarrett D'Amore 			break;
2496b5e5868SGarrett D'Amore 		case 'u':
2506b5e5868SGarrett D'Amore 			set_wide_encoding(optarg);
2516b5e5868SGarrett D'Amore 			break;
2526b5e5868SGarrett D'Amore 		case 'f':
2536b5e5868SGarrett D'Amore 			cfname = optarg;
2546b5e5868SGarrett D'Amore 			break;
2556b5e5868SGarrett D'Amore 		case 'U':
2566b5e5868SGarrett D'Amore 			undefok++;
2576b5e5868SGarrett D'Amore 			break;
2586b5e5868SGarrett D'Amore 		case 'c':
2596b5e5868SGarrett D'Amore 			warnok++;
2606b5e5868SGarrett D'Amore 			break;
261*2da1cd3aSGarrett D'Amore 		case 'w':
262*2da1cd3aSGarrett D'Amore 			wfname = optarg;
263*2da1cd3aSGarrett D'Amore 			break;
2646b5e5868SGarrett D'Amore 		case '?':
2656b5e5868SGarrett D'Amore 			usage();
2666b5e5868SGarrett D'Amore 			break;
2676b5e5868SGarrett D'Amore 		}
2686b5e5868SGarrett D'Amore 	}
2696b5e5868SGarrett D'Amore 
2706b5e5868SGarrett D'Amore 	if ((argc - 1) != (optind)) {
2716b5e5868SGarrett D'Amore 		usage();
2726b5e5868SGarrett D'Amore 	}
2736b5e5868SGarrett D'Amore 	locname = argv[argc - 1];
2746b5e5868SGarrett D'Amore 	if (verbose) {
2756b5e5868SGarrett D'Amore 		(void) printf(_("Processing locale %s.\n"), locname);
2766b5e5868SGarrett D'Amore 	}
2776b5e5868SGarrett D'Amore 
2786b5e5868SGarrett D'Amore 	if (cfname) {
2796b5e5868SGarrett D'Amore 		if (verbose)
2806b5e5868SGarrett D'Amore 			(void) printf(_("Loading charmap %s.\n"), cfname);
2816b5e5868SGarrett D'Amore 		reset_scanner(cfname);
2826b5e5868SGarrett D'Amore 		(void) yyparse();
2836b5e5868SGarrett D'Amore 	}
2846b5e5868SGarrett D'Amore 
285*2da1cd3aSGarrett D'Amore 	if (wfname) {
286*2da1cd3aSGarrett D'Amore 		if (verbose)
287*2da1cd3aSGarrett D'Amore 			(void) printf(_("Loading widths %s.\n"), wfname);
288*2da1cd3aSGarrett D'Amore 		reset_scanner(wfname);
289*2da1cd3aSGarrett D'Amore 		(void) yyparse();
290*2da1cd3aSGarrett D'Amore 	}
291*2da1cd3aSGarrett D'Amore 
2926b5e5868SGarrett D'Amore 	if (verbose) {
2936b5e5868SGarrett D'Amore 		(void) printf(_("Loading POSIX portable characters.\n"));
2946b5e5868SGarrett D'Amore 	}
2956b5e5868SGarrett D'Amore 	add_charmap_posix();
2966b5e5868SGarrett D'Amore 
2976b5e5868SGarrett D'Amore 	if (lfname) {
2986b5e5868SGarrett D'Amore 		reset_scanner(lfname);
2996b5e5868SGarrett D'Amore 	} else {
3006b5e5868SGarrett D'Amore 		reset_scanner(NULL);
3016b5e5868SGarrett D'Amore 	}
3026b5e5868SGarrett D'Amore 
3036b5e5868SGarrett D'Amore 	/* make the directory for the locale if not already present */
3046b5e5868SGarrett D'Amore 	while ((dir = opendir(locname)) == NULL) {
3056b5e5868SGarrett D'Amore 		if ((errno != ENOENT) ||
3066b5e5868SGarrett D'Amore 		    (mkdir(locname, 0755) <  0)) {
3076b5e5868SGarrett D'Amore 			errf(strerror(errno));
3086b5e5868SGarrett D'Amore 		}
3096b5e5868SGarrett D'Amore 	}
3106b5e5868SGarrett D'Amore 	(void) closedir(dir);
3116b5e5868SGarrett D'Amore 
3126b5e5868SGarrett D'Amore 	(void) mkdirp(dirname(category_file()), 0755);
3136b5e5868SGarrett D'Amore 
3146b5e5868SGarrett D'Amore 	(void) yyparse();
3156b5e5868SGarrett D'Amore 	if (verbose) {
3166b5e5868SGarrett D'Amore 		(void) printf(_("All done.\n"));
3176b5e5868SGarrett D'Amore 	}
3186b5e5868SGarrett D'Amore 	return (warnings ? 1 : 0);
3196b5e5868SGarrett D'Amore }
320