1 /* 2 * This file and its contents are supplied under the terms of the 3 * Common Development and Distribution License ("CDDL"), version 1.0. 4 * You may only use this file in accordance with the terms of version 5 * 1.0 of the CDDL. 6 * 7 * A full copy of the text of the CDDL should have accompanied this 8 * source. A copy of the CDDL is also available via the Internet at 9 * http://www.illumos.org/license/CDDL. 10 */ 11 12 /* 13 * Copyright 2010 Nexenta Systems, Inc. All rights reserved. 14 * Copyright 2013 DEY Storage Systems, Inc. 15 */ 16 17 /* 18 * POSIX localedef. 19 */ 20 21 #include <stdio.h> 22 #include <stdlib.h> 23 #include <errno.h> 24 #include <sys/types.h> 25 #include <sys/stat.h> 26 #include <string.h> 27 #include <unistd.h> 28 #include <libgen.h> 29 #include <stddef.h> 30 #include <unistd.h> 31 #include <limits.h> 32 #include <locale.h> 33 #include <dirent.h> 34 #include "localedef.h" 35 #include "parser.tab.h" 36 37 #ifndef TEXT_DOMAIN 38 #define TEXT_DOMAIN "SYS_TEST" 39 #endif 40 41 int verbose = 0; 42 int undefok = 0; 43 int warnok = 0; 44 static char *locname = NULL; 45 static char locpath[PATH_MAX]; 46 47 const char * 48 category_name(void) 49 { 50 switch (get_category()) { 51 case T_CHARMAP: 52 return ("CHARMAP"); 53 case T_WIDTH: 54 return ("WIDTH"); 55 case T_COLLATE: 56 return ("LC_COLLATE"); 57 case T_CTYPE: 58 return ("LC_CTYPE"); 59 case T_MESSAGES: 60 return ("LC_MESSAGES"); 61 case T_MONETARY: 62 return ("LC_MONETARY"); 63 case T_NUMERIC: 64 return ("LC_NUMERIC"); 65 case T_TIME: 66 return ("LC_TIME"); 67 default: 68 INTERR; 69 return (NULL); 70 } 71 } 72 73 static char * 74 category_file(void) 75 { 76 (void) snprintf(locpath, sizeof (locpath), "%s/%s/LCL_DATA", 77 locname, category_name()); 78 return (locpath); 79 } 80 81 FILE * 82 open_category(void) 83 { 84 FILE *file; 85 86 if (verbose) { 87 (void) printf(_("Writing category %s: "), category_name()); 88 (void) fflush(stdout); 89 } 90 91 /* make the parent directory */ 92 (void) mkdirp(dirname(category_file()), 0755); 93 94 /* 95 * note that we have to regenerate the file name, as dirname 96 * clobbered it. 97 */ 98 file = fopen(category_file(), "w"); 99 if (file == NULL) { 100 errf(strerror(errno)); 101 return (NULL); 102 } 103 return (file); 104 } 105 106 void 107 close_category(FILE *f) 108 { 109 if (fchmod(fileno(f), 0644) < 0) { 110 (void) fclose(f); 111 (void) unlink(category_file()); 112 errf(strerror(errno)); 113 } 114 if (fclose(f) < 0) { 115 (void) unlink(category_file()); 116 errf(strerror(errno)); 117 } 118 if (verbose) { 119 (void) fprintf(stdout, _("done.\n")); 120 (void) fflush(stdout); 121 } 122 } 123 124 /* 125 * This function is used when copying the category from another 126 * locale. Note that the copy is actually performed using a hard 127 * link for efficiency. 128 */ 129 void 130 copy_category(char *src) 131 { 132 char srcpath[PATH_MAX]; 133 int rv; 134 135 (void) snprintf(srcpath, sizeof (srcpath), "%s/%s/LCL_DATA", 136 src, category_name()); 137 rv = access(srcpath, R_OK); 138 if ((rv != 0) && (strchr(srcpath, '/') == NULL)) { 139 /* Maybe we should try the system locale */ 140 (void) snprintf(srcpath, sizeof (srcpath), 141 "/usr/lib/locale/%s/%s/LCL_DATA", src, category_name()); 142 rv = access(srcpath, R_OK); 143 } 144 145 if (rv != 0) { 146 errf(_("source locale data unavailable"), src); 147 return; 148 } 149 150 if (verbose > 1) { 151 (void) printf(_("Copying category %s from %s: "), 152 category_name(), src); 153 (void) fflush(stdout); 154 } 155 156 /* make the parent directory */ 157 (void) mkdirp(dirname(category_file()), 0755); 158 159 if (link(srcpath, category_file()) != 0) { 160 errf(_("unable to copy locale data: %s"), strerror(errno)); 161 return; 162 } 163 if (verbose > 1) { 164 (void) printf(_("done.\n")); 165 } 166 } 167 168 int 169 putl_category(const char *s, FILE *f) 170 { 171 if (s && fputs(s, f) == EOF) { 172 (void) fclose(f); 173 (void) unlink(category_file()); 174 errf(strerror(errno)); 175 return (EOF); 176 } 177 if (fputc('\n', f) == EOF) { 178 (void) fclose(f); 179 (void) unlink(category_file()); 180 errf(strerror(errno)); 181 return (EOF); 182 } 183 return (0); 184 } 185 186 int 187 wr_category(void *buf, size_t sz, FILE *f) 188 { 189 if (!sz) { 190 return (0); 191 } 192 if (fwrite(buf, sz, 1, f) < 1) { 193 (void) fclose(f); 194 (void) unlink(category_file()); 195 errf(strerror(errno)); 196 return (EOF); 197 } 198 return (0); 199 } 200 201 int yyparse(void); 202 203 static void 204 usage(void) 205 { 206 (void) fprintf(stderr, 207 _("Usage: localedef [options] localename\n")); 208 (void) fprintf(stderr, ("[options] are:\n")); 209 (void) fprintf(stderr, (" -c : ignore warnings\n")); 210 (void) fprintf(stderr, (" -v : verbose output\n")); 211 (void) fprintf(stderr, (" -U : ignore undefined symbols\n")); 212 (void) fprintf(stderr, (" -f charmap : use given charmap file\n")); 213 (void) fprintf(stderr, (" -u encoding : assume encoding\n")); 214 (void) fprintf(stderr, (" -w widths : use screen widths file\n")); 215 (void) fprintf(stderr, (" -i locsrc : source file for locale\n")); 216 exit(4); 217 } 218 219 int 220 main(int argc, char **argv) 221 { 222 int c; 223 char *lfname = NULL; 224 char *cfname = NULL; 225 char *wfname = NULL; 226 DIR *dir; 227 228 init_charmap(); 229 init_collate(); 230 init_ctype(); 231 init_messages(); 232 init_monetary(); 233 init_numeric(); 234 init_time(); 235 236 yydebug = 0; 237 238 (void) setlocale(LC_ALL, ""); 239 (void) textdomain(TEXT_DOMAIN); 240 241 while ((c = getopt(argc, argv, "w:i:cf:u:vU")) != -1) { 242 switch (c) { 243 case 'v': 244 verbose++; 245 break; 246 case 'i': 247 lfname = optarg; 248 break; 249 case 'u': 250 set_wide_encoding(optarg); 251 break; 252 case 'f': 253 cfname = optarg; 254 break; 255 case 'U': 256 undefok++; 257 break; 258 case 'c': 259 warnok++; 260 break; 261 case 'w': 262 wfname = optarg; 263 break; 264 case '?': 265 usage(); 266 break; 267 } 268 } 269 270 if ((argc - 1) != (optind)) { 271 usage(); 272 } 273 locname = argv[argc - 1]; 274 if (verbose) { 275 (void) printf(_("Processing locale %s.\n"), locname); 276 } 277 278 if (cfname) { 279 if (verbose) 280 (void) printf(_("Loading charmap %s.\n"), cfname); 281 reset_scanner(cfname); 282 (void) yyparse(); 283 } 284 285 if (wfname) { 286 if (verbose) 287 (void) printf(_("Loading widths %s.\n"), wfname); 288 reset_scanner(wfname); 289 (void) yyparse(); 290 } 291 292 if (verbose) { 293 (void) printf(_("Loading POSIX portable characters.\n")); 294 } 295 add_charmap_posix(); 296 297 if (lfname) { 298 reset_scanner(lfname); 299 } else { 300 reset_scanner(NULL); 301 } 302 303 /* make the directory for the locale if not already present */ 304 while ((dir = opendir(locname)) == NULL) { 305 if ((errno != ENOENT) || 306 (mkdir(locname, 0755) < 0)) { 307 errf(strerror(errno)); 308 } 309 } 310 (void) closedir(dir); 311 312 (void) mkdirp(dirname(category_file()), 0755); 313 314 (void) yyparse(); 315 if (verbose) { 316 (void) printf(_("All done.\n")); 317 } 318 return (warnings ? 1 : 0); 319 } 320