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