17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 77c478bd9Sstevel@tonic-gate * with the License. 87c478bd9Sstevel@tonic-gate * 97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 127c478bd9Sstevel@tonic-gate * and limitations under the License. 137c478bd9Sstevel@tonic-gate * 147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 197c478bd9Sstevel@tonic-gate * 207c478bd9Sstevel@tonic-gate * CDDL HEADER END 217c478bd9Sstevel@tonic-gate */ 227c478bd9Sstevel@tonic-gate /* 237c478bd9Sstevel@tonic-gate * Copyright 1995 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate /* Copyright (c) 1984 AT&T */ 287c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 297c478bd9Sstevel@tonic-gate 307c478bd9Sstevel@tonic-gate 317c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 327c478bd9Sstevel@tonic-gate 33*5d54f3d8Smuffin #include <sys/fcntl.h> 347c478bd9Sstevel@tonic-gate #include <locale.h> 357c478bd9Sstevel@tonic-gate #include <stdlib.h> 367c478bd9Sstevel@tonic-gate #include "codeset.h" 377c478bd9Sstevel@tonic-gate #include <ctype.h> 387c478bd9Sstevel@tonic-gate #include <string.h> 397c478bd9Sstevel@tonic-gate #include <memory.h> 407c478bd9Sstevel@tonic-gate #include <malloc.h> 417c478bd9Sstevel@tonic-gate #include <sys/param.h> /* for MAXPATHLEN */ 427c478bd9Sstevel@tonic-gate #include <sys/stat.h> 437c478bd9Sstevel@tonic-gate #include <errno.h> 447c478bd9Sstevel@tonic-gate #include <limits.h> 457c478bd9Sstevel@tonic-gate 467c478bd9Sstevel@tonic-gate #define TRAILER ".ci" 477c478bd9Sstevel@tonic-gate 487c478bd9Sstevel@tonic-gate 497c478bd9Sstevel@tonic-gate struct _code_set_info _code_set_info = { 507c478bd9Sstevel@tonic-gate NULL, 517c478bd9Sstevel@tonic-gate CODESET_NONE, /* no codeset */ 527c478bd9Sstevel@tonic-gate NULL, /* not defined */ 537c478bd9Sstevel@tonic-gate 0, 547c478bd9Sstevel@tonic-gate }; 557c478bd9Sstevel@tonic-gate 567c478bd9Sstevel@tonic-gate /* tolower() and toupper() conversion table 577c478bd9Sstevel@tonic-gate * is hidden here to avoid being placed in the 587c478bd9Sstevel@tonic-gate * extern .sa file in the dynamic version of libc 597c478bd9Sstevel@tonic-gate */ 607c478bd9Sstevel@tonic-gate 617c478bd9Sstevel@tonic-gate char _ctype_ul[] = { 0, 627c478bd9Sstevel@tonic-gate 637c478bd9Sstevel@tonic-gate /* 0 1 2 3 4 5 6 7 */ 647c478bd9Sstevel@tonic-gate '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007', 657c478bd9Sstevel@tonic-gate '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017', 667c478bd9Sstevel@tonic-gate '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027', 677c478bd9Sstevel@tonic-gate '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037', 687c478bd9Sstevel@tonic-gate ' ', '!', '"', '#', '$', '%', '&', '\'', 697c478bd9Sstevel@tonic-gate '(', ')', '*', '+', ',', '-', '.', '/', 707c478bd9Sstevel@tonic-gate '0', '1', '2', '3', '4', '5', '6', '7', 717c478bd9Sstevel@tonic-gate '8', '9', ':', ';', '<', '=', '>', '?', 727c478bd9Sstevel@tonic-gate '@', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 737c478bd9Sstevel@tonic-gate 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 747c478bd9Sstevel@tonic-gate 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 757c478bd9Sstevel@tonic-gate 'x', 'y', 'z', '[', '\\', ']', '^', '_', 767c478bd9Sstevel@tonic-gate '`', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 777c478bd9Sstevel@tonic-gate 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 787c478bd9Sstevel@tonic-gate 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 797c478bd9Sstevel@tonic-gate 'X', 'Y', 'Z', '{', '|', '}', '~', '\177', 807c478bd9Sstevel@tonic-gate 0, 0, 0, 0, 0, 0, 0, 0, 817c478bd9Sstevel@tonic-gate 0, 0, 0, 0, 0, 0, 0, 0, 827c478bd9Sstevel@tonic-gate 0, 0, 0, 0, 0, 0, 0, 0, 837c478bd9Sstevel@tonic-gate 0, 0, 0, 0, 0, 0, 0, 0, 847c478bd9Sstevel@tonic-gate 0, 0, 0, 0, 0, 0, 0, 0, 857c478bd9Sstevel@tonic-gate 0, 0, 0, 0, 0, 0, 0, 0, 867c478bd9Sstevel@tonic-gate 0, 0, 0, 0, 0, 0, 0, 0, 877c478bd9Sstevel@tonic-gate 0, 0, 0, 0, 0, 0, 0, 0, 887c478bd9Sstevel@tonic-gate 0, 0, 0, 0, 0, 0, 0, 0, 897c478bd9Sstevel@tonic-gate 0, 0, 0, 0, 0, 0, 0, 0, 907c478bd9Sstevel@tonic-gate 0, 0, 0, 0, 0, 0, 0, 0, 917c478bd9Sstevel@tonic-gate 0, 0, 0, 0, 0, 0, 0, 0, 927c478bd9Sstevel@tonic-gate 0, 0, 0, 0, 0, 0, 0, 0, 937c478bd9Sstevel@tonic-gate 0, 0, 0, 0, 0, 0, 0, 0, 947c478bd9Sstevel@tonic-gate 0, 0, 0, 0, 0, 0, 0, 0, 957c478bd9Sstevel@tonic-gate 0, 0, 0, 0, 0, 0, 0, 0, 967c478bd9Sstevel@tonic-gate }; 977c478bd9Sstevel@tonic-gate 987c478bd9Sstevel@tonic-gate /* following layout is: 997c478bd9Sstevel@tonic-gate * LC_NUMERIC LC_TIME LC_MONETARY LANGINFO LC_COLLATE LC_MESSAGES 1007c478bd9Sstevel@tonic-gate */ 1017c478bd9Sstevel@tonic-gate char _locales[MAXLOCALE - 1][MAXLOCALENAME + 1] ; 1027c478bd9Sstevel@tonic-gate 1037c478bd9Sstevel@tonic-gate char _my_time[MAXLOCALENAME + 1]; 1047c478bd9Sstevel@tonic-gate 1057c478bd9Sstevel@tonic-gate /* The array Default holds the systems notion of default locale. It is normally 1067c478bd9Sstevel@tonic-gate * found in {LOCALE}/.default and moved to here. Note there is only one 1077c478bd9Sstevel@tonic-gate * default locale spanning all categories 1087c478bd9Sstevel@tonic-gate */ 1097c478bd9Sstevel@tonic-gate 1107c478bd9Sstevel@tonic-gate static char Default[MAXLOCALENAME+1]; 1117c478bd9Sstevel@tonic-gate 1127c478bd9Sstevel@tonic-gate struct langinfo _langinfo; 1137c478bd9Sstevel@tonic-gate struct dtconv *_dtconv = NULL; 1147c478bd9Sstevel@tonic-gate 1157c478bd9Sstevel@tonic-gate static char *realmonths = NULL; 1167c478bd9Sstevel@tonic-gate static char *realdays = NULL; 1177c478bd9Sstevel@tonic-gate static char *realfmts = NULL; 1187c478bd9Sstevel@tonic-gate static short lang_succ = ON; /* setlocale success */ 1197c478bd9Sstevel@tonic-gate 1207c478bd9Sstevel@tonic-gate 1217c478bd9Sstevel@tonic-gate /* Set the values here to guarantee stdio use of the 1227c478bd9Sstevel@tonic-gate decimal point 1237c478bd9Sstevel@tonic-gate */ 1247c478bd9Sstevel@tonic-gate static struct lconv lconv_arr = { 1257c478bd9Sstevel@tonic-gate ".", "", "", "", "", 1267c478bd9Sstevel@tonic-gate "", "", "", "", "", 1277c478bd9Sstevel@tonic-gate CHAR_MAX, CHAR_MAX, CHAR_MAX, CHAR_MAX, 1287c478bd9Sstevel@tonic-gate CHAR_MAX, CHAR_MAX, CHAR_MAX, CHAR_MAX 1297c478bd9Sstevel@tonic-gate }; 1307c478bd9Sstevel@tonic-gate 1317c478bd9Sstevel@tonic-gate /* lconv is externally defined by ANSI C */ 1327c478bd9Sstevel@tonic-gate struct lconv *lconv = &lconv_arr; 1337c478bd9Sstevel@tonic-gate 1347c478bd9Sstevel@tonic-gate static char *lconv_numeric_str = NULL; 1357c478bd9Sstevel@tonic-gate static char *lconv_monetary_str = NULL; 1367c478bd9Sstevel@tonic-gate 137*5d54f3d8Smuffin int openlocale(char *, int, char *, char *); 138*5d54f3d8Smuffin int getlocale_ctype(char *, char *, char *); 139*5d54f3d8Smuffin char *getlocale_numeric(char *, struct lconv *, char *); 140*5d54f3d8Smuffin void init_statics(void); 141*5d54f3d8Smuffin static char *getlocale_monetary(char *, struct lconv *, char *); 142*5d54f3d8Smuffin static char *getstr(char *, char **); 143*5d54f3d8Smuffin static char *getgrouping(char *, char **); 144*5d54f3d8Smuffin static char *getnum(char *, char *); 145*5d54f3d8Smuffin static char *getbool(char *, char *); 146*5d54f3d8Smuffin static void set_default(void); 1477c478bd9Sstevel@tonic-gate 1487c478bd9Sstevel@tonic-gate char * 149*5d54f3d8Smuffin setlocale(int category, char *locale) 1507c478bd9Sstevel@tonic-gate { 1517c478bd9Sstevel@tonic-gate static char buf[MAXLOCALE*(MAXLOCALENAME + 1) + 1]; 1527c478bd9Sstevel@tonic-gate /* buffer for current LC_ALL value */ 1537c478bd9Sstevel@tonic-gate int nonuniform; 1547c478bd9Sstevel@tonic-gate short ret; 1557c478bd9Sstevel@tonic-gate char my_ctype[CTYPE_SIZE]; /* local copy */ 1567c478bd9Sstevel@tonic-gate struct lconv my_lconv; /* local copy */ 1577c478bd9Sstevel@tonic-gate char *my_lconv_numeric_str; 1587c478bd9Sstevel@tonic-gate char *my_lconv_monetary_str; 159*5d54f3d8Smuffin int i; 160*5d54f3d8Smuffin char *p; 1617c478bd9Sstevel@tonic-gate 1627c478bd9Sstevel@tonic-gate 1637c478bd9Sstevel@tonic-gate /* initialize my_lconv to lconv */ 1647c478bd9Sstevel@tonic-gate memcpy(&my_lconv, lconv, sizeof(my_lconv)); 1657c478bd9Sstevel@tonic-gate 1667c478bd9Sstevel@tonic-gate /* 1677c478bd9Sstevel@tonic-gate * Following code is to avoid static initialisation of 1687c478bd9Sstevel@tonic-gate * strings which would otherwise blow up "xstr". 1697c478bd9Sstevel@tonic-gate */ 1707c478bd9Sstevel@tonic-gate if (_locales[0][0] == '\0') 1717c478bd9Sstevel@tonic-gate init_statics(); 1727c478bd9Sstevel@tonic-gate 1737c478bd9Sstevel@tonic-gate if (locale == NULL) { 1747c478bd9Sstevel@tonic-gate if (category == LC_ALL) { 1757c478bd9Sstevel@tonic-gate /* 1767c478bd9Sstevel@tonic-gate * Assume all locales are set to the same value. Then 1777c478bd9Sstevel@tonic-gate * scan through the locales to see if any are 1787c478bd9Sstevel@tonic-gate * different. If they are the same, return the common 1797c478bd9Sstevel@tonic-gate * value; otherwise, construct a "composite" value. 1807c478bd9Sstevel@tonic-gate */ 1817c478bd9Sstevel@tonic-gate nonuniform = 0; /* assume all locales set the same */ 1827c478bd9Sstevel@tonic-gate for (i = 0; i < MAXLOCALE - 2; i++) { 1837c478bd9Sstevel@tonic-gate if (strcmp(_locales[i], _locales[i + 1]) != 0) { 1847c478bd9Sstevel@tonic-gate nonuniform = 1; 1857c478bd9Sstevel@tonic-gate break; 1867c478bd9Sstevel@tonic-gate } 1877c478bd9Sstevel@tonic-gate } 1887c478bd9Sstevel@tonic-gate if (nonuniform) { 1897c478bd9Sstevel@tonic-gate /* 1907c478bd9Sstevel@tonic-gate * They're not all the same. Construct a list 1917c478bd9Sstevel@tonic-gate * of all the locale values, in order, 1927c478bd9Sstevel@tonic-gate * separated by slashes. Return that value. 1937c478bd9Sstevel@tonic-gate */ 1947c478bd9Sstevel@tonic-gate (void) strcpy(buf, _locales[0]); 1957c478bd9Sstevel@tonic-gate for (i = 1; i < MAXLOCALE - 1; i++) { 1967c478bd9Sstevel@tonic-gate (void) strcat(buf, "/"); 1977c478bd9Sstevel@tonic-gate (void) strcat(buf, _locales[i]); 1987c478bd9Sstevel@tonic-gate } 1997c478bd9Sstevel@tonic-gate return (buf); 2007c478bd9Sstevel@tonic-gate } else { 2017c478bd9Sstevel@tonic-gate /* 2027c478bd9Sstevel@tonic-gate * They're all the same; any one you return is 2037c478bd9Sstevel@tonic-gate * OK. 2047c478bd9Sstevel@tonic-gate */ 2057c478bd9Sstevel@tonic-gate return (_locales[0]); 2067c478bd9Sstevel@tonic-gate } 2077c478bd9Sstevel@tonic-gate } else 2087c478bd9Sstevel@tonic-gate return (_locales[category - 1]); 2097c478bd9Sstevel@tonic-gate } 2107c478bd9Sstevel@tonic-gate 2117c478bd9Sstevel@tonic-gate switch (category) { 2127c478bd9Sstevel@tonic-gate 2137c478bd9Sstevel@tonic-gate case LC_ALL: 2147c478bd9Sstevel@tonic-gate if (strchr(locale, '/') != NULL) { 2157c478bd9Sstevel@tonic-gate /* 2167c478bd9Sstevel@tonic-gate * Composite value; extract each category. 2177c478bd9Sstevel@tonic-gate */ 2187c478bd9Sstevel@tonic-gate if (strlen(locale) > sizeof buf - 1) 2197c478bd9Sstevel@tonic-gate return (NULL); /* too long */ 2207c478bd9Sstevel@tonic-gate (void) strcpy(buf, locale); 2217c478bd9Sstevel@tonic-gate p = buf; 2227c478bd9Sstevel@tonic-gate 2237c478bd9Sstevel@tonic-gate /* 2247c478bd9Sstevel@tonic-gate * LC_CTYPE and LC_NUMERIC are set here. 2257c478bd9Sstevel@tonic-gate * Others locales won't be set here, 2267c478bd9Sstevel@tonic-gate * they will be just marked. 2277c478bd9Sstevel@tonic-gate */ 2287c478bd9Sstevel@tonic-gate for (i = 0; i < MAXLOCALE - 1; i++) { 2297c478bd9Sstevel@tonic-gate p = strtok(p, "/"); 2307c478bd9Sstevel@tonic-gate if (p == NULL) 2317c478bd9Sstevel@tonic-gate return (NULL); /* missing item */ 2327c478bd9Sstevel@tonic-gate switch (i) { 2337c478bd9Sstevel@tonic-gate 2347c478bd9Sstevel@tonic-gate case LC_CTYPE - 1: 2357c478bd9Sstevel@tonic-gate if (setlocale(LC_CTYPE,p) == NULL) 236*5d54f3d8Smuffin return (NULL); 2377c478bd9Sstevel@tonic-gate break; 2387c478bd9Sstevel@tonic-gate case LC_NUMERIC - 1: 2397c478bd9Sstevel@tonic-gate if (setlocale(LC_NUMERIC,p) == NULL) 240*5d54f3d8Smuffin return (NULL); 2417c478bd9Sstevel@tonic-gate break; 2427c478bd9Sstevel@tonic-gate case LC_TIME - 1: 2437c478bd9Sstevel@tonic-gate if (setlocale(LC_TIME,p) == NULL) 244*5d54f3d8Smuffin return (NULL); 2457c478bd9Sstevel@tonic-gate break; 2467c478bd9Sstevel@tonic-gate case LC_MONETARY - 1: 2477c478bd9Sstevel@tonic-gate if (setlocale(LC_MONETARY,p) == NULL) 248*5d54f3d8Smuffin return (NULL); 2497c478bd9Sstevel@tonic-gate break; 2507c478bd9Sstevel@tonic-gate case LANGINFO - 1: 2517c478bd9Sstevel@tonic-gate if (setlocale(LANGINFO,p) == NULL) 252*5d54f3d8Smuffin return (NULL); 2537c478bd9Sstevel@tonic-gate break; 2547c478bd9Sstevel@tonic-gate case LC_COLLATE - 1: 2557c478bd9Sstevel@tonic-gate if (setlocale(LC_COLLATE,p) == NULL) 256*5d54f3d8Smuffin return (NULL); 2577c478bd9Sstevel@tonic-gate break; 2587c478bd9Sstevel@tonic-gate case LC_MESSAGES - 1: 2597c478bd9Sstevel@tonic-gate if (setlocale(LC_MESSAGES,p) == NULL) 260*5d54f3d8Smuffin return (NULL); 2617c478bd9Sstevel@tonic-gate break; 2627c478bd9Sstevel@tonic-gate } 2637c478bd9Sstevel@tonic-gate p = NULL; 2647c478bd9Sstevel@tonic-gate } 2657c478bd9Sstevel@tonic-gate if (strtok((char *)NULL, "/") != NULL) 2667c478bd9Sstevel@tonic-gate return (NULL); /* extra stuff at end */ 2677c478bd9Sstevel@tonic-gate } 2687c478bd9Sstevel@tonic-gate 2697c478bd9Sstevel@tonic-gate /* If category = LC_ALL, Drop through to test each individual 2707c478bd9Sstevel@tonic-gate * category, one at a time. Note default rules where env vars 2717c478bd9Sstevel@tonic-gate * are not set 2727c478bd9Sstevel@tonic-gate */ 2737c478bd9Sstevel@tonic-gate 2747c478bd9Sstevel@tonic-gate case LC_CTYPE: 2757c478bd9Sstevel@tonic-gate if ((ret = getlocale_ctype(locale , my_ctype, 2767c478bd9Sstevel@tonic-gate _locales[LC_CTYPE - 1])) < 0) 2777c478bd9Sstevel@tonic-gate return (NULL); 2787c478bd9Sstevel@tonic-gate if (ret) { 2797c478bd9Sstevel@tonic-gate (void) memcpy(_ctype_, my_ctype, CTYPE_SIZE/2); 2807c478bd9Sstevel@tonic-gate (void) memcpy(_ctype_ul, my_ctype+(CTYPE_SIZE/2), CTYPE_SIZE/2); 2817c478bd9Sstevel@tonic-gate } 2827c478bd9Sstevel@tonic-gate if (category != LC_ALL) 2837c478bd9Sstevel@tonic-gate break; 2847c478bd9Sstevel@tonic-gate 2857c478bd9Sstevel@tonic-gate case LC_NUMERIC: 2867c478bd9Sstevel@tonic-gate if ((my_lconv_numeric_str = 2877c478bd9Sstevel@tonic-gate getlocale_numeric(locale, &my_lconv, 2887c478bd9Sstevel@tonic-gate _locales[LC_NUMERIC - 1])) == NULL) 2897c478bd9Sstevel@tonic-gate return (NULL); 2907c478bd9Sstevel@tonic-gate if (*my_lconv_numeric_str) { 2917c478bd9Sstevel@tonic-gate if (lconv_numeric_str != NULL) 2927c478bd9Sstevel@tonic-gate free((malloc_t)lconv_numeric_str); 2937c478bd9Sstevel@tonic-gate lconv_numeric_str = my_lconv_numeric_str; 2947c478bd9Sstevel@tonic-gate memcpy(lconv, my_lconv, sizeof(my_lconv)); 2957c478bd9Sstevel@tonic-gate } 2967c478bd9Sstevel@tonic-gate if (category != LC_ALL) 2977c478bd9Sstevel@tonic-gate break; 2987c478bd9Sstevel@tonic-gate 2997c478bd9Sstevel@tonic-gate case LC_TIME: 3007c478bd9Sstevel@tonic-gate if ((ret = openlocale("LC_TIME", LC_TIME, locale, 3017c478bd9Sstevel@tonic-gate _locales[LC_TIME -1])) < 0) 3027c478bd9Sstevel@tonic-gate return (NULL); 3037c478bd9Sstevel@tonic-gate if (ret) 3047c478bd9Sstevel@tonic-gate (void) close(ret); 3057c478bd9Sstevel@tonic-gate if (category != LC_ALL) 3067c478bd9Sstevel@tonic-gate break; 3077c478bd9Sstevel@tonic-gate 3087c478bd9Sstevel@tonic-gate case LC_MONETARY: 3097c478bd9Sstevel@tonic-gate if ((my_lconv_monetary_str = 3107c478bd9Sstevel@tonic-gate getlocale_monetary(locale, &my_lconv, 3117c478bd9Sstevel@tonic-gate _locales[LC_MONETARY - 1])) == NULL) 3127c478bd9Sstevel@tonic-gate return (NULL); 3137c478bd9Sstevel@tonic-gate if (*my_lconv_monetary_str) { 3147c478bd9Sstevel@tonic-gate if (lconv_monetary_str != NULL) 3157c478bd9Sstevel@tonic-gate free((malloc_t)lconv_monetary_str); 3167c478bd9Sstevel@tonic-gate lconv_monetary_str = my_lconv_monetary_str; 3177c478bd9Sstevel@tonic-gate memcpy(lconv, &my_lconv, sizeof(my_lconv)); 3187c478bd9Sstevel@tonic-gate } 3197c478bd9Sstevel@tonic-gate if (category != LC_ALL) 3207c478bd9Sstevel@tonic-gate break; 3217c478bd9Sstevel@tonic-gate 3227c478bd9Sstevel@tonic-gate case LANGINFO: 3237c478bd9Sstevel@tonic-gate if ((ret = openlocale("LANGINFO", LANGINFO, locale, 3247c478bd9Sstevel@tonic-gate _locales[LANGINFO - 1])) < 0) { 3257c478bd9Sstevel@tonic-gate lang_succ = OFF; 3267c478bd9Sstevel@tonic-gate return (NULL); 3277c478bd9Sstevel@tonic-gate } 3287c478bd9Sstevel@tonic-gate if (ret) { 3297c478bd9Sstevel@tonic-gate lang_succ = OFF; 3307c478bd9Sstevel@tonic-gate (void) close(ret); 3317c478bd9Sstevel@tonic-gate } 3327c478bd9Sstevel@tonic-gate if (category != LC_ALL) 3337c478bd9Sstevel@tonic-gate break; 3347c478bd9Sstevel@tonic-gate 3357c478bd9Sstevel@tonic-gate case LC_COLLATE: 3367c478bd9Sstevel@tonic-gate if ((ret = openlocale("LC_COLLATE", LC_COLLATE, locale, 3377c478bd9Sstevel@tonic-gate _locales[LC_COLLATE - 1])) < 0) 3387c478bd9Sstevel@tonic-gate return (NULL); 3397c478bd9Sstevel@tonic-gate if (ret) { 3407c478bd9Sstevel@tonic-gate (void) close(ret); 3417c478bd9Sstevel@tonic-gate } 3427c478bd9Sstevel@tonic-gate if (category != LC_ALL) 3437c478bd9Sstevel@tonic-gate break; 3447c478bd9Sstevel@tonic-gate 3457c478bd9Sstevel@tonic-gate case LC_MESSAGES: 3467c478bd9Sstevel@tonic-gate if ((ret = openlocale("LC_MESSAGES", LC_MESSAGES, locale, 3477c478bd9Sstevel@tonic-gate _locales[LC_MESSAGES - 1])) < 0) 3487c478bd9Sstevel@tonic-gate return (NULL); 3497c478bd9Sstevel@tonic-gate if (ret) { 3507c478bd9Sstevel@tonic-gate (void) close(ret); 3517c478bd9Sstevel@tonic-gate } 3527c478bd9Sstevel@tonic-gate } 3537c478bd9Sstevel@tonic-gate return (setlocale(category, (char *)NULL)); 3547c478bd9Sstevel@tonic-gate } 3557c478bd9Sstevel@tonic-gate 3567c478bd9Sstevel@tonic-gate int 357*5d54f3d8Smuffin getlocale_ctype(char *locale, char *ctypep, char *newlocale) 3587c478bd9Sstevel@tonic-gate { 359*5d54f3d8Smuffin int fd; 3607c478bd9Sstevel@tonic-gate 3617c478bd9Sstevel@tonic-gate if ((fd = openlocale("LC_CTYPE", LC_CTYPE, locale, newlocale)) > 0) { 3627c478bd9Sstevel@tonic-gate if (read(fd, (char *)ctypep, CTYPE_SIZE) != CTYPE_SIZE) { 3637c478bd9Sstevel@tonic-gate (void) close(fd); 3647c478bd9Sstevel@tonic-gate fd = -1; 3657c478bd9Sstevel@tonic-gate } 3667c478bd9Sstevel@tonic-gate (void) close(fd); 3677c478bd9Sstevel@tonic-gate } 3687c478bd9Sstevel@tonic-gate return (fd); 3697c478bd9Sstevel@tonic-gate } 3707c478bd9Sstevel@tonic-gate 3717c478bd9Sstevel@tonic-gate /* open and load the numeric information */ 3727c478bd9Sstevel@tonic-gate 3737c478bd9Sstevel@tonic-gate char * 374*5d54f3d8Smuffin getlocale_numeric(char *locale, struct lconv *lconvp, char *newlocale) 3757c478bd9Sstevel@tonic-gate { 376*5d54f3d8Smuffin int fd; 3777c478bd9Sstevel@tonic-gate struct stat buf; 3787c478bd9Sstevel@tonic-gate char *str; 379*5d54f3d8Smuffin char *p; 3807c478bd9Sstevel@tonic-gate 3817c478bd9Sstevel@tonic-gate if ((fd = openlocale("LC_NUMERIC", LC_NUMERIC, locale, newlocale)) < 0) 3827c478bd9Sstevel@tonic-gate return (NULL); 3837c478bd9Sstevel@tonic-gate if (fd == 0) 3847c478bd9Sstevel@tonic-gate return ""; 3857c478bd9Sstevel@tonic-gate if ((fstat(fd, &buf)) != 0) 3867c478bd9Sstevel@tonic-gate return (NULL); 3877c478bd9Sstevel@tonic-gate if ((str = (char*)malloc((unsigned)buf.st_size + 2)) == NULL) 3887c478bd9Sstevel@tonic-gate return (NULL); 3897c478bd9Sstevel@tonic-gate 3907c478bd9Sstevel@tonic-gate if ((read(fd, str, (int)buf.st_size)) != buf.st_size) { 3917c478bd9Sstevel@tonic-gate free((malloc_t)str); 3927c478bd9Sstevel@tonic-gate return (NULL); 3937c478bd9Sstevel@tonic-gate } 3947c478bd9Sstevel@tonic-gate 3957c478bd9Sstevel@tonic-gate /* Set last character of str to '\0' */ 3967c478bd9Sstevel@tonic-gate p = &str[buf.st_size]; 3977c478bd9Sstevel@tonic-gate *p++ = '\n'; 3987c478bd9Sstevel@tonic-gate *p = '\0'; 3997c478bd9Sstevel@tonic-gate 4007c478bd9Sstevel@tonic-gate /* p will "walk thru" str */ 4017c478bd9Sstevel@tonic-gate p = str; 4027c478bd9Sstevel@tonic-gate 4037c478bd9Sstevel@tonic-gate p = getstr(p, &lconvp->decimal_point); 4047c478bd9Sstevel@tonic-gate if (p == NULL) 4057c478bd9Sstevel@tonic-gate goto fail; 4067c478bd9Sstevel@tonic-gate p = getstr(p, &lconvp->thousands_sep); 4077c478bd9Sstevel@tonic-gate if (p == NULL) 4087c478bd9Sstevel@tonic-gate goto fail; 4097c478bd9Sstevel@tonic-gate p = getgrouping(p, &lconvp->grouping); 4107c478bd9Sstevel@tonic-gate if (p == NULL) 4117c478bd9Sstevel@tonic-gate goto fail; 4127c478bd9Sstevel@tonic-gate (void) close(fd); 4137c478bd9Sstevel@tonic-gate 4147c478bd9Sstevel@tonic-gate return (str); 4157c478bd9Sstevel@tonic-gate 4167c478bd9Sstevel@tonic-gate fail: 4177c478bd9Sstevel@tonic-gate (void) close(fd); 4187c478bd9Sstevel@tonic-gate free((malloc_t)str); 4197c478bd9Sstevel@tonic-gate return (NULL); 4207c478bd9Sstevel@tonic-gate } 4217c478bd9Sstevel@tonic-gate 4227c478bd9Sstevel@tonic-gate 4237c478bd9Sstevel@tonic-gate static char * 424*5d54f3d8Smuffin getlocale_monetary(char *locale, struct lconv *lconvp, char *newlocale) 4257c478bd9Sstevel@tonic-gate { 426*5d54f3d8Smuffin int fd; 4277c478bd9Sstevel@tonic-gate struct stat buf; 4287c478bd9Sstevel@tonic-gate char *str; 429*5d54f3d8Smuffin char *p; 4307c478bd9Sstevel@tonic-gate 4317c478bd9Sstevel@tonic-gate if ((fd = openlocale("LC_MONETARY", LC_MONETARY, locale, newlocale)) < 0) 4327c478bd9Sstevel@tonic-gate return (NULL); 4337c478bd9Sstevel@tonic-gate if (fd == 0) 434*5d54f3d8Smuffin return (""); 4357c478bd9Sstevel@tonic-gate if ((fstat(fd, &buf)) != 0) 4367c478bd9Sstevel@tonic-gate return (NULL); 4377c478bd9Sstevel@tonic-gate if ((str = (char*)malloc((unsigned)buf.st_size + 2)) == NULL) 4387c478bd9Sstevel@tonic-gate return (NULL); 4397c478bd9Sstevel@tonic-gate 4407c478bd9Sstevel@tonic-gate if ((read(fd, str, (int)buf.st_size)) != buf.st_size) { 4417c478bd9Sstevel@tonic-gate free((malloc_t)str); 4427c478bd9Sstevel@tonic-gate return (NULL); 4437c478bd9Sstevel@tonic-gate } 4447c478bd9Sstevel@tonic-gate 4457c478bd9Sstevel@tonic-gate /* Set last character of str to '\0' */ 4467c478bd9Sstevel@tonic-gate p = &str[buf.st_size]; 4477c478bd9Sstevel@tonic-gate *p++ = '\n'; 4487c478bd9Sstevel@tonic-gate *p = '\0'; 4497c478bd9Sstevel@tonic-gate 4507c478bd9Sstevel@tonic-gate /* p will "walk thru" str */ 4517c478bd9Sstevel@tonic-gate p = str; 4527c478bd9Sstevel@tonic-gate 4537c478bd9Sstevel@tonic-gate p = getstr(p, &lconvp->int_curr_symbol); 4547c478bd9Sstevel@tonic-gate if (p == NULL) 4557c478bd9Sstevel@tonic-gate goto fail; 4567c478bd9Sstevel@tonic-gate p = getstr(p, &lconvp->currency_symbol); 4577c478bd9Sstevel@tonic-gate if (p == NULL) 4587c478bd9Sstevel@tonic-gate goto fail; 4597c478bd9Sstevel@tonic-gate p = getstr(p, &lconvp->mon_decimal_point); 4607c478bd9Sstevel@tonic-gate if (p == NULL) 4617c478bd9Sstevel@tonic-gate goto fail; 4627c478bd9Sstevel@tonic-gate p = getstr(p, &lconvp->mon_thousands_sep); 4637c478bd9Sstevel@tonic-gate if (p == NULL) 4647c478bd9Sstevel@tonic-gate goto fail; 4657c478bd9Sstevel@tonic-gate p = getgrouping(p, &lconvp->mon_grouping); 4667c478bd9Sstevel@tonic-gate if (p == NULL) 4677c478bd9Sstevel@tonic-gate goto fail; 4687c478bd9Sstevel@tonic-gate p = getstr(p, &lconvp->positive_sign); 4697c478bd9Sstevel@tonic-gate if (p == NULL) 4707c478bd9Sstevel@tonic-gate goto fail; 4717c478bd9Sstevel@tonic-gate p = getstr(p, &lconvp->negative_sign); 4727c478bd9Sstevel@tonic-gate if (p == NULL) 4737c478bd9Sstevel@tonic-gate goto fail; 4747c478bd9Sstevel@tonic-gate p = getnum(p, &lconvp->frac_digits); 4757c478bd9Sstevel@tonic-gate if (p == NULL) 4767c478bd9Sstevel@tonic-gate goto fail; 4777c478bd9Sstevel@tonic-gate p = getbool(p, &lconvp->p_cs_precedes); 4787c478bd9Sstevel@tonic-gate if (p == NULL) 4797c478bd9Sstevel@tonic-gate goto fail; 4807c478bd9Sstevel@tonic-gate p = getbool(p, &lconvp->p_sep_by_space); 4817c478bd9Sstevel@tonic-gate if (p == NULL) 4827c478bd9Sstevel@tonic-gate goto fail; 4837c478bd9Sstevel@tonic-gate p = getbool(p, &lconvp->n_cs_precedes); 4847c478bd9Sstevel@tonic-gate if (p == NULL) 4857c478bd9Sstevel@tonic-gate goto fail; 4867c478bd9Sstevel@tonic-gate p = getbool(p, &lconvp->n_sep_by_space); 4877c478bd9Sstevel@tonic-gate if (p == NULL) 4887c478bd9Sstevel@tonic-gate goto fail; 4897c478bd9Sstevel@tonic-gate p = getnum(p, &lconvp->p_sign_posn); 4907c478bd9Sstevel@tonic-gate if (p == NULL) 4917c478bd9Sstevel@tonic-gate goto fail; 4927c478bd9Sstevel@tonic-gate p = getnum(p, &lconvp->n_sign_posn); 4937c478bd9Sstevel@tonic-gate if (p == NULL) 4947c478bd9Sstevel@tonic-gate goto fail; 4957c478bd9Sstevel@tonic-gate (void) close(fd); 4967c478bd9Sstevel@tonic-gate 4977c478bd9Sstevel@tonic-gate return (str); 4987c478bd9Sstevel@tonic-gate 4997c478bd9Sstevel@tonic-gate fail: 5007c478bd9Sstevel@tonic-gate (void) close(fd); 5017c478bd9Sstevel@tonic-gate free((malloc_t)str); 502*5d54f3d8Smuffin return (NULL); 5037c478bd9Sstevel@tonic-gate } 5047c478bd9Sstevel@tonic-gate 5057c478bd9Sstevel@tonic-gate static char * 506*5d54f3d8Smuffin getstr(char *p, char **strp) 5077c478bd9Sstevel@tonic-gate { 5087c478bd9Sstevel@tonic-gate *strp = p; 5097c478bd9Sstevel@tonic-gate p = strchr(p, '\n'); 5107c478bd9Sstevel@tonic-gate if (p == NULL) 5117c478bd9Sstevel@tonic-gate return (NULL); /* no end-of-line */ 5127c478bd9Sstevel@tonic-gate *p++ = '\0'; 5137c478bd9Sstevel@tonic-gate return (p); 5147c478bd9Sstevel@tonic-gate } 5157c478bd9Sstevel@tonic-gate 5167c478bd9Sstevel@tonic-gate static char * 517*5d54f3d8Smuffin getgrouping(char *p, char **groupingp) 5187c478bd9Sstevel@tonic-gate { 519*5d54f3d8Smuffin int c; 5207c478bd9Sstevel@tonic-gate 5217c478bd9Sstevel@tonic-gate if (*p == '\0') 5227c478bd9Sstevel@tonic-gate return (NULL); /* no grouping */ 5237c478bd9Sstevel@tonic-gate *groupingp = p; 5247c478bd9Sstevel@tonic-gate while ((c = *p) != '\n') { 5257c478bd9Sstevel@tonic-gate if (c == '\0') 5267c478bd9Sstevel@tonic-gate return (NULL); /* no end-of-line */ 5277c478bd9Sstevel@tonic-gate if (c >= '0' && c <= '9') 5287c478bd9Sstevel@tonic-gate *p++ = c - '0'; 5297c478bd9Sstevel@tonic-gate else 5307c478bd9Sstevel@tonic-gate *p++ = '\177'; 5317c478bd9Sstevel@tonic-gate } 5327c478bd9Sstevel@tonic-gate *p++ = '\0'; 5337c478bd9Sstevel@tonic-gate return (p); 5347c478bd9Sstevel@tonic-gate } 5357c478bd9Sstevel@tonic-gate 5367c478bd9Sstevel@tonic-gate static char * 537*5d54f3d8Smuffin getnum(char *p, char *nump) 5387c478bd9Sstevel@tonic-gate { 539*5d54f3d8Smuffin int num; 540*5d54f3d8Smuffin int c; 5417c478bd9Sstevel@tonic-gate 5427c478bd9Sstevel@tonic-gate if (*p == '\0') 5437c478bd9Sstevel@tonic-gate return (NULL); /* no number */ 5447c478bd9Sstevel@tonic-gate if (*p == '\n') 5457c478bd9Sstevel@tonic-gate *nump = '\177'; /* blank line - no value */ 5467c478bd9Sstevel@tonic-gate else { 5477c478bd9Sstevel@tonic-gate num = 0; 5487c478bd9Sstevel@tonic-gate while ((c = *p) != '\n') { 5497c478bd9Sstevel@tonic-gate if (c < '0' || c > '9') 5507c478bd9Sstevel@tonic-gate return (NULL); /* bad number */ 5517c478bd9Sstevel@tonic-gate num = num*10 + c - '0'; 5527c478bd9Sstevel@tonic-gate p++; 5537c478bd9Sstevel@tonic-gate } 5547c478bd9Sstevel@tonic-gate *nump = num; 5557c478bd9Sstevel@tonic-gate } 5567c478bd9Sstevel@tonic-gate *p++ = '\0'; 5577c478bd9Sstevel@tonic-gate return (p); 5587c478bd9Sstevel@tonic-gate } 5597c478bd9Sstevel@tonic-gate 5607c478bd9Sstevel@tonic-gate static char * 561*5d54f3d8Smuffin getbool(char *p, char *boolp) 5627c478bd9Sstevel@tonic-gate { 5637c478bd9Sstevel@tonic-gate 5647c478bd9Sstevel@tonic-gate if (*p == '\0') 5657c478bd9Sstevel@tonic-gate return (NULL); /* no number */ 5667c478bd9Sstevel@tonic-gate if (*p == '\n') 5677c478bd9Sstevel@tonic-gate *boolp = '\177'; /* blank line - no value */ 5687c478bd9Sstevel@tonic-gate else { 5697c478bd9Sstevel@tonic-gate switch (*p++) { 5707c478bd9Sstevel@tonic-gate 5717c478bd9Sstevel@tonic-gate case 'y': 5727c478bd9Sstevel@tonic-gate case 'Y': 5737c478bd9Sstevel@tonic-gate case 't': 5747c478bd9Sstevel@tonic-gate case 'T': 5757c478bd9Sstevel@tonic-gate *boolp = 1; /* true */ 5767c478bd9Sstevel@tonic-gate break; 5777c478bd9Sstevel@tonic-gate 5787c478bd9Sstevel@tonic-gate case 'n': 5797c478bd9Sstevel@tonic-gate case 'N': 5807c478bd9Sstevel@tonic-gate case 'f': 5817c478bd9Sstevel@tonic-gate case 'F': 5827c478bd9Sstevel@tonic-gate *boolp = 0; /* false */ 5837c478bd9Sstevel@tonic-gate break; 5847c478bd9Sstevel@tonic-gate 5857c478bd9Sstevel@tonic-gate default: 5867c478bd9Sstevel@tonic-gate return (NULL); /* bad boolean */ 5877c478bd9Sstevel@tonic-gate } 5887c478bd9Sstevel@tonic-gate if (*p != '\n') 5897c478bd9Sstevel@tonic-gate return (NULL); /* noise at end of line */ 5907c478bd9Sstevel@tonic-gate } 5917c478bd9Sstevel@tonic-gate *p++ = '\0'; 5927c478bd9Sstevel@tonic-gate return (p); 5937c478bd9Sstevel@tonic-gate } 5947c478bd9Sstevel@tonic-gate 5957c478bd9Sstevel@tonic-gate /* 5967c478bd9Sstevel@tonic-gate * Open a locale file. First, check the value of "locale"; if it's a null 5977c478bd9Sstevel@tonic-gate * string, first check the environment variable with the same name as the 5987c478bd9Sstevel@tonic-gate * category, and then check the environment variable "LANG". If neither of 5997c478bd9Sstevel@tonic-gate * them are set to non-null strings, use the LC_default env.var and if this 6007c478bd9Sstevel@tonic-gate * has no meaning then assume we are running in the C locale. It is expected 6017c478bd9Sstevel@tonic-gate * That LC_default is set across the whole system. If the resulting locale is 6027c478bd9Sstevel@tonic-gate * longer than MAXLOCALENAME characters, reject it. Then, try looking in the 6037c478bd9Sstevel@tonic-gate * per-machine locale directory for the file in question; if it's not found 6047c478bd9Sstevel@tonic-gate * there, try looking in the shared locale directory. 6057c478bd9Sstevel@tonic-gate * If there is no work to do, that is, the last setting of locales is equal 6067c478bd9Sstevel@tonic-gate * to the current request, then we don't do anything, and exit with value 0. 6077c478bd9Sstevel@tonic-gate * Copy the name of the locale used into "newlocale". 6087c478bd9Sstevel@tonic-gate * Exit with positive value if we opened a file 6097c478bd9Sstevel@tonic-gate * Exit with -1 if an error occured (invalid locale). 6107c478bd9Sstevel@tonic-gate * Exit with 0 if there is no need to look at the disk file. 6117c478bd9Sstevel@tonic-gate * (Assumption - there is always at least one fd open before setlocale 6127c478bd9Sstevel@tonic-gate * is called) 6137c478bd9Sstevel@tonic-gate */ 6147c478bd9Sstevel@tonic-gate int 615*5d54f3d8Smuffin openlocale(char *category, int cat_id, char *locale, char *newlocale) 6167c478bd9Sstevel@tonic-gate { 6177c478bd9Sstevel@tonic-gate char pathname[MAXPATHLEN], *defp; 6187c478bd9Sstevel@tonic-gate int fd, fd2; 6197c478bd9Sstevel@tonic-gate struct _code_header code_header; 6207c478bd9Sstevel@tonic-gate char *my_info; 6217c478bd9Sstevel@tonic-gate 6227c478bd9Sstevel@tonic-gate if (*locale == '\0') { 6237c478bd9Sstevel@tonic-gate locale = getenv(category); 6247c478bd9Sstevel@tonic-gate if (locale == NULL || *locale == '\0') { 6257c478bd9Sstevel@tonic-gate locale = getenv("LANG"); 6267c478bd9Sstevel@tonic-gate if (locale == NULL || *locale == '\0') { 6277c478bd9Sstevel@tonic-gate if (*Default == '\0') { 6287c478bd9Sstevel@tonic-gate defp = getenv("LC_default"); 6297c478bd9Sstevel@tonic-gate if (defp == NULL || *defp == '\0') 6307c478bd9Sstevel@tonic-gate strcpy(Default,"C"); 6317c478bd9Sstevel@tonic-gate else 6327c478bd9Sstevel@tonic-gate strcpy(Default, defp); 6337c478bd9Sstevel@tonic-gate } 6347c478bd9Sstevel@tonic-gate locale = Default; 6357c478bd9Sstevel@tonic-gate } 6367c478bd9Sstevel@tonic-gate } 6377c478bd9Sstevel@tonic-gate } 6387c478bd9Sstevel@tonic-gate if (strcmp(locale,_locales[cat_id-1]) == 0) { 6397c478bd9Sstevel@tonic-gate (void) strcpy(newlocale, locale); 640*5d54f3d8Smuffin return (0); 6417c478bd9Sstevel@tonic-gate } 6427c478bd9Sstevel@tonic-gate if (strlen(locale) > MAXLOCALENAME) 643*5d54f3d8Smuffin return (-1); 6447c478bd9Sstevel@tonic-gate 6457c478bd9Sstevel@tonic-gate (void) strcpy(pathname, PRIVATE_LOCALE_DIR); 6467c478bd9Sstevel@tonic-gate (void) strcat(pathname, category); 6477c478bd9Sstevel@tonic-gate (void) strcat(pathname, "/"); 6487c478bd9Sstevel@tonic-gate (void) strcat(pathname, locale); 6497c478bd9Sstevel@tonic-gate if ((fd = open(pathname, O_RDONLY)) < 0 && errno == ENOENT) { 6507c478bd9Sstevel@tonic-gate (void) strcpy(pathname, LOCALE_DIR); 6517c478bd9Sstevel@tonic-gate (void) strcat(pathname, category); 6527c478bd9Sstevel@tonic-gate (void) strcat(pathname, "/"); 6537c478bd9Sstevel@tonic-gate (void) strcat(pathname, locale); 6547c478bd9Sstevel@tonic-gate fd = open(pathname, O_RDONLY); 6557c478bd9Sstevel@tonic-gate } 6567c478bd9Sstevel@tonic-gate if (fd >= 0) 6577c478bd9Sstevel@tonic-gate (void) strcpy(newlocale, locale); 6587c478bd9Sstevel@tonic-gate /* 6597c478bd9Sstevel@tonic-gate * bug id 1072740; if by some chance the actual fd we're going to 6607c478bd9Sstevel@tonic-gate * return is 0, change it to be some non-zero descriptor, because 6617c478bd9Sstevel@tonic-gate * returning 0 means something different. If '0' is the only 6627c478bd9Sstevel@tonic-gate * descriptor left, return an error. 6637c478bd9Sstevel@tonic-gate */ 6647c478bd9Sstevel@tonic-gate if (fd == 0) { 6657c478bd9Sstevel@tonic-gate int dupfd; 6667c478bd9Sstevel@tonic-gate 6677c478bd9Sstevel@tonic-gate if ((dupfd = dup(fd)) < 1) { 6687c478bd9Sstevel@tonic-gate (void) close(fd); 6697c478bd9Sstevel@tonic-gate fd = -1; 6707c478bd9Sstevel@tonic-gate } else { 6717c478bd9Sstevel@tonic-gate (void) close(fd); 6727c478bd9Sstevel@tonic-gate fd = dupfd; 6737c478bd9Sstevel@tonic-gate } 6747c478bd9Sstevel@tonic-gate } 6757c478bd9Sstevel@tonic-gate 6767c478bd9Sstevel@tonic-gate if (cat_id == LC_CTYPE) { 6777c478bd9Sstevel@tonic-gate 6787c478bd9Sstevel@tonic-gate /* Go and get the trailer file */ 6797c478bd9Sstevel@tonic-gate 6807c478bd9Sstevel@tonic-gate (void) strcat(pathname, TRAILER); 6817c478bd9Sstevel@tonic-gate fd2 = open(pathname, O_RDONLY); 6827c478bd9Sstevel@tonic-gate if ( fd2 == 0 ) { 6837c478bd9Sstevel@tonic-gate fd2 = dup(fd2); 6847c478bd9Sstevel@tonic-gate close(0); 6857c478bd9Sstevel@tonic-gate } 6867c478bd9Sstevel@tonic-gate 6877c478bd9Sstevel@tonic-gate if (fd2 == -1) { 6887c478bd9Sstevel@tonic-gate set_default(); 689*5d54f3d8Smuffin return (fd); 6907c478bd9Sstevel@tonic-gate } 6917c478bd9Sstevel@tonic-gate 6927c478bd9Sstevel@tonic-gate /* 6937c478bd9Sstevel@tonic-gate * ctype trailer file exists - read it 6947c478bd9Sstevel@tonic-gate */ 6957c478bd9Sstevel@tonic-gate 6967c478bd9Sstevel@tonic-gate if (read (fd2, (char *)&code_header, sizeof (code_header)) != 6977c478bd9Sstevel@tonic-gate sizeof (code_header)) { 6987c478bd9Sstevel@tonic-gate /* 6997c478bd9Sstevel@tonic-gate * File format not correct 7007c478bd9Sstevel@tonic-gate */ 7017c478bd9Sstevel@tonic-gate set_default(); 7027c478bd9Sstevel@tonic-gate close(fd2); 703*5d54f3d8Smuffin return (-1); 7047c478bd9Sstevel@tonic-gate } 7057c478bd9Sstevel@tonic-gate /* 7067c478bd9Sstevel@tonic-gate * set up trailer file 7077c478bd9Sstevel@tonic-gate */ 7087c478bd9Sstevel@tonic-gate strcpy(_code_set_info.code_name, code_header.code_name); 7097c478bd9Sstevel@tonic-gate _code_set_info.code_id = code_header.code_id; 7107c478bd9Sstevel@tonic-gate if (_code_set_info.code_info != NULL) 7117c478bd9Sstevel@tonic-gate free (_code_set_info.code_info); 7127c478bd9Sstevel@tonic-gate if (code_header.code_info_size > 0) { 7137c478bd9Sstevel@tonic-gate my_info = malloc(code_header.code_info_size); 7147c478bd9Sstevel@tonic-gate if (read (fd2, (char *)my_info, 7157c478bd9Sstevel@tonic-gate code_header.code_info_size) != 7167c478bd9Sstevel@tonic-gate code_header.code_info_size) { 7177c478bd9Sstevel@tonic-gate close(fd2); 7187c478bd9Sstevel@tonic-gate set_default(); 719*5d54f3d8Smuffin return (-1); 7207c478bd9Sstevel@tonic-gate } 7217c478bd9Sstevel@tonic-gate _code_set_info.code_info = my_info; 7227c478bd9Sstevel@tonic-gate } 7237c478bd9Sstevel@tonic-gate else { 7247c478bd9Sstevel@tonic-gate /* 7257c478bd9Sstevel@tonic-gate * We have a corrupted file too 7267c478bd9Sstevel@tonic-gate */ 7277c478bd9Sstevel@tonic-gate _code_set_info.code_info = NULL; 7287c478bd9Sstevel@tonic-gate close(fd2); 7297c478bd9Sstevel@tonic-gate set_default(); 730*5d54f3d8Smuffin return (-1); 7317c478bd9Sstevel@tonic-gate } 7327c478bd9Sstevel@tonic-gate close (fd2); 7337c478bd9Sstevel@tonic-gate } 734*5d54f3d8Smuffin return (fd); 7357c478bd9Sstevel@tonic-gate } 7367c478bd9Sstevel@tonic-gate 7377c478bd9Sstevel@tonic-gate struct lconv * 738*5d54f3d8Smuffin localeconv(void) 7397c478bd9Sstevel@tonic-gate { 7407c478bd9Sstevel@tonic-gate return (lconv); 7417c478bd9Sstevel@tonic-gate } 7427c478bd9Sstevel@tonic-gate 7437c478bd9Sstevel@tonic-gate struct dtconv * 744*5d54f3d8Smuffin localdtconv(void) 7457c478bd9Sstevel@tonic-gate { 746*5d54f3d8Smuffin char *p; 747*5d54f3d8Smuffin short i; 7487c478bd9Sstevel@tonic-gate 7497c478bd9Sstevel@tonic-gate char *rawmonths = "Jan\nFeb\nMar\nApr\nMay\nJun\nJul\nAug\nSep\nOct\nNov\nDec\nJanuary\nFebruary\nMarch\nApril\nMay\nJune\nJuly\nAugust\nSeptember\nOctober\nNovember\nDecember"; 7507c478bd9Sstevel@tonic-gate 7517c478bd9Sstevel@tonic-gate char *rawdays = "Sun\nMon\nTue\nWed\nThu\nFri\nSat\nSunday\nMonday\nTuesday\nWednesday\nThursday\nFriday\nSaturday"; 7527c478bd9Sstevel@tonic-gate 7537c478bd9Sstevel@tonic-gate char *rawfmts = "%H:%M:%S\n%m/%d/%y\n%a %b %e %T %Z %Y\nAM\nPM\n%A, %B %e, %Y\n"; 7547c478bd9Sstevel@tonic-gate 7557c478bd9Sstevel@tonic-gate /* fix for bugid 1067574 ... robinson */ 7567c478bd9Sstevel@tonic-gate (void)getlocale_time(); 7577c478bd9Sstevel@tonic-gate 7587c478bd9Sstevel@tonic-gate if (_dtconv == NULL) { 7597c478bd9Sstevel@tonic-gate 7607c478bd9Sstevel@tonic-gate /* We malloc both the space for the dtconv struct and the 7617c478bd9Sstevel@tonic-gate * copy of the strings above because this program is later run 7627c478bd9Sstevel@tonic-gate * through xstr and the resultant strings are put in read-only 7637c478bd9Sstevel@tonic-gate * text segment. Therefore we cannot write to the original 7647c478bd9Sstevel@tonic-gate * raw strings but we can to their copies. 7657c478bd9Sstevel@tonic-gate */ 7667c478bd9Sstevel@tonic-gate 7677c478bd9Sstevel@tonic-gate _dtconv = (struct dtconv*)malloc(sizeof (struct dtconv)); 7687c478bd9Sstevel@tonic-gate if (_dtconv == NULL) 7697c478bd9Sstevel@tonic-gate return (NULL); 7707c478bd9Sstevel@tonic-gate if ((realmonths = malloc(strlen(rawmonths)+1)) == NULL) 7717c478bd9Sstevel@tonic-gate return (NULL); 7727c478bd9Sstevel@tonic-gate strcpy(realmonths, rawmonths); 7737c478bd9Sstevel@tonic-gate if ((realdays = malloc(strlen(rawdays)+1)) == NULL) 7747c478bd9Sstevel@tonic-gate return (NULL); 7757c478bd9Sstevel@tonic-gate strcpy(realdays, rawdays); 7767c478bd9Sstevel@tonic-gate if ((realfmts = malloc(strlen(rawfmts)+1)) == NULL) 7777c478bd9Sstevel@tonic-gate return (NULL); 7787c478bd9Sstevel@tonic-gate strcpy(realfmts, rawfmts); 7797c478bd9Sstevel@tonic-gate 7807c478bd9Sstevel@tonic-gate /* p will "walk thru" str */ 7817c478bd9Sstevel@tonic-gate 7827c478bd9Sstevel@tonic-gate p = realmonths; 7837c478bd9Sstevel@tonic-gate 7847c478bd9Sstevel@tonic-gate for (i = 0; i < 12; i++) 7857c478bd9Sstevel@tonic-gate p = getstr(p, &(_dtconv->abbrev_month_names[i])); 7867c478bd9Sstevel@tonic-gate 7877c478bd9Sstevel@tonic-gate for (i = 0; i < 12; i++) 7887c478bd9Sstevel@tonic-gate p = getstr(p, &(_dtconv->month_names[i])); 7897c478bd9Sstevel@tonic-gate p = realdays; 7907c478bd9Sstevel@tonic-gate for (i= 0; i < 7; i++) 7917c478bd9Sstevel@tonic-gate p = getstr(p, &(_dtconv->abbrev_weekday_names[i])); 7927c478bd9Sstevel@tonic-gate for (i = 0; i < 7; i++) 7937c478bd9Sstevel@tonic-gate p = getstr(p, &(_dtconv->weekday_names[i])); 7947c478bd9Sstevel@tonic-gate p = realfmts; 7957c478bd9Sstevel@tonic-gate p = getstr(p, &_dtconv->time_format); 7967c478bd9Sstevel@tonic-gate p = getstr(p, &_dtconv->sdate_format); 7977c478bd9Sstevel@tonic-gate p = getstr(p, &_dtconv->dtime_format); 7987c478bd9Sstevel@tonic-gate p = getstr(p, &_dtconv->am_string); 7997c478bd9Sstevel@tonic-gate p = getstr(p, &_dtconv->pm_string); 8007c478bd9Sstevel@tonic-gate p = getstr(p, &_dtconv->ldate_format); 8017c478bd9Sstevel@tonic-gate } 8027c478bd9Sstevel@tonic-gate 8037c478bd9Sstevel@tonic-gate return (_dtconv); 8047c478bd9Sstevel@tonic-gate } 8057c478bd9Sstevel@tonic-gate 8067c478bd9Sstevel@tonic-gate 807*5d54f3d8Smuffin static void 808*5d54f3d8Smuffin set_default(void) 8097c478bd9Sstevel@tonic-gate { 8107c478bd9Sstevel@tonic-gate 8117c478bd9Sstevel@tonic-gate strcpy(_code_set_info.code_name, Default); 8127c478bd9Sstevel@tonic-gate _code_set_info.code_id = CODESET_NONE; 8137c478bd9Sstevel@tonic-gate if (_code_set_info.code_info != NULL) 8147c478bd9Sstevel@tonic-gate free (_code_set_info.code_info); 8157c478bd9Sstevel@tonic-gate _code_set_info.code_info = NULL; 8167c478bd9Sstevel@tonic-gate _code_set_info.open_flag = 0; 8177c478bd9Sstevel@tonic-gate } 8187c478bd9Sstevel@tonic-gate 819*5d54f3d8Smuffin void 820*5d54f3d8Smuffin init_statics(void) 821*5d54f3d8Smuffin { 8227c478bd9Sstevel@tonic-gate 8237c478bd9Sstevel@tonic-gate short i; 8247c478bd9Sstevel@tonic-gate 8257c478bd9Sstevel@tonic-gate for (i=0; i<MAXLOCALE-1;i++) 8267c478bd9Sstevel@tonic-gate strcpy(_locales[i],"C"); 8277c478bd9Sstevel@tonic-gate strcpy(_code_set_info.code_name, "default"); 8287c478bd9Sstevel@tonic-gate strcpy(_my_time,"C"); 8297c478bd9Sstevel@tonic-gate _langinfo.yesstr = "yes"; 8307c478bd9Sstevel@tonic-gate _langinfo.nostr = "no"; 8317c478bd9Sstevel@tonic-gate } 832