xref: /onnv-gate/usr/src/lib/libbc/libc/gen/common/setlocale.c (revision 722:636b850d4ee9)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
50Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
60Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
70Sstevel@tonic-gate  * with the License.
80Sstevel@tonic-gate  *
90Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
100Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
110Sstevel@tonic-gate  * See the License for the specific language governing permissions
120Sstevel@tonic-gate  * and limitations under the License.
130Sstevel@tonic-gate  *
140Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
150Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
160Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
170Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
180Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
190Sstevel@tonic-gate  *
200Sstevel@tonic-gate  * CDDL HEADER END
210Sstevel@tonic-gate  */
220Sstevel@tonic-gate /*
230Sstevel@tonic-gate  * Copyright 1995 Sun Microsystems, Inc.  All rights reserved.
240Sstevel@tonic-gate  * Use is subject to license terms.
250Sstevel@tonic-gate  */
260Sstevel@tonic-gate 
270Sstevel@tonic-gate /*	Copyright (c) 1984 AT&T	*/
280Sstevel@tonic-gate /*	  All Rights Reserved  	*/
290Sstevel@tonic-gate 
300Sstevel@tonic-gate 
310Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
320Sstevel@tonic-gate 
33*722Smuffin #include <sys/fcntl.h>
340Sstevel@tonic-gate #include <locale.h>
350Sstevel@tonic-gate #include <stdlib.h>
360Sstevel@tonic-gate #include "codeset.h"
370Sstevel@tonic-gate #include <ctype.h>
380Sstevel@tonic-gate #include <string.h>
390Sstevel@tonic-gate #include <memory.h>
400Sstevel@tonic-gate #include <malloc.h>
410Sstevel@tonic-gate #include <sys/param.h>		/* for MAXPATHLEN */
420Sstevel@tonic-gate #include <sys/stat.h>
430Sstevel@tonic-gate #include <errno.h>
440Sstevel@tonic-gate #include <limits.h>
450Sstevel@tonic-gate 
460Sstevel@tonic-gate #define	TRAILER ".ci"
470Sstevel@tonic-gate 
480Sstevel@tonic-gate 
490Sstevel@tonic-gate struct	_code_set_info _code_set_info = {
500Sstevel@tonic-gate 	NULL,
510Sstevel@tonic-gate 	CODESET_NONE, 	/* no codeset */
520Sstevel@tonic-gate 	NULL, 		/* not defined */
530Sstevel@tonic-gate 	0,
540Sstevel@tonic-gate };
550Sstevel@tonic-gate 
560Sstevel@tonic-gate /* tolower()  and toupper() conversion table
570Sstevel@tonic-gate  * is hidden here to avoid being placed in the
580Sstevel@tonic-gate  * extern  .sa file in the dynamic version of libc
590Sstevel@tonic-gate  */
600Sstevel@tonic-gate 
610Sstevel@tonic-gate char _ctype_ul[] = { 0,
620Sstevel@tonic-gate 
630Sstevel@tonic-gate /*	 0	 1	 2	 3	 4	 5	 6	 7  */
640Sstevel@tonic-gate 	'\000',	'\001',	'\002',	'\003',	'\004',	'\005',	'\006',	'\007',
650Sstevel@tonic-gate 	'\010',	'\011',	'\012',	'\013',	'\014',	'\015',	'\016',	'\017',
660Sstevel@tonic-gate 	'\020',	'\021',	'\022',	'\023',	'\024',	'\025',	'\026',	'\027',
670Sstevel@tonic-gate 	'\030',	'\031',	'\032',	'\033',	'\034',	'\035',	'\036',	'\037',
680Sstevel@tonic-gate 	' ',	'!',	'"',	'#',	'$',	'%',	'&',	'\'',
690Sstevel@tonic-gate 	'(',	')',	'*',	'+',	',',	'-',	'.',	'/',
700Sstevel@tonic-gate 	'0',	'1',	'2',	'3',	'4',	'5',	'6',	'7',
710Sstevel@tonic-gate 	'8',	'9',	':',	';',	'<',	'=',	'>',	'?',
720Sstevel@tonic-gate 	'@',	'a',	'b',	'c',	'd',	'e',	'f',	'g',
730Sstevel@tonic-gate 	'h',	'i',	'j',	'k',	'l',	'm',	'n',	'o',
740Sstevel@tonic-gate 	'p',	'q',	'r',	's',	't',	'u',	'v',	'w',
750Sstevel@tonic-gate 	'x',	'y',	'z',	'[',	'\\',	']',	'^',	'_',
760Sstevel@tonic-gate 	'`',	'A',	'B',	'C',	'D',	'E',	'F',	'G',
770Sstevel@tonic-gate 	'H',	'I',	'J',	'K',	'L',	'M',	'N',	'O',
780Sstevel@tonic-gate 	'P',	'Q',	'R',	'S',	'T',	'U',	'V',	'W',
790Sstevel@tonic-gate 	'X',	'Y',	'Z',	'{',	'|',	'}',	'~',	'\177',
800Sstevel@tonic-gate 	0,	0,	0,	0,	0,	0,	0,	0,
810Sstevel@tonic-gate 	0,	0,	0,	0,	0,	0,	0,	0,
820Sstevel@tonic-gate 	0,	0,	0,	0,	0,	0,	0,	0,
830Sstevel@tonic-gate 	0,	0,	0,	0,	0,	0,	0,	0,
840Sstevel@tonic-gate 	0,	0,	0,	0,	0,	0,	0,	0,
850Sstevel@tonic-gate 	0,	0,	0,	0,	0,	0,	0,	0,
860Sstevel@tonic-gate 	0,	0,	0,	0,	0,	0,	0,	0,
870Sstevel@tonic-gate 	0,	0,	0,	0,	0,	0,	0,	0,
880Sstevel@tonic-gate 	0,	0,	0,	0,	0,	0,	0,	0,
890Sstevel@tonic-gate 	0,	0,	0,	0,	0,	0,	0,	0,
900Sstevel@tonic-gate 	0,	0,	0,	0,	0,	0,	0,	0,
910Sstevel@tonic-gate 	0,	0,	0,	0,	0,	0,	0,	0,
920Sstevel@tonic-gate 	0,	0,	0,	0,	0,	0,	0,	0,
930Sstevel@tonic-gate 	0,	0,	0,	0,	0,	0,	0,	0,
940Sstevel@tonic-gate 	0,	0,	0,	0,	0,	0,	0,	0,
950Sstevel@tonic-gate 	0,	0,	0,	0,	0,	0,	0,	0,
960Sstevel@tonic-gate };
970Sstevel@tonic-gate 
980Sstevel@tonic-gate /* following layout is:
990Sstevel@tonic-gate  * LC_NUMERIC LC_TIME LC_MONETARY LANGINFO LC_COLLATE LC_MESSAGES
1000Sstevel@tonic-gate  */
1010Sstevel@tonic-gate char _locales[MAXLOCALE - 1][MAXLOCALENAME + 1] ;
1020Sstevel@tonic-gate 
1030Sstevel@tonic-gate char _my_time[MAXLOCALENAME + 1];
1040Sstevel@tonic-gate 
1050Sstevel@tonic-gate /* The array Default holds the systems notion of default locale. It is normally
1060Sstevel@tonic-gate  * found in {LOCALE}/.default and moved to here. Note there is only one
1070Sstevel@tonic-gate  * default locale spanning all categories
1080Sstevel@tonic-gate  */
1090Sstevel@tonic-gate 
1100Sstevel@tonic-gate static char Default[MAXLOCALENAME+1];
1110Sstevel@tonic-gate 
1120Sstevel@tonic-gate struct	langinfo _langinfo;
1130Sstevel@tonic-gate struct	dtconv *_dtconv = NULL;
1140Sstevel@tonic-gate 
1150Sstevel@tonic-gate static	char *realmonths = NULL;
1160Sstevel@tonic-gate static	char *realdays = NULL;
1170Sstevel@tonic-gate static	char *realfmts = NULL;
1180Sstevel@tonic-gate static  short lang_succ = ON;	/* setlocale success */
1190Sstevel@tonic-gate 
1200Sstevel@tonic-gate 
1210Sstevel@tonic-gate /* Set the values here to guarantee stdio use of the
1220Sstevel@tonic-gate    decimal point
1230Sstevel@tonic-gate  */
1240Sstevel@tonic-gate static struct lconv lconv_arr = {
1250Sstevel@tonic-gate 	".", "", "", "", "",
1260Sstevel@tonic-gate 	"", "", "", "", "",
1270Sstevel@tonic-gate 	CHAR_MAX, CHAR_MAX, CHAR_MAX, CHAR_MAX,
1280Sstevel@tonic-gate 	CHAR_MAX, CHAR_MAX, CHAR_MAX, CHAR_MAX
1290Sstevel@tonic-gate };
1300Sstevel@tonic-gate 
1310Sstevel@tonic-gate /* lconv is externally defined by ANSI C */
1320Sstevel@tonic-gate struct	lconv *lconv = &lconv_arr;
1330Sstevel@tonic-gate 
1340Sstevel@tonic-gate static	char *lconv_numeric_str = NULL;
1350Sstevel@tonic-gate static 	char *lconv_monetary_str = NULL;
1360Sstevel@tonic-gate 
137*722Smuffin int	openlocale(char *, int, char *, char *);
138*722Smuffin int	getlocale_ctype(char *, char *, char *);
139*722Smuffin char	*getlocale_numeric(char *, struct lconv *, char *);
140*722Smuffin void	init_statics(void);
141*722Smuffin static char	*getlocale_monetary(char *, struct lconv *, char *);
142*722Smuffin static char	*getstr(char *, char **);
143*722Smuffin static char	*getgrouping(char *, char **);
144*722Smuffin static char	*getnum(char  *, char *);
145*722Smuffin static char	*getbool(char *, char *);
146*722Smuffin static void	set_default(void);
1470Sstevel@tonic-gate 
1480Sstevel@tonic-gate char *
setlocale(int category,char * locale)149*722Smuffin setlocale(int category, char *locale)
1500Sstevel@tonic-gate {
1510Sstevel@tonic-gate 	static char buf[MAXLOCALE*(MAXLOCALENAME + 1) + 1];
1520Sstevel@tonic-gate 		/* buffer for current LC_ALL value */
1530Sstevel@tonic-gate 	int nonuniform;
1540Sstevel@tonic-gate 	short ret;
1550Sstevel@tonic-gate 	char my_ctype[CTYPE_SIZE];	/* local copy */
1560Sstevel@tonic-gate 	struct lconv my_lconv;		/* local copy */
1570Sstevel@tonic-gate 	char *my_lconv_numeric_str;
1580Sstevel@tonic-gate 	char *my_lconv_monetary_str;
159*722Smuffin 	int i;
160*722Smuffin 	char *p;
1610Sstevel@tonic-gate 
1620Sstevel@tonic-gate 
1630Sstevel@tonic-gate 	 /* initialize my_lconv to lconv */
1640Sstevel@tonic-gate         memcpy(&my_lconv, lconv, sizeof(my_lconv));
1650Sstevel@tonic-gate 
1660Sstevel@tonic-gate 	/*
1670Sstevel@tonic-gate 	 *  Following code is to avoid static initialisation of
1680Sstevel@tonic-gate 	 *  strings which would otherwise blow up "xstr".
1690Sstevel@tonic-gate 	 */
1700Sstevel@tonic-gate 	if (_locales[0][0] == '\0')
1710Sstevel@tonic-gate 		init_statics();
1720Sstevel@tonic-gate 
1730Sstevel@tonic-gate 	if (locale == NULL) {
1740Sstevel@tonic-gate 		if (category == LC_ALL) {
1750Sstevel@tonic-gate 			/*
1760Sstevel@tonic-gate 			 * Assume all locales are set to the same value.  Then
1770Sstevel@tonic-gate 			 * scan through the locales to see if any are
1780Sstevel@tonic-gate 			 * different.  If they are the same, return the common
1790Sstevel@tonic-gate 			 * value; otherwise, construct a "composite" value.
1800Sstevel@tonic-gate 			 */
1810Sstevel@tonic-gate 			nonuniform = 0;	/* assume all locales set the same */
1820Sstevel@tonic-gate 			for (i = 0; i < MAXLOCALE - 2; i++) {
1830Sstevel@tonic-gate 				if (strcmp(_locales[i], _locales[i + 1]) != 0) {
1840Sstevel@tonic-gate 					nonuniform = 1;
1850Sstevel@tonic-gate 					break;
1860Sstevel@tonic-gate 				}
1870Sstevel@tonic-gate 			}
1880Sstevel@tonic-gate 			if (nonuniform) {
1890Sstevel@tonic-gate 				/*
1900Sstevel@tonic-gate 				 * They're not all the same.  Construct a list
1910Sstevel@tonic-gate 				 * of all the locale values, in order,
1920Sstevel@tonic-gate 				 * separated by slashes.  Return that value.
1930Sstevel@tonic-gate 				 */
1940Sstevel@tonic-gate 				(void) strcpy(buf, _locales[0]);
1950Sstevel@tonic-gate 				for (i = 1; i < MAXLOCALE - 1; i++) {
1960Sstevel@tonic-gate 					(void) strcat(buf, "/");
1970Sstevel@tonic-gate 					(void) strcat(buf, _locales[i]);
1980Sstevel@tonic-gate 				}
1990Sstevel@tonic-gate 				return (buf);
2000Sstevel@tonic-gate 			} else {
2010Sstevel@tonic-gate 				/*
2020Sstevel@tonic-gate 				 * They're all the same; any one you return is
2030Sstevel@tonic-gate 				 * OK.
2040Sstevel@tonic-gate 				 */
2050Sstevel@tonic-gate 				return (_locales[0]);
2060Sstevel@tonic-gate 			}
2070Sstevel@tonic-gate 		} else
2080Sstevel@tonic-gate 			return (_locales[category - 1]);
2090Sstevel@tonic-gate 	}
2100Sstevel@tonic-gate 
2110Sstevel@tonic-gate 	switch (category) {
2120Sstevel@tonic-gate 
2130Sstevel@tonic-gate 	case LC_ALL:
2140Sstevel@tonic-gate 		if (strchr(locale, '/') != NULL) {
2150Sstevel@tonic-gate 			/*
2160Sstevel@tonic-gate 			 * Composite value; extract each category.
2170Sstevel@tonic-gate 			 */
2180Sstevel@tonic-gate 			if (strlen(locale) > sizeof buf - 1)
2190Sstevel@tonic-gate 				return (NULL);	/* too long */
2200Sstevel@tonic-gate 			(void) strcpy(buf, locale);
2210Sstevel@tonic-gate 			p = buf;
2220Sstevel@tonic-gate 
2230Sstevel@tonic-gate 			/*
2240Sstevel@tonic-gate 			 * LC_CTYPE and LC_NUMERIC are set here.
2250Sstevel@tonic-gate 			 * Others locales won't be set here,
2260Sstevel@tonic-gate 			 * they will be just marked.
2270Sstevel@tonic-gate 			 */
2280Sstevel@tonic-gate 			for (i = 0; i < MAXLOCALE - 1; i++) {
2290Sstevel@tonic-gate 				p = strtok(p, "/");
2300Sstevel@tonic-gate 				if (p == NULL)
2310Sstevel@tonic-gate 					return (NULL);	/* missing item */
2320Sstevel@tonic-gate 				switch (i) {
2330Sstevel@tonic-gate 
2340Sstevel@tonic-gate 				case LC_CTYPE - 1:
2350Sstevel@tonic-gate 					if (setlocale(LC_CTYPE,p) == NULL)
236*722Smuffin 						return (NULL);
2370Sstevel@tonic-gate 					break;
2380Sstevel@tonic-gate 				case LC_NUMERIC - 1:
2390Sstevel@tonic-gate 					if (setlocale(LC_NUMERIC,p) == NULL)
240*722Smuffin 						return (NULL);
2410Sstevel@tonic-gate 					break;
2420Sstevel@tonic-gate 				case LC_TIME - 1:
2430Sstevel@tonic-gate 					if (setlocale(LC_TIME,p) == NULL)
244*722Smuffin 						return (NULL);
2450Sstevel@tonic-gate 					break;
2460Sstevel@tonic-gate 				case LC_MONETARY - 1:
2470Sstevel@tonic-gate 					if (setlocale(LC_MONETARY,p) == NULL)
248*722Smuffin 						return (NULL);
2490Sstevel@tonic-gate 					break;
2500Sstevel@tonic-gate 				case LANGINFO - 1:
2510Sstevel@tonic-gate 					if (setlocale(LANGINFO,p) == NULL)
252*722Smuffin 						return (NULL);
2530Sstevel@tonic-gate 					break;
2540Sstevel@tonic-gate 				case LC_COLLATE - 1:
2550Sstevel@tonic-gate 					if (setlocale(LC_COLLATE,p) == NULL)
256*722Smuffin 						return (NULL);
2570Sstevel@tonic-gate 					break;
2580Sstevel@tonic-gate 				case LC_MESSAGES - 1:
2590Sstevel@tonic-gate 					if (setlocale(LC_MESSAGES,p) == NULL)
260*722Smuffin 						return (NULL);
2610Sstevel@tonic-gate 					break;
2620Sstevel@tonic-gate 				}
2630Sstevel@tonic-gate 				p = NULL;
2640Sstevel@tonic-gate 			}
2650Sstevel@tonic-gate 			if (strtok((char *)NULL, "/") != NULL)
2660Sstevel@tonic-gate 				return (NULL);	/* extra stuff at end */
2670Sstevel@tonic-gate 		}
2680Sstevel@tonic-gate 
2690Sstevel@tonic-gate 	/* If category = LC_ALL, Drop through to test each individual
2700Sstevel@tonic-gate   	 * category, one at a time. Note default rules where env vars
2710Sstevel@tonic-gate 	 * are not set
2720Sstevel@tonic-gate 	 */
2730Sstevel@tonic-gate 
2740Sstevel@tonic-gate 	case LC_CTYPE:
2750Sstevel@tonic-gate 		if ((ret = getlocale_ctype(locale , my_ctype,
2760Sstevel@tonic-gate 		    _locales[LC_CTYPE - 1])) < 0)
2770Sstevel@tonic-gate 			return (NULL);
2780Sstevel@tonic-gate 		if (ret) {
2790Sstevel@tonic-gate 		      (void) memcpy(_ctype_, my_ctype, CTYPE_SIZE/2);
2800Sstevel@tonic-gate 		      (void) memcpy(_ctype_ul, my_ctype+(CTYPE_SIZE/2), CTYPE_SIZE/2);
2810Sstevel@tonic-gate 		}
2820Sstevel@tonic-gate 		if (category != LC_ALL)
2830Sstevel@tonic-gate 			break;
2840Sstevel@tonic-gate 
2850Sstevel@tonic-gate 	case LC_NUMERIC:
2860Sstevel@tonic-gate 		if ((my_lconv_numeric_str =
2870Sstevel@tonic-gate 		    getlocale_numeric(locale, &my_lconv,
2880Sstevel@tonic-gate 		      _locales[LC_NUMERIC - 1])) == NULL)
2890Sstevel@tonic-gate 			return (NULL);
2900Sstevel@tonic-gate 		if (*my_lconv_numeric_str) {
2910Sstevel@tonic-gate 			if (lconv_numeric_str != NULL)
2920Sstevel@tonic-gate 				free((malloc_t)lconv_numeric_str);
2930Sstevel@tonic-gate 			lconv_numeric_str = my_lconv_numeric_str;
2940Sstevel@tonic-gate 			memcpy(lconv, my_lconv, sizeof(my_lconv));
2950Sstevel@tonic-gate 		}
2960Sstevel@tonic-gate 		if (category != LC_ALL)
2970Sstevel@tonic-gate 			break;
2980Sstevel@tonic-gate 
2990Sstevel@tonic-gate 	case LC_TIME:
3000Sstevel@tonic-gate 		if ((ret = openlocale("LC_TIME", LC_TIME, locale,
3010Sstevel@tonic-gate 		      _locales[LC_TIME -1])) < 0)
3020Sstevel@tonic-gate 			return (NULL);
3030Sstevel@tonic-gate 		if (ret)
3040Sstevel@tonic-gate 			(void) close(ret);
3050Sstevel@tonic-gate 		if (category != LC_ALL)
3060Sstevel@tonic-gate 			break;
3070Sstevel@tonic-gate 
3080Sstevel@tonic-gate 	case LC_MONETARY:
3090Sstevel@tonic-gate 		if ((my_lconv_monetary_str =
3100Sstevel@tonic-gate 		    getlocale_monetary(locale, &my_lconv,
3110Sstevel@tonic-gate 		      _locales[LC_MONETARY - 1])) == NULL)
3120Sstevel@tonic-gate 			return (NULL);
3130Sstevel@tonic-gate 		if (*my_lconv_monetary_str) {
3140Sstevel@tonic-gate 			if (lconv_monetary_str != NULL)
3150Sstevel@tonic-gate 				free((malloc_t)lconv_monetary_str);
3160Sstevel@tonic-gate 			lconv_monetary_str = my_lconv_monetary_str;
3170Sstevel@tonic-gate 			memcpy(lconv, &my_lconv, sizeof(my_lconv));
3180Sstevel@tonic-gate 		}
3190Sstevel@tonic-gate 		if (category != LC_ALL)
3200Sstevel@tonic-gate 			break;
3210Sstevel@tonic-gate 
3220Sstevel@tonic-gate 	case LANGINFO:
3230Sstevel@tonic-gate 		if ((ret = openlocale("LANGINFO", LANGINFO, locale,
3240Sstevel@tonic-gate 		      _locales[LANGINFO - 1])) < 0) {
3250Sstevel@tonic-gate 			lang_succ = OFF;
3260Sstevel@tonic-gate 			return (NULL);
3270Sstevel@tonic-gate 		}
3280Sstevel@tonic-gate 		if (ret) {
3290Sstevel@tonic-gate 			lang_succ = OFF;
3300Sstevel@tonic-gate 			(void) close(ret);
3310Sstevel@tonic-gate 		}
3320Sstevel@tonic-gate 		if (category != LC_ALL)
3330Sstevel@tonic-gate 			break;
3340Sstevel@tonic-gate 
3350Sstevel@tonic-gate 	case LC_COLLATE:
3360Sstevel@tonic-gate 		if ((ret = openlocale("LC_COLLATE", LC_COLLATE, locale,
3370Sstevel@tonic-gate 		      _locales[LC_COLLATE - 1])) < 0)
3380Sstevel@tonic-gate 			return (NULL);
3390Sstevel@tonic-gate 		if (ret) {
3400Sstevel@tonic-gate 			(void) close(ret);
3410Sstevel@tonic-gate 		}
3420Sstevel@tonic-gate 		if (category != LC_ALL)
3430Sstevel@tonic-gate 			break;
3440Sstevel@tonic-gate 
3450Sstevel@tonic-gate 	case LC_MESSAGES:
3460Sstevel@tonic-gate 		if ((ret = openlocale("LC_MESSAGES", LC_MESSAGES, locale,
3470Sstevel@tonic-gate 		      _locales[LC_MESSAGES - 1])) < 0)
3480Sstevel@tonic-gate 			return (NULL);
3490Sstevel@tonic-gate 		if (ret) {
3500Sstevel@tonic-gate 			(void) close(ret);
3510Sstevel@tonic-gate 		}
3520Sstevel@tonic-gate 	}
3530Sstevel@tonic-gate 	return (setlocale(category, (char *)NULL));
3540Sstevel@tonic-gate }
3550Sstevel@tonic-gate 
3560Sstevel@tonic-gate int
getlocale_ctype(char * locale,char * ctypep,char * newlocale)357*722Smuffin getlocale_ctype(char *locale, char *ctypep, char *newlocale)
3580Sstevel@tonic-gate {
359*722Smuffin 	int fd;
3600Sstevel@tonic-gate 
3610Sstevel@tonic-gate 	if ((fd = openlocale("LC_CTYPE", LC_CTYPE, locale, newlocale)) > 0) {
3620Sstevel@tonic-gate 		if (read(fd, (char *)ctypep, CTYPE_SIZE) != CTYPE_SIZE) {
3630Sstevel@tonic-gate 			(void) close(fd);
3640Sstevel@tonic-gate 			fd = -1;
3650Sstevel@tonic-gate 		}
3660Sstevel@tonic-gate 		(void) close(fd);
3670Sstevel@tonic-gate 	}
3680Sstevel@tonic-gate 	return (fd);
3690Sstevel@tonic-gate }
3700Sstevel@tonic-gate 
3710Sstevel@tonic-gate /* open and load the numeric information */
3720Sstevel@tonic-gate 
3730Sstevel@tonic-gate char *
getlocale_numeric(char * locale,struct lconv * lconvp,char * newlocale)374*722Smuffin getlocale_numeric(char *locale, struct lconv *lconvp, char *newlocale)
3750Sstevel@tonic-gate {
376*722Smuffin 	int fd;
3770Sstevel@tonic-gate 	struct stat buf;
3780Sstevel@tonic-gate 	char *str;
379*722Smuffin 	char *p;
3800Sstevel@tonic-gate 
3810Sstevel@tonic-gate 	if ((fd = openlocale("LC_NUMERIC", LC_NUMERIC, locale, newlocale)) < 0)
3820Sstevel@tonic-gate 		return (NULL);
3830Sstevel@tonic-gate 	if (fd == 0)
3840Sstevel@tonic-gate 		return "";
3850Sstevel@tonic-gate 	if ((fstat(fd, &buf)) != 0)
3860Sstevel@tonic-gate 		return (NULL);
3870Sstevel@tonic-gate 	if ((str = (char*)malloc((unsigned)buf.st_size + 2)) == NULL)
3880Sstevel@tonic-gate 		return (NULL);
3890Sstevel@tonic-gate 
3900Sstevel@tonic-gate 	if ((read(fd, str, (int)buf.st_size)) != buf.st_size) {
3910Sstevel@tonic-gate 		free((malloc_t)str);
3920Sstevel@tonic-gate 		return (NULL);
3930Sstevel@tonic-gate 	}
3940Sstevel@tonic-gate 
3950Sstevel@tonic-gate 	/* Set last character of str to '\0' */
3960Sstevel@tonic-gate 	p = &str[buf.st_size];
3970Sstevel@tonic-gate 	*p++ = '\n';
3980Sstevel@tonic-gate 	*p = '\0';
3990Sstevel@tonic-gate 
4000Sstevel@tonic-gate 	/* p will "walk thru" str */
4010Sstevel@tonic-gate 	p = str;
4020Sstevel@tonic-gate 
4030Sstevel@tonic-gate 	p = getstr(p, &lconvp->decimal_point);
4040Sstevel@tonic-gate 	if (p == NULL)
4050Sstevel@tonic-gate 		goto fail;
4060Sstevel@tonic-gate 	p = getstr(p, &lconvp->thousands_sep);
4070Sstevel@tonic-gate 	if (p == NULL)
4080Sstevel@tonic-gate 		goto fail;
4090Sstevel@tonic-gate 	p = getgrouping(p, &lconvp->grouping);
4100Sstevel@tonic-gate 	if (p == NULL)
4110Sstevel@tonic-gate 		goto fail;
4120Sstevel@tonic-gate 	(void) close(fd);
4130Sstevel@tonic-gate 
4140Sstevel@tonic-gate 	return (str);
4150Sstevel@tonic-gate 
4160Sstevel@tonic-gate fail:
4170Sstevel@tonic-gate 	(void) close(fd);
4180Sstevel@tonic-gate 	free((malloc_t)str);
4190Sstevel@tonic-gate 	return (NULL);
4200Sstevel@tonic-gate }
4210Sstevel@tonic-gate 
4220Sstevel@tonic-gate 
4230Sstevel@tonic-gate static char *
getlocale_monetary(char * locale,struct lconv * lconvp,char * newlocale)424*722Smuffin getlocale_monetary(char *locale, struct lconv *lconvp, char *newlocale)
4250Sstevel@tonic-gate {
426*722Smuffin 	int fd;
4270Sstevel@tonic-gate 	struct stat buf;
4280Sstevel@tonic-gate 	char *str;
429*722Smuffin 	char *p;
4300Sstevel@tonic-gate 
4310Sstevel@tonic-gate 	if ((fd = openlocale("LC_MONETARY", LC_MONETARY, locale, newlocale)) < 0)
4320Sstevel@tonic-gate 		return (NULL);
4330Sstevel@tonic-gate 	if (fd == 0)
434*722Smuffin 		return ("");
4350Sstevel@tonic-gate 	if ((fstat(fd, &buf)) != 0)
4360Sstevel@tonic-gate 		return (NULL);
4370Sstevel@tonic-gate 	if ((str = (char*)malloc((unsigned)buf.st_size + 2)) == NULL)
4380Sstevel@tonic-gate 		return (NULL);
4390Sstevel@tonic-gate 
4400Sstevel@tonic-gate 	if ((read(fd, str, (int)buf.st_size)) != buf.st_size) {
4410Sstevel@tonic-gate 		free((malloc_t)str);
4420Sstevel@tonic-gate 		return (NULL);
4430Sstevel@tonic-gate 	}
4440Sstevel@tonic-gate 
4450Sstevel@tonic-gate 	/* Set last character of str to '\0' */
4460Sstevel@tonic-gate 	p = &str[buf.st_size];
4470Sstevel@tonic-gate 	*p++ = '\n';
4480Sstevel@tonic-gate 	*p = '\0';
4490Sstevel@tonic-gate 
4500Sstevel@tonic-gate 	/* p will "walk thru" str */
4510Sstevel@tonic-gate 	p = str;
4520Sstevel@tonic-gate 
4530Sstevel@tonic-gate 	p = getstr(p, &lconvp->int_curr_symbol);
4540Sstevel@tonic-gate 	if (p == NULL)
4550Sstevel@tonic-gate 		goto fail;
4560Sstevel@tonic-gate 	p = getstr(p, &lconvp->currency_symbol);
4570Sstevel@tonic-gate 	if (p == NULL)
4580Sstevel@tonic-gate 		goto fail;
4590Sstevel@tonic-gate 	p = getstr(p, &lconvp->mon_decimal_point);
4600Sstevel@tonic-gate 	if (p == NULL)
4610Sstevel@tonic-gate 		goto fail;
4620Sstevel@tonic-gate 	p = getstr(p, &lconvp->mon_thousands_sep);
4630Sstevel@tonic-gate 	if (p == NULL)
4640Sstevel@tonic-gate 		goto fail;
4650Sstevel@tonic-gate 	p = getgrouping(p, &lconvp->mon_grouping);
4660Sstevel@tonic-gate 	if (p == NULL)
4670Sstevel@tonic-gate 		goto fail;
4680Sstevel@tonic-gate 	p = getstr(p, &lconvp->positive_sign);
4690Sstevel@tonic-gate 	if (p == NULL)
4700Sstevel@tonic-gate 		goto fail;
4710Sstevel@tonic-gate 	p = getstr(p, &lconvp->negative_sign);
4720Sstevel@tonic-gate 	if (p == NULL)
4730Sstevel@tonic-gate 		goto fail;
4740Sstevel@tonic-gate 	p = getnum(p, &lconvp->frac_digits);
4750Sstevel@tonic-gate 	if (p == NULL)
4760Sstevel@tonic-gate 		goto fail;
4770Sstevel@tonic-gate 	p = getbool(p, &lconvp->p_cs_precedes);
4780Sstevel@tonic-gate 	if (p == NULL)
4790Sstevel@tonic-gate 		goto fail;
4800Sstevel@tonic-gate 	p = getbool(p, &lconvp->p_sep_by_space);
4810Sstevel@tonic-gate 	if (p == NULL)
4820Sstevel@tonic-gate 		goto fail;
4830Sstevel@tonic-gate 	p = getbool(p, &lconvp->n_cs_precedes);
4840Sstevel@tonic-gate 	if (p == NULL)
4850Sstevel@tonic-gate 		goto fail;
4860Sstevel@tonic-gate 	p = getbool(p, &lconvp->n_sep_by_space);
4870Sstevel@tonic-gate 	if (p == NULL)
4880Sstevel@tonic-gate 		goto fail;
4890Sstevel@tonic-gate 	p = getnum(p, &lconvp->p_sign_posn);
4900Sstevel@tonic-gate 	if (p == NULL)
4910Sstevel@tonic-gate 		goto fail;
4920Sstevel@tonic-gate 	p = getnum(p, &lconvp->n_sign_posn);
4930Sstevel@tonic-gate 	if (p == NULL)
4940Sstevel@tonic-gate 		goto fail;
4950Sstevel@tonic-gate 	(void) close(fd);
4960Sstevel@tonic-gate 
4970Sstevel@tonic-gate 	return (str);
4980Sstevel@tonic-gate 
4990Sstevel@tonic-gate fail:
5000Sstevel@tonic-gate 	(void) close(fd);
5010Sstevel@tonic-gate 	free((malloc_t)str);
502*722Smuffin 	return (NULL);
5030Sstevel@tonic-gate }
5040Sstevel@tonic-gate 
5050Sstevel@tonic-gate static char *
getstr(char * p,char ** strp)506*722Smuffin getstr(char *p, char **strp)
5070Sstevel@tonic-gate {
5080Sstevel@tonic-gate 	*strp = p;
5090Sstevel@tonic-gate 	p = strchr(p, '\n');
5100Sstevel@tonic-gate 	if (p == NULL)
5110Sstevel@tonic-gate 		return (NULL);	/* no end-of-line */
5120Sstevel@tonic-gate 	*p++ = '\0';
5130Sstevel@tonic-gate 	return (p);
5140Sstevel@tonic-gate }
5150Sstevel@tonic-gate 
5160Sstevel@tonic-gate static char *
getgrouping(char * p,char ** groupingp)517*722Smuffin getgrouping(char *p, char **groupingp)
5180Sstevel@tonic-gate {
519*722Smuffin 	int c;
5200Sstevel@tonic-gate 
5210Sstevel@tonic-gate 	if (*p == '\0')
5220Sstevel@tonic-gate 		return (NULL);	/* no grouping */
5230Sstevel@tonic-gate 	*groupingp = p;
5240Sstevel@tonic-gate 	while ((c = *p) != '\n') {
5250Sstevel@tonic-gate 		if (c == '\0')
5260Sstevel@tonic-gate 			return (NULL);	/* no end-of-line */
5270Sstevel@tonic-gate 		if (c >= '0' && c <= '9')
5280Sstevel@tonic-gate 			*p++ = c - '0';
5290Sstevel@tonic-gate 		else
5300Sstevel@tonic-gate 			*p++ = '\177';
5310Sstevel@tonic-gate 	}
5320Sstevel@tonic-gate 	*p++ = '\0';
5330Sstevel@tonic-gate 	return (p);
5340Sstevel@tonic-gate }
5350Sstevel@tonic-gate 
5360Sstevel@tonic-gate static char *
getnum(char * p,char * nump)537*722Smuffin getnum(char *p, char *nump)
5380Sstevel@tonic-gate {
539*722Smuffin 	int num;
540*722Smuffin 	int c;
5410Sstevel@tonic-gate 
5420Sstevel@tonic-gate 	if (*p == '\0')
5430Sstevel@tonic-gate 		return (NULL);	/* no number */
5440Sstevel@tonic-gate 	if (*p == '\n')
5450Sstevel@tonic-gate 		*nump = '\177';	/* blank line - no value */
5460Sstevel@tonic-gate 	else {
5470Sstevel@tonic-gate 		num = 0;
5480Sstevel@tonic-gate 		while ((c = *p) != '\n') {
5490Sstevel@tonic-gate 			if (c < '0' || c > '9')
5500Sstevel@tonic-gate 				return (NULL);	/* bad number */
5510Sstevel@tonic-gate 			num = num*10 + c - '0';
5520Sstevel@tonic-gate 			p++;
5530Sstevel@tonic-gate 		}
5540Sstevel@tonic-gate 		*nump = num;
5550Sstevel@tonic-gate 	}
5560Sstevel@tonic-gate 	*p++ = '\0';
5570Sstevel@tonic-gate 	return (p);
5580Sstevel@tonic-gate }
5590Sstevel@tonic-gate 
5600Sstevel@tonic-gate static char *
getbool(char * p,char * boolp)561*722Smuffin getbool(char *p, char *boolp)
5620Sstevel@tonic-gate {
5630Sstevel@tonic-gate 
5640Sstevel@tonic-gate 	if (*p == '\0')
5650Sstevel@tonic-gate 		return (NULL);	/* no number */
5660Sstevel@tonic-gate 	if (*p == '\n')
5670Sstevel@tonic-gate 		*boolp = '\177';	/* blank line - no value */
5680Sstevel@tonic-gate 	else {
5690Sstevel@tonic-gate 		switch (*p++) {
5700Sstevel@tonic-gate 
5710Sstevel@tonic-gate 		case 'y':
5720Sstevel@tonic-gate 		case 'Y':
5730Sstevel@tonic-gate 		case 't':
5740Sstevel@tonic-gate 		case 'T':
5750Sstevel@tonic-gate 			*boolp = 1;	/* true */
5760Sstevel@tonic-gate 			break;
5770Sstevel@tonic-gate 
5780Sstevel@tonic-gate 		case 'n':
5790Sstevel@tonic-gate 		case 'N':
5800Sstevel@tonic-gate 		case 'f':
5810Sstevel@tonic-gate 		case 'F':
5820Sstevel@tonic-gate 			*boolp = 0;	/* false */
5830Sstevel@tonic-gate 			break;
5840Sstevel@tonic-gate 
5850Sstevel@tonic-gate 		default:
5860Sstevel@tonic-gate 			return (NULL);	/* bad boolean */
5870Sstevel@tonic-gate 		}
5880Sstevel@tonic-gate 		if (*p != '\n')
5890Sstevel@tonic-gate 			return (NULL);	/* noise at end of line */
5900Sstevel@tonic-gate 	}
5910Sstevel@tonic-gate 	*p++ = '\0';
5920Sstevel@tonic-gate 	return (p);
5930Sstevel@tonic-gate }
5940Sstevel@tonic-gate 
5950Sstevel@tonic-gate /*
5960Sstevel@tonic-gate  * Open a locale file.  First, check the value of "locale"; if it's a null
5970Sstevel@tonic-gate  * string, first check the environment variable with the same name as the
5980Sstevel@tonic-gate  * category, and then check the environment variable "LANG".  If neither of
5990Sstevel@tonic-gate  * them are set to non-null strings, use the LC_default env.var and if this
6000Sstevel@tonic-gate  * has no meaning then assume we are running in the C locale. It is expected
6010Sstevel@tonic-gate  * That LC_default is set across the whole system. If the resulting locale is
6020Sstevel@tonic-gate  * longer than MAXLOCALENAME characters, reject it.  Then, try looking in the
6030Sstevel@tonic-gate  * per-machine locale directory for the file in question; if it's not found
6040Sstevel@tonic-gate  * there, try looking in the shared locale directory.
6050Sstevel@tonic-gate  * If there is no work to do, that is, the last setting of locales is equal
6060Sstevel@tonic-gate  * to the current request, then we don't do anything, and exit with value 0.
6070Sstevel@tonic-gate  * Copy the name of the locale used into "newlocale".
6080Sstevel@tonic-gate  * Exit with positive value if we opened a file
6090Sstevel@tonic-gate  * Exit with -1 if an error occured (invalid locale).
6100Sstevel@tonic-gate  * Exit with 0 if there is no need to look at the disk file.
6110Sstevel@tonic-gate  * (Assumption - there is always at least one fd open before setlocale
6120Sstevel@tonic-gate  *  is called)
6130Sstevel@tonic-gate  */
6140Sstevel@tonic-gate int
openlocale(char * category,int cat_id,char * locale,char * newlocale)615*722Smuffin openlocale(char *category, int cat_id, char *locale, char *newlocale)
6160Sstevel@tonic-gate {
6170Sstevel@tonic-gate 	char pathname[MAXPATHLEN], *defp;
6180Sstevel@tonic-gate 	int fd, fd2;
6190Sstevel@tonic-gate 	struct _code_header code_header;
6200Sstevel@tonic-gate 	char *my_info;
6210Sstevel@tonic-gate 
6220Sstevel@tonic-gate 	if (*locale == '\0') {
6230Sstevel@tonic-gate 		locale = getenv(category);
6240Sstevel@tonic-gate 		if (locale == NULL || *locale == '\0') {
6250Sstevel@tonic-gate 			locale = getenv("LANG");
6260Sstevel@tonic-gate 			if (locale == NULL || *locale == '\0') {
6270Sstevel@tonic-gate 				if (*Default == '\0') {
6280Sstevel@tonic-gate 					defp = getenv("LC_default");
6290Sstevel@tonic-gate 					if (defp == NULL || *defp == '\0')
6300Sstevel@tonic-gate 						strcpy(Default,"C");
6310Sstevel@tonic-gate 					else
6320Sstevel@tonic-gate 						strcpy(Default, defp);
6330Sstevel@tonic-gate 				}
6340Sstevel@tonic-gate 				locale = Default;
6350Sstevel@tonic-gate 			}
6360Sstevel@tonic-gate 		}
6370Sstevel@tonic-gate 	}
6380Sstevel@tonic-gate 	if (strcmp(locale,_locales[cat_id-1]) == 0) {
6390Sstevel@tonic-gate 		(void) strcpy(newlocale, locale);
640*722Smuffin 		return (0);
6410Sstevel@tonic-gate 	}
6420Sstevel@tonic-gate 	if (strlen(locale) > MAXLOCALENAME)
643*722Smuffin 		return (-1);
6440Sstevel@tonic-gate 
6450Sstevel@tonic-gate 	(void) strcpy(pathname, PRIVATE_LOCALE_DIR);
6460Sstevel@tonic-gate 	(void) strcat(pathname, category);
6470Sstevel@tonic-gate 	(void) strcat(pathname, "/");
6480Sstevel@tonic-gate 	(void) strcat(pathname, locale);
6490Sstevel@tonic-gate 	if ((fd = open(pathname, O_RDONLY)) < 0 && errno == ENOENT) {
6500Sstevel@tonic-gate 		(void) strcpy(pathname, LOCALE_DIR);
6510Sstevel@tonic-gate 		(void) strcat(pathname, category);
6520Sstevel@tonic-gate 		(void) strcat(pathname, "/");
6530Sstevel@tonic-gate 		(void) strcat(pathname, locale);
6540Sstevel@tonic-gate 		fd = open(pathname, O_RDONLY);
6550Sstevel@tonic-gate 	}
6560Sstevel@tonic-gate 	if (fd >= 0)
6570Sstevel@tonic-gate 		(void) strcpy(newlocale, locale);
6580Sstevel@tonic-gate 	/*
6590Sstevel@tonic-gate 	 * bug id 1072740; if by some chance the actual fd we're going to
6600Sstevel@tonic-gate 	 * return is 0, change it to be some non-zero descriptor, because
6610Sstevel@tonic-gate 	 * returning 0 means something different.  If '0' is the only
6620Sstevel@tonic-gate 	 * descriptor left, return an error.
6630Sstevel@tonic-gate 	 */
6640Sstevel@tonic-gate 	if (fd == 0) {
6650Sstevel@tonic-gate 		int dupfd;
6660Sstevel@tonic-gate 
6670Sstevel@tonic-gate 		if ((dupfd = dup(fd)) < 1) {
6680Sstevel@tonic-gate 			(void) close(fd);
6690Sstevel@tonic-gate 			fd = -1;
6700Sstevel@tonic-gate 		} else {
6710Sstevel@tonic-gate 			(void) close(fd);
6720Sstevel@tonic-gate 			fd = dupfd;
6730Sstevel@tonic-gate 		}
6740Sstevel@tonic-gate 	}
6750Sstevel@tonic-gate 
6760Sstevel@tonic-gate 	if (cat_id == LC_CTYPE) {
6770Sstevel@tonic-gate 
6780Sstevel@tonic-gate 		/* Go and get the trailer file */
6790Sstevel@tonic-gate 
6800Sstevel@tonic-gate 		(void) strcat(pathname, TRAILER);
6810Sstevel@tonic-gate 		fd2 = open(pathname, O_RDONLY);
6820Sstevel@tonic-gate                 if ( fd2 == 0 ) {
6830Sstevel@tonic-gate                         fd2 = dup(fd2);
6840Sstevel@tonic-gate                         close(0);
6850Sstevel@tonic-gate                 }
6860Sstevel@tonic-gate 
6870Sstevel@tonic-gate 		if (fd2 == -1)  {
6880Sstevel@tonic-gate 			set_default();
689*722Smuffin 			return (fd);
6900Sstevel@tonic-gate 		}
6910Sstevel@tonic-gate 
6920Sstevel@tonic-gate 		/*
6930Sstevel@tonic-gate 		 * ctype trailer file  exists - read it
6940Sstevel@tonic-gate 		 */
6950Sstevel@tonic-gate 
6960Sstevel@tonic-gate 		if (read (fd2, (char *)&code_header, sizeof (code_header)) !=
6970Sstevel@tonic-gate 						    sizeof (code_header)) {
6980Sstevel@tonic-gate 			/*
6990Sstevel@tonic-gate 			 * File format not correct
7000Sstevel@tonic-gate 			 */
7010Sstevel@tonic-gate 			 set_default();
7020Sstevel@tonic-gate 			 close(fd2);
703*722Smuffin 			 return (-1);
7040Sstevel@tonic-gate 		}
7050Sstevel@tonic-gate 		/*
7060Sstevel@tonic-gate 		 * set up trailer file
7070Sstevel@tonic-gate 		 */
7080Sstevel@tonic-gate 		 strcpy(_code_set_info.code_name, code_header.code_name);
7090Sstevel@tonic-gate 		 _code_set_info.code_id = code_header.code_id;
7100Sstevel@tonic-gate 		 if (_code_set_info.code_info != NULL)
7110Sstevel@tonic-gate 			free (_code_set_info.code_info);
7120Sstevel@tonic-gate 		 if (code_header.code_info_size > 0)  {
7130Sstevel@tonic-gate 			my_info = malloc(code_header.code_info_size);
7140Sstevel@tonic-gate 			if (read (fd2, (char *)my_info,
7150Sstevel@tonic-gate 			 code_header.code_info_size) !=
7160Sstevel@tonic-gate 		 	 code_header.code_info_size) {
7170Sstevel@tonic-gate 					close(fd2);
7180Sstevel@tonic-gate 					set_default();
719*722Smuffin 					return (-1);
7200Sstevel@tonic-gate 				}
7210Sstevel@tonic-gate 			_code_set_info.code_info = my_info;
7220Sstevel@tonic-gate 		 }
7230Sstevel@tonic-gate 		 else {
7240Sstevel@tonic-gate 		 /*
7250Sstevel@tonic-gate 		  * We have a corrupted file too
7260Sstevel@tonic-gate 		  */
7270Sstevel@tonic-gate 			_code_set_info.code_info = NULL;
7280Sstevel@tonic-gate 			close(fd2);
7290Sstevel@tonic-gate 			set_default();
730*722Smuffin 			return (-1);
7310Sstevel@tonic-gate 		 }
7320Sstevel@tonic-gate 		 close (fd2);
7330Sstevel@tonic-gate 	}
734*722Smuffin 	return (fd);
7350Sstevel@tonic-gate }
7360Sstevel@tonic-gate 
7370Sstevel@tonic-gate struct	lconv *
localeconv(void)738*722Smuffin localeconv(void)
7390Sstevel@tonic-gate {
7400Sstevel@tonic-gate 	return (lconv);
7410Sstevel@tonic-gate }
7420Sstevel@tonic-gate 
7430Sstevel@tonic-gate struct	dtconv *
localdtconv(void)744*722Smuffin localdtconv(void)
7450Sstevel@tonic-gate {
746*722Smuffin 	char *p;
747*722Smuffin 	short i;
7480Sstevel@tonic-gate 
7490Sstevel@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";
7500Sstevel@tonic-gate 
7510Sstevel@tonic-gate 	char *rawdays = "Sun\nMon\nTue\nWed\nThu\nFri\nSat\nSunday\nMonday\nTuesday\nWednesday\nThursday\nFriday\nSaturday";
7520Sstevel@tonic-gate 
7530Sstevel@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";
7540Sstevel@tonic-gate 
7550Sstevel@tonic-gate 	/* fix for bugid 1067574 ... robinson */
7560Sstevel@tonic-gate         (void)getlocale_time();
7570Sstevel@tonic-gate 
7580Sstevel@tonic-gate 	if (_dtconv == NULL) {
7590Sstevel@tonic-gate 
7600Sstevel@tonic-gate 		/* We malloc both the space for the dtconv struct and the
7610Sstevel@tonic-gate 		 * copy of the strings above because this program is later run
7620Sstevel@tonic-gate 		 * through xstr and the resultant strings are put in read-only
7630Sstevel@tonic-gate 		 * text segment. Therefore we cannot write to the original
7640Sstevel@tonic-gate 		 * raw strings but we can to their copies.
7650Sstevel@tonic-gate 		 */
7660Sstevel@tonic-gate 
7670Sstevel@tonic-gate 		_dtconv = (struct dtconv*)malloc(sizeof (struct dtconv));
7680Sstevel@tonic-gate 		if (_dtconv == NULL)
7690Sstevel@tonic-gate 			return (NULL);
7700Sstevel@tonic-gate 		if ((realmonths = malloc(strlen(rawmonths)+1)) == NULL)
7710Sstevel@tonic-gate 			return (NULL);
7720Sstevel@tonic-gate 		strcpy(realmonths, rawmonths);
7730Sstevel@tonic-gate 		if ((realdays = malloc(strlen(rawdays)+1)) == NULL)
7740Sstevel@tonic-gate 			return (NULL);
7750Sstevel@tonic-gate 		strcpy(realdays, rawdays);
7760Sstevel@tonic-gate 		if ((realfmts = malloc(strlen(rawfmts)+1)) == NULL)
7770Sstevel@tonic-gate 			return (NULL);
7780Sstevel@tonic-gate 		strcpy(realfmts, rawfmts);
7790Sstevel@tonic-gate 
7800Sstevel@tonic-gate 		/* p will "walk thru" str */
7810Sstevel@tonic-gate 
7820Sstevel@tonic-gate 		p = realmonths;
7830Sstevel@tonic-gate 
7840Sstevel@tonic-gate 		for (i = 0; i < 12; i++)
7850Sstevel@tonic-gate 			p = getstr(p, &(_dtconv->abbrev_month_names[i]));
7860Sstevel@tonic-gate 
7870Sstevel@tonic-gate 		for (i = 0; i < 12; i++)
7880Sstevel@tonic-gate 			p = getstr(p, &(_dtconv->month_names[i]));
7890Sstevel@tonic-gate 		p = realdays;
7900Sstevel@tonic-gate 		for (i= 0; i < 7; i++)
7910Sstevel@tonic-gate 			p = getstr(p, &(_dtconv->abbrev_weekday_names[i]));
7920Sstevel@tonic-gate 		for (i = 0; i < 7; i++)
7930Sstevel@tonic-gate 			p = getstr(p, &(_dtconv->weekday_names[i]));
7940Sstevel@tonic-gate 		p = realfmts;
7950Sstevel@tonic-gate 		p = getstr(p, &_dtconv->time_format);
7960Sstevel@tonic-gate 		p = getstr(p, &_dtconv->sdate_format);
7970Sstevel@tonic-gate 		p = getstr(p, &_dtconv->dtime_format);
7980Sstevel@tonic-gate 		p = getstr(p, &_dtconv->am_string);
7990Sstevel@tonic-gate 		p = getstr(p, &_dtconv->pm_string);
8000Sstevel@tonic-gate 		p = getstr(p, &_dtconv->ldate_format);
8010Sstevel@tonic-gate 	}
8020Sstevel@tonic-gate 
8030Sstevel@tonic-gate 	return (_dtconv);
8040Sstevel@tonic-gate }
8050Sstevel@tonic-gate 
8060Sstevel@tonic-gate 
807*722Smuffin static void
set_default(void)808*722Smuffin set_default(void)
8090Sstevel@tonic-gate {
8100Sstevel@tonic-gate 
8110Sstevel@tonic-gate 	strcpy(_code_set_info.code_name, Default);
8120Sstevel@tonic-gate 	_code_set_info.code_id = CODESET_NONE;
8130Sstevel@tonic-gate 	if (_code_set_info.code_info != NULL)
8140Sstevel@tonic-gate 		free (_code_set_info.code_info);
8150Sstevel@tonic-gate 	_code_set_info.code_info = NULL;
8160Sstevel@tonic-gate 	_code_set_info.open_flag = 0;
8170Sstevel@tonic-gate }
8180Sstevel@tonic-gate 
819*722Smuffin void
init_statics(void)820*722Smuffin init_statics(void)
821*722Smuffin {
8220Sstevel@tonic-gate 
823*722Smuffin 	short i;
8240Sstevel@tonic-gate 
825*722Smuffin 	for (i=0; i<MAXLOCALE-1;i++)
826*722Smuffin 		strcpy(_locales[i],"C");
827*722Smuffin 	strcpy(_code_set_info.code_name, "default");
828*722Smuffin 	strcpy(_my_time,"C");
829*722Smuffin 	_langinfo.yesstr = "yes";
830*722Smuffin 	_langinfo.nostr = "no";
8310Sstevel@tonic-gate }
832