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 *
setlocale(int category,char * locale)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
getlocale_ctype(char * locale,char * ctypep,char * newlocale)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 *
getlocale_numeric(char * locale,struct lconv * lconvp,char * newlocale)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 *
getlocale_monetary(char * locale,struct lconv * lconvp,char * newlocale)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 *
getstr(char * p,char ** strp)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 *
getgrouping(char * p,char ** groupingp)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 *
getnum(char * p,char * nump)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 *
getbool(char * p,char * boolp)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
openlocale(char * category,int cat_id,char * locale,char * newlocale)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 *
localeconv(void)738*5d54f3d8Smuffin localeconv(void)
7397c478bd9Sstevel@tonic-gate {
7407c478bd9Sstevel@tonic-gate return (lconv);
7417c478bd9Sstevel@tonic-gate }
7427c478bd9Sstevel@tonic-gate
7437c478bd9Sstevel@tonic-gate struct dtconv *
localdtconv(void)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
set_default(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
init_statics(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