1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2003 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate /* 28*7c478bd9Sstevel@tonic-gate * locale -- get current locale information 29*7c478bd9Sstevel@tonic-gate * 30*7c478bd9Sstevel@tonic-gate * Copyright 1991, 1993 by Mortice Kern Systems Inc. All rights reserved. 31*7c478bd9Sstevel@tonic-gate * 32*7c478bd9Sstevel@tonic-gate */ 33*7c478bd9Sstevel@tonic-gate 34*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 35*7c478bd9Sstevel@tonic-gate 36*7c478bd9Sstevel@tonic-gate /* 37*7c478bd9Sstevel@tonic-gate * locale: get locale-specific information 38*7c478bd9Sstevel@tonic-gate * usage: locale [-a|-m] 39*7c478bd9Sstevel@tonic-gate * locale [-ck] name ... 40*7c478bd9Sstevel@tonic-gate */ 41*7c478bd9Sstevel@tonic-gate 42*7c478bd9Sstevel@tonic-gate /* 43*7c478bd9Sstevel@tonic-gate * New members added in the struct lconv by IEEE Std 1003.1-2001 44*7c478bd9Sstevel@tonic-gate * are always activated in the locale object. 45*7c478bd9Sstevel@tonic-gate * See <iso/locale_iso.h>. 46*7c478bd9Sstevel@tonic-gate */ 47*7c478bd9Sstevel@tonic-gate #define _LCONV_C99 48*7c478bd9Sstevel@tonic-gate 49*7c478bd9Sstevel@tonic-gate #include <stdio.h> 50*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 51*7c478bd9Sstevel@tonic-gate #include <limits.h> 52*7c478bd9Sstevel@tonic-gate #include <string.h> 53*7c478bd9Sstevel@tonic-gate #include <dirent.h> 54*7c478bd9Sstevel@tonic-gate #include <ctype.h> 55*7c478bd9Sstevel@tonic-gate #include <stddef.h> 56*7c478bd9Sstevel@tonic-gate #include <nl_types.h> 57*7c478bd9Sstevel@tonic-gate #include <langinfo.h> 58*7c478bd9Sstevel@tonic-gate #include <locale.h> 59*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 60*7c478bd9Sstevel@tonic-gate #include <sys/stat.h> 61*7c478bd9Sstevel@tonic-gate 62*7c478bd9Sstevel@tonic-gate #define LC_LOCDEF 999 /* Random number! */ 63*7c478bd9Sstevel@tonic-gate 64*7c478bd9Sstevel@tonic-gate #define LOCALE_DIR "/usr/lib/locale/" 65*7c478bd9Sstevel@tonic-gate #define CHARMAP_DIR "/usr/lib/localedef/src/" 66*7c478bd9Sstevel@tonic-gate #define CHARMAP_NAME "charmap.src" 67*7c478bd9Sstevel@tonic-gate 68*7c478bd9Sstevel@tonic-gate #define GET_LOCALE 0 69*7c478bd9Sstevel@tonic-gate #define GET_CHARMAP 1 70*7c478bd9Sstevel@tonic-gate #define CSSIZE 128 71*7c478bd9Sstevel@tonic-gate 72*7c478bd9Sstevel@tonic-gate #ifndef isblank 73*7c478bd9Sstevel@tonic-gate #define isblank(c) ((__ctype + 1)[c] & _B) 74*7c478bd9Sstevel@tonic-gate #endif 75*7c478bd9Sstevel@tonic-gate 76*7c478bd9Sstevel@tonic-gate enum types { 77*7c478bd9Sstevel@tonic-gate TYPE_STR, /* char * */ 78*7c478bd9Sstevel@tonic-gate TYPE_GROUP, /* char *, for mon_grouping, and grouping */ 79*7c478bd9Sstevel@tonic-gate TYPE_INT, /* int */ 80*7c478bd9Sstevel@tonic-gate TYPE_CHR, /* char, printed as signed integer */ 81*7c478bd9Sstevel@tonic-gate TYPE_PCHR, /* char, printed as printable character */ 82*7c478bd9Sstevel@tonic-gate TYPE_CTP, /* ctype entry */ 83*7c478bd9Sstevel@tonic-gate TYPE_CNVL, /* convert to lower */ 84*7c478bd9Sstevel@tonic-gate TYPE_CNVU, /* convert to upper */ 85*7c478bd9Sstevel@tonic-gate TYPE_COLLEL /* print the multi-character collating elements */ 86*7c478bd9Sstevel@tonic-gate }; 87*7c478bd9Sstevel@tonic-gate 88*7c478bd9Sstevel@tonic-gate static int print_locale_info(char *keyword, int cflag, int kflag); 89*7c478bd9Sstevel@tonic-gate static int print_category(int category, int cflag, int kflag); 90*7c478bd9Sstevel@tonic-gate static int print_keyword(char *name, int cflag, int kflag); 91*7c478bd9Sstevel@tonic-gate static void usage(void); 92*7c478bd9Sstevel@tonic-gate static void print_all_info(int); 93*7c478bd9Sstevel@tonic-gate static void print_cur_locale(void); 94*7c478bd9Sstevel@tonic-gate static void outstr(char *s); 95*7c478bd9Sstevel@tonic-gate static void outchar(int); 96*7c478bd9Sstevel@tonic-gate static void prt_ctp(char *); 97*7c478bd9Sstevel@tonic-gate static void prt_cnv(char *); 98*7c478bd9Sstevel@tonic-gate static void prt_collel(char *); 99*7c478bd9Sstevel@tonic-gate static char get_escapechar(void); 100*7c478bd9Sstevel@tonic-gate static char get_commentchar(void); 101*7c478bd9Sstevel@tonic-gate 102*7c478bd9Sstevel@tonic-gate static char *save_loc; 103*7c478bd9Sstevel@tonic-gate 104*7c478bd9Sstevel@tonic-gate /* 105*7c478bd9Sstevel@tonic-gate * yes/no is not in the localeconv structure for xpg style. 106*7c478bd9Sstevel@tonic-gate * We dummy up a new structure for purposes of the code below. 107*7c478bd9Sstevel@tonic-gate * If YESEXPR is available per XPG4, we use it. 108*7c478bd9Sstevel@tonic-gate * Otherwise, use YESSTR, the old method with less functionality from XPG3. 109*7c478bd9Sstevel@tonic-gate */ 110*7c478bd9Sstevel@tonic-gate struct yesno { 111*7c478bd9Sstevel@tonic-gate char *yes_expr; 112*7c478bd9Sstevel@tonic-gate char *no_expr; 113*7c478bd9Sstevel@tonic-gate char *yes_str; 114*7c478bd9Sstevel@tonic-gate char *no_str; 115*7c478bd9Sstevel@tonic-gate }; 116*7c478bd9Sstevel@tonic-gate 117*7c478bd9Sstevel@tonic-gate struct dtconv { 118*7c478bd9Sstevel@tonic-gate char *date_time_format; 119*7c478bd9Sstevel@tonic-gate char *date_format; 120*7c478bd9Sstevel@tonic-gate char *time_format; 121*7c478bd9Sstevel@tonic-gate char *time_format_ampm; 122*7c478bd9Sstevel@tonic-gate char *am_string; 123*7c478bd9Sstevel@tonic-gate char *pm_string; 124*7c478bd9Sstevel@tonic-gate char *abbrev_day_names[7]; 125*7c478bd9Sstevel@tonic-gate char *day_names[7]; 126*7c478bd9Sstevel@tonic-gate char *abbrev_month_names[12]; 127*7c478bd9Sstevel@tonic-gate char *month_names[12]; 128*7c478bd9Sstevel@tonic-gate char *era; 129*7c478bd9Sstevel@tonic-gate char *era_d_fmt; 130*7c478bd9Sstevel@tonic-gate char *era_d_t_fmt; 131*7c478bd9Sstevel@tonic-gate char *era_t_fmt; 132*7c478bd9Sstevel@tonic-gate char *alt_digits; 133*7c478bd9Sstevel@tonic-gate }; 134*7c478bd9Sstevel@tonic-gate 135*7c478bd9Sstevel@tonic-gate struct localedef { 136*7c478bd9Sstevel@tonic-gate char *charmap; 137*7c478bd9Sstevel@tonic-gate char *code_set_name; 138*7c478bd9Sstevel@tonic-gate char escape_char; 139*7c478bd9Sstevel@tonic-gate char comment_char; 140*7c478bd9Sstevel@tonic-gate int mb_cur_max; 141*7c478bd9Sstevel@tonic-gate int mb_cur_min; 142*7c478bd9Sstevel@tonic-gate }; 143*7c478bd9Sstevel@tonic-gate 144*7c478bd9Sstevel@tonic-gate static struct yesno * 145*7c478bd9Sstevel@tonic-gate getyesno(void) 146*7c478bd9Sstevel@tonic-gate { 147*7c478bd9Sstevel@tonic-gate static struct yesno yn; 148*7c478bd9Sstevel@tonic-gate static int loaded = 0; 149*7c478bd9Sstevel@tonic-gate 150*7c478bd9Sstevel@tonic-gate if (loaded) { 151*7c478bd9Sstevel@tonic-gate return (&yn); 152*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 153*7c478bd9Sstevel@tonic-gate } 154*7c478bd9Sstevel@tonic-gate 155*7c478bd9Sstevel@tonic-gate yn.yes_expr = strdup(nl_langinfo(YESEXPR)); 156*7c478bd9Sstevel@tonic-gate yn.no_expr = strdup(nl_langinfo(NOEXPR)); 157*7c478bd9Sstevel@tonic-gate yn.yes_str = strdup(nl_langinfo(YESSTR)); 158*7c478bd9Sstevel@tonic-gate yn.no_str = strdup(nl_langinfo(NOSTR)); 159*7c478bd9Sstevel@tonic-gate 160*7c478bd9Sstevel@tonic-gate loaded = 1; 161*7c478bd9Sstevel@tonic-gate return (&yn); 162*7c478bd9Sstevel@tonic-gate } 163*7c478bd9Sstevel@tonic-gate 164*7c478bd9Sstevel@tonic-gate static struct dtconv * 165*7c478bd9Sstevel@tonic-gate localedtconv(void) 166*7c478bd9Sstevel@tonic-gate { 167*7c478bd9Sstevel@tonic-gate static struct dtconv _dtconv; 168*7c478bd9Sstevel@tonic-gate static int loaded = 0; 169*7c478bd9Sstevel@tonic-gate 170*7c478bd9Sstevel@tonic-gate if (loaded) { 171*7c478bd9Sstevel@tonic-gate return (&_dtconv); 172*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 173*7c478bd9Sstevel@tonic-gate } 174*7c478bd9Sstevel@tonic-gate 175*7c478bd9Sstevel@tonic-gate _dtconv.date_time_format = strdup(nl_langinfo(D_T_FMT)); 176*7c478bd9Sstevel@tonic-gate _dtconv.date_format = strdup(nl_langinfo(D_FMT)); 177*7c478bd9Sstevel@tonic-gate _dtconv.time_format = strdup(nl_langinfo(T_FMT)); 178*7c478bd9Sstevel@tonic-gate _dtconv.time_format_ampm = strdup(nl_langinfo(T_FMT_AMPM)); 179*7c478bd9Sstevel@tonic-gate _dtconv.am_string = strdup(nl_langinfo(AM_STR)); 180*7c478bd9Sstevel@tonic-gate _dtconv.pm_string = strdup(nl_langinfo(PM_STR)); 181*7c478bd9Sstevel@tonic-gate _dtconv.abbrev_day_names[0] = strdup(nl_langinfo(ABDAY_1)); 182*7c478bd9Sstevel@tonic-gate _dtconv.abbrev_day_names[1] = strdup(nl_langinfo(ABDAY_2)); 183*7c478bd9Sstevel@tonic-gate _dtconv.abbrev_day_names[2] = strdup(nl_langinfo(ABDAY_3)); 184*7c478bd9Sstevel@tonic-gate _dtconv.abbrev_day_names[3] = strdup(nl_langinfo(ABDAY_4)); 185*7c478bd9Sstevel@tonic-gate _dtconv.abbrev_day_names[4] = strdup(nl_langinfo(ABDAY_5)); 186*7c478bd9Sstevel@tonic-gate _dtconv.abbrev_day_names[5] = strdup(nl_langinfo(ABDAY_6)); 187*7c478bd9Sstevel@tonic-gate _dtconv.abbrev_day_names[6] = strdup(nl_langinfo(ABDAY_7)); 188*7c478bd9Sstevel@tonic-gate _dtconv.day_names[0] = strdup(nl_langinfo(DAY_1)); 189*7c478bd9Sstevel@tonic-gate _dtconv.day_names[1] = strdup(nl_langinfo(DAY_2)); 190*7c478bd9Sstevel@tonic-gate _dtconv.day_names[2] = strdup(nl_langinfo(DAY_3)); 191*7c478bd9Sstevel@tonic-gate _dtconv.day_names[3] = strdup(nl_langinfo(DAY_4)); 192*7c478bd9Sstevel@tonic-gate _dtconv.day_names[4] = strdup(nl_langinfo(DAY_5)); 193*7c478bd9Sstevel@tonic-gate _dtconv.day_names[5] = strdup(nl_langinfo(DAY_6)); 194*7c478bd9Sstevel@tonic-gate _dtconv.day_names[6] = strdup(nl_langinfo(DAY_7)); 195*7c478bd9Sstevel@tonic-gate _dtconv.abbrev_month_names[0] = strdup(nl_langinfo(ABMON_1)); 196*7c478bd9Sstevel@tonic-gate _dtconv.abbrev_month_names[1] = strdup(nl_langinfo(ABMON_2)); 197*7c478bd9Sstevel@tonic-gate _dtconv.abbrev_month_names[2] = strdup(nl_langinfo(ABMON_3)); 198*7c478bd9Sstevel@tonic-gate _dtconv.abbrev_month_names[3] = strdup(nl_langinfo(ABMON_4)); 199*7c478bd9Sstevel@tonic-gate _dtconv.abbrev_month_names[4] = strdup(nl_langinfo(ABMON_5)); 200*7c478bd9Sstevel@tonic-gate _dtconv.abbrev_month_names[5] = strdup(nl_langinfo(ABMON_6)); 201*7c478bd9Sstevel@tonic-gate _dtconv.abbrev_month_names[6] = strdup(nl_langinfo(ABMON_7)); 202*7c478bd9Sstevel@tonic-gate _dtconv.abbrev_month_names[7] = strdup(nl_langinfo(ABMON_8)); 203*7c478bd9Sstevel@tonic-gate _dtconv.abbrev_month_names[8] = strdup(nl_langinfo(ABMON_9)); 204*7c478bd9Sstevel@tonic-gate _dtconv.abbrev_month_names[9] = strdup(nl_langinfo(ABMON_10)); 205*7c478bd9Sstevel@tonic-gate _dtconv.abbrev_month_names[10] = strdup(nl_langinfo(ABMON_11)); 206*7c478bd9Sstevel@tonic-gate _dtconv.abbrev_month_names[11] = strdup(nl_langinfo(ABMON_12)); 207*7c478bd9Sstevel@tonic-gate _dtconv.month_names[0] = strdup(nl_langinfo(MON_1)); 208*7c478bd9Sstevel@tonic-gate _dtconv.month_names[1] = strdup(nl_langinfo(MON_2)); 209*7c478bd9Sstevel@tonic-gate _dtconv.month_names[2] = strdup(nl_langinfo(MON_3)); 210*7c478bd9Sstevel@tonic-gate _dtconv.month_names[3] = strdup(nl_langinfo(MON_4)); 211*7c478bd9Sstevel@tonic-gate _dtconv.month_names[4] = strdup(nl_langinfo(MON_5)); 212*7c478bd9Sstevel@tonic-gate _dtconv.month_names[5] = strdup(nl_langinfo(MON_6)); 213*7c478bd9Sstevel@tonic-gate _dtconv.month_names[6] = strdup(nl_langinfo(MON_7)); 214*7c478bd9Sstevel@tonic-gate _dtconv.month_names[7] = strdup(nl_langinfo(MON_8)); 215*7c478bd9Sstevel@tonic-gate _dtconv.month_names[8] = strdup(nl_langinfo(MON_9)); 216*7c478bd9Sstevel@tonic-gate _dtconv.month_names[9] = strdup(nl_langinfo(MON_10)); 217*7c478bd9Sstevel@tonic-gate _dtconv.month_names[10] = strdup(nl_langinfo(MON_11)); 218*7c478bd9Sstevel@tonic-gate _dtconv.month_names[11] = strdup(nl_langinfo(MON_12)); 219*7c478bd9Sstevel@tonic-gate _dtconv.era = strdup(nl_langinfo(ERA)); 220*7c478bd9Sstevel@tonic-gate _dtconv.era_d_fmt = strdup(nl_langinfo(ERA_D_FMT)); 221*7c478bd9Sstevel@tonic-gate _dtconv.era_d_t_fmt = strdup(nl_langinfo(ERA_D_T_FMT)); 222*7c478bd9Sstevel@tonic-gate _dtconv.era_t_fmt = strdup(nl_langinfo(ERA_T_FMT)); 223*7c478bd9Sstevel@tonic-gate _dtconv.alt_digits = strdup(nl_langinfo(ALT_DIGITS)); 224*7c478bd9Sstevel@tonic-gate 225*7c478bd9Sstevel@tonic-gate loaded = 1; 226*7c478bd9Sstevel@tonic-gate return (&_dtconv); 227*7c478bd9Sstevel@tonic-gate } 228*7c478bd9Sstevel@tonic-gate 229*7c478bd9Sstevel@tonic-gate static struct localedef * 230*7c478bd9Sstevel@tonic-gate localeldconv(void) 231*7c478bd9Sstevel@tonic-gate { 232*7c478bd9Sstevel@tonic-gate static struct localedef _locdef; 233*7c478bd9Sstevel@tonic-gate static int loaded = 0; 234*7c478bd9Sstevel@tonic-gate 235*7c478bd9Sstevel@tonic-gate if (loaded) { 236*7c478bd9Sstevel@tonic-gate return (&_locdef); 237*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 238*7c478bd9Sstevel@tonic-gate } 239*7c478bd9Sstevel@tonic-gate 240*7c478bd9Sstevel@tonic-gate _locdef.charmap = strdup(nl_langinfo(CODESET)); 241*7c478bd9Sstevel@tonic-gate _locdef.code_set_name = strdup(nl_langinfo(CODESET)); 242*7c478bd9Sstevel@tonic-gate _locdef.mb_cur_max = MB_CUR_MAX; 243*7c478bd9Sstevel@tonic-gate _locdef.mb_cur_min = 1; 244*7c478bd9Sstevel@tonic-gate _locdef.escape_char = get_escapechar(); 245*7c478bd9Sstevel@tonic-gate _locdef.comment_char = get_commentchar(); 246*7c478bd9Sstevel@tonic-gate 247*7c478bd9Sstevel@tonic-gate loaded = 1; 248*7c478bd9Sstevel@tonic-gate return (&_locdef); 249*7c478bd9Sstevel@tonic-gate } 250*7c478bd9Sstevel@tonic-gate 251*7c478bd9Sstevel@tonic-gate /* 252*7c478bd9Sstevel@tonic-gate * The locale_name array also defines a canonical ordering for the categories. 253*7c478bd9Sstevel@tonic-gate * The function tocanon() translates the LC_* manifests to their canonical 254*7c478bd9Sstevel@tonic-gate * values. 255*7c478bd9Sstevel@tonic-gate */ 256*7c478bd9Sstevel@tonic-gate static struct locale_name { 257*7c478bd9Sstevel@tonic-gate char *name; 258*7c478bd9Sstevel@tonic-gate int category; 259*7c478bd9Sstevel@tonic-gate } locale_name[] = { 260*7c478bd9Sstevel@tonic-gate {"LC_CTYPE", LC_CTYPE}, 261*7c478bd9Sstevel@tonic-gate {"LC_NUMERIC", LC_NUMERIC}, 262*7c478bd9Sstevel@tonic-gate {"LC_TIME", LC_TIME}, 263*7c478bd9Sstevel@tonic-gate {"LC_COLLATE", LC_COLLATE}, 264*7c478bd9Sstevel@tonic-gate {"LC_MONETARY", LC_MONETARY}, 265*7c478bd9Sstevel@tonic-gate {"LC_MESSAGES", LC_MESSAGES}, 266*7c478bd9Sstevel@tonic-gate {"LC_ALL", LC_ALL}, 267*7c478bd9Sstevel@tonic-gate NULL 268*7c478bd9Sstevel@tonic-gate }; 269*7c478bd9Sstevel@tonic-gate 270*7c478bd9Sstevel@tonic-gate /* 271*7c478bd9Sstevel@tonic-gate * The structure key contains all keywords string name, 272*7c478bd9Sstevel@tonic-gate * symbolic name, category, and type (STR INT ...) 273*7c478bd9Sstevel@tonic-gate * the type will decide the way the value of the item be printed out 274*7c478bd9Sstevel@tonic-gate */ 275*7c478bd9Sstevel@tonic-gate static struct key { 276*7c478bd9Sstevel@tonic-gate char *name; 277*7c478bd9Sstevel@tonic-gate void *(*structure)(void); 278*7c478bd9Sstevel@tonic-gate int offset; 279*7c478bd9Sstevel@tonic-gate int count; 280*7c478bd9Sstevel@tonic-gate int category; 281*7c478bd9Sstevel@tonic-gate enum types type; 282*7c478bd9Sstevel@tonic-gate } key[] = { 283*7c478bd9Sstevel@tonic-gate 284*7c478bd9Sstevel@tonic-gate #define SPECIAL 0, 0, 0, 285*7c478bd9Sstevel@tonic-gate {"lower", SPECIAL LC_CTYPE, TYPE_CTP}, 286*7c478bd9Sstevel@tonic-gate {"upper", SPECIAL LC_CTYPE, TYPE_CTP}, 287*7c478bd9Sstevel@tonic-gate {"alpha", SPECIAL LC_CTYPE, TYPE_CTP}, 288*7c478bd9Sstevel@tonic-gate {"digit", SPECIAL LC_CTYPE, TYPE_CTP}, 289*7c478bd9Sstevel@tonic-gate {"space", SPECIAL LC_CTYPE, TYPE_CTP}, 290*7c478bd9Sstevel@tonic-gate {"cntrl", SPECIAL LC_CTYPE, TYPE_CTP}, 291*7c478bd9Sstevel@tonic-gate {"punct", SPECIAL LC_CTYPE, TYPE_CTP}, 292*7c478bd9Sstevel@tonic-gate {"graph", SPECIAL LC_CTYPE, TYPE_CTP}, 293*7c478bd9Sstevel@tonic-gate {"print", SPECIAL LC_CTYPE, TYPE_CTP}, 294*7c478bd9Sstevel@tonic-gate {"xdigit", SPECIAL LC_CTYPE, TYPE_CTP}, 295*7c478bd9Sstevel@tonic-gate {"blank", SPECIAL LC_CTYPE, TYPE_CTP}, 296*7c478bd9Sstevel@tonic-gate 297*7c478bd9Sstevel@tonic-gate {"tolower", SPECIAL LC_CTYPE, TYPE_CNVL}, 298*7c478bd9Sstevel@tonic-gate {"toupper", SPECIAL LC_CTYPE, TYPE_CNVU}, 299*7c478bd9Sstevel@tonic-gate 300*7c478bd9Sstevel@tonic-gate {"collating-element", 0, 0, 0, LC_COLLATE, TYPE_COLLEL}, 301*7c478bd9Sstevel@tonic-gate {"character-collation", 0, 1, 0, LC_COLLATE, TYPE_COLLEL}, 302*7c478bd9Sstevel@tonic-gate 303*7c478bd9Sstevel@tonic-gate #define dt(member, count) \ 304*7c478bd9Sstevel@tonic-gate (void *(*)(void))localedtconv, \ 305*7c478bd9Sstevel@tonic-gate offsetof(struct dtconv, member), \ 306*7c478bd9Sstevel@tonic-gate count, \ 307*7c478bd9Sstevel@tonic-gate LC_TIME, \ 308*7c478bd9Sstevel@tonic-gate TYPE_STR 309*7c478bd9Sstevel@tonic-gate {"d_t_fmt", dt(date_time_format, 1)}, 310*7c478bd9Sstevel@tonic-gate {"d_fmt", dt(date_format, 1)}, 311*7c478bd9Sstevel@tonic-gate {"t_fmt", dt(time_format, 1)}, 312*7c478bd9Sstevel@tonic-gate {"t_fmt_ampm", dt(time_format_ampm, 1)}, 313*7c478bd9Sstevel@tonic-gate {"am_pm", dt(am_string, 2)}, 314*7c478bd9Sstevel@tonic-gate {"day", dt(day_names, 7)}, 315*7c478bd9Sstevel@tonic-gate {"abday", dt(abbrev_day_names, 7)}, 316*7c478bd9Sstevel@tonic-gate {"mon", dt(month_names, 12)}, 317*7c478bd9Sstevel@tonic-gate {"abmon", dt(abbrev_month_names, 12)}, 318*7c478bd9Sstevel@tonic-gate {"era", dt(era, 1)}, 319*7c478bd9Sstevel@tonic-gate {"era_d_fmt", dt(era_d_fmt, 1)}, 320*7c478bd9Sstevel@tonic-gate {"era_d_t_fmt", dt(era_d_t_fmt, 1)}, 321*7c478bd9Sstevel@tonic-gate {"era_t_fmt", dt(era_t_fmt, 1)}, 322*7c478bd9Sstevel@tonic-gate {"alt_digits", dt(alt_digits, 1)}, 323*7c478bd9Sstevel@tonic-gate 324*7c478bd9Sstevel@tonic-gate #undef dt 325*7c478bd9Sstevel@tonic-gate 326*7c478bd9Sstevel@tonic-gate #define lc(member, locale, type) \ 327*7c478bd9Sstevel@tonic-gate (void *(*)(void))localeconv, \ 328*7c478bd9Sstevel@tonic-gate offsetof(struct lconv, member), \ 329*7c478bd9Sstevel@tonic-gate 1, \ 330*7c478bd9Sstevel@tonic-gate locale, \ 331*7c478bd9Sstevel@tonic-gate type 332*7c478bd9Sstevel@tonic-gate {"decimal_point", lc(decimal_point, LC_NUMERIC, TYPE_STR) }, 333*7c478bd9Sstevel@tonic-gate {"thousands_sep", lc(thousands_sep, LC_NUMERIC, TYPE_STR) }, 334*7c478bd9Sstevel@tonic-gate {"grouping", lc(grouping, LC_NUMERIC, TYPE_GROUP)}, 335*7c478bd9Sstevel@tonic-gate {"int_curr_symbol", lc(int_curr_symbol, LC_MONETARY, TYPE_STR)}, 336*7c478bd9Sstevel@tonic-gate {"currency_symbol", lc(currency_symbol, LC_MONETARY, TYPE_STR)}, 337*7c478bd9Sstevel@tonic-gate {"mon_decimal_point", lc(mon_decimal_point, LC_MONETARY, TYPE_STR)}, 338*7c478bd9Sstevel@tonic-gate {"mon_thousands_sep", lc(mon_thousands_sep, LC_MONETARY, TYPE_STR)}, 339*7c478bd9Sstevel@tonic-gate {"mon_grouping", lc(mon_grouping, LC_MONETARY, TYPE_GROUP)}, 340*7c478bd9Sstevel@tonic-gate {"positive_sign", lc(positive_sign, LC_MONETARY, TYPE_STR)}, 341*7c478bd9Sstevel@tonic-gate {"negative_sign", lc(negative_sign, LC_MONETARY, TYPE_STR)}, 342*7c478bd9Sstevel@tonic-gate 343*7c478bd9Sstevel@tonic-gate {"int_frac_digits", lc(int_frac_digits, LC_MONETARY, TYPE_CHR)}, 344*7c478bd9Sstevel@tonic-gate {"frac_digits", lc(frac_digits, LC_MONETARY, TYPE_CHR)}, 345*7c478bd9Sstevel@tonic-gate {"p_cs_precedes", lc(p_cs_precedes, LC_MONETARY, TYPE_CHR)}, 346*7c478bd9Sstevel@tonic-gate {"p_sep_by_space", lc(p_sep_by_space, LC_MONETARY, TYPE_CHR)}, 347*7c478bd9Sstevel@tonic-gate {"n_cs_precedes", lc(n_cs_precedes, LC_MONETARY, TYPE_CHR)}, 348*7c478bd9Sstevel@tonic-gate {"n_sep_by_space", lc(n_sep_by_space, LC_MONETARY, TYPE_CHR)}, 349*7c478bd9Sstevel@tonic-gate {"p_sign_posn", lc(p_sign_posn, LC_MONETARY, TYPE_CHR)}, 350*7c478bd9Sstevel@tonic-gate {"n_sign_posn", lc(n_sign_posn, LC_MONETARY, TYPE_CHR)}, 351*7c478bd9Sstevel@tonic-gate {"int_p_cs_precedes", lc(int_p_cs_precedes, LC_MONETARY, TYPE_CHR)}, 352*7c478bd9Sstevel@tonic-gate {"int_p_sep_by_space", lc(int_p_sep_by_space, LC_MONETARY, TYPE_CHR)}, 353*7c478bd9Sstevel@tonic-gate {"int_n_cs_precedes", lc(int_n_cs_precedes, LC_MONETARY, TYPE_CHR)}, 354*7c478bd9Sstevel@tonic-gate {"int_n_sep_by_space", lc(int_n_sep_by_space, LC_MONETARY, TYPE_CHR)}, 355*7c478bd9Sstevel@tonic-gate {"int_p_sign_posn", lc(int_p_sign_posn, LC_MONETARY, TYPE_CHR)}, 356*7c478bd9Sstevel@tonic-gate {"int_n_sign_posn", lc(int_n_sign_posn, LC_MONETARY, TYPE_CHR)}, 357*7c478bd9Sstevel@tonic-gate 358*7c478bd9Sstevel@tonic-gate #undef lc 359*7c478bd9Sstevel@tonic-gate #define lc(member) \ 360*7c478bd9Sstevel@tonic-gate (void *(*)(void))getyesno, \ 361*7c478bd9Sstevel@tonic-gate offsetof(struct yesno, member), \ 362*7c478bd9Sstevel@tonic-gate 1, \ 363*7c478bd9Sstevel@tonic-gate LC_MESSAGES, \ 364*7c478bd9Sstevel@tonic-gate TYPE_STR 365*7c478bd9Sstevel@tonic-gate {"yesexpr", lc(yes_expr)}, 366*7c478bd9Sstevel@tonic-gate {"noexpr", lc(no_expr)}, 367*7c478bd9Sstevel@tonic-gate {"yesstr", lc(yes_str)}, 368*7c478bd9Sstevel@tonic-gate {"nostr", lc(no_str)}, 369*7c478bd9Sstevel@tonic-gate #undef lc 370*7c478bd9Sstevel@tonic-gate 371*7c478bd9Sstevel@tonic-gate /* 372*7c478bd9Sstevel@tonic-gate * Following keywords have no official method of obtaining them 373*7c478bd9Sstevel@tonic-gate */ 374*7c478bd9Sstevel@tonic-gate #define ld(member, locale, type) \ 375*7c478bd9Sstevel@tonic-gate (void *(*)(void))localeldconv, \ 376*7c478bd9Sstevel@tonic-gate offsetof(struct localedef, member), \ 377*7c478bd9Sstevel@tonic-gate 1, \ 378*7c478bd9Sstevel@tonic-gate locale, \ 379*7c478bd9Sstevel@tonic-gate type 380*7c478bd9Sstevel@tonic-gate {"charmap", ld(charmap, LC_LOCDEF, TYPE_STR)}, 381*7c478bd9Sstevel@tonic-gate {"code_set_name", ld(code_set_name, LC_LOCDEF, TYPE_STR)}, 382*7c478bd9Sstevel@tonic-gate {"escape_char", ld(escape_char, LC_LOCDEF, TYPE_PCHR)}, 383*7c478bd9Sstevel@tonic-gate {"comment_char", ld(comment_char, LC_LOCDEF, TYPE_PCHR)}, 384*7c478bd9Sstevel@tonic-gate {"mb_cur_max", ld(mb_cur_max, LC_LOCDEF, TYPE_INT)}, 385*7c478bd9Sstevel@tonic-gate {"mb_cur_min", ld(mb_cur_min, LC_LOCDEF, TYPE_INT)}, 386*7c478bd9Sstevel@tonic-gate #undef ld 387*7c478bd9Sstevel@tonic-gate 388*7c478bd9Sstevel@tonic-gate {NULL, NULL, 0, 0} 389*7c478bd9Sstevel@tonic-gate }; 390*7c478bd9Sstevel@tonic-gate 391*7c478bd9Sstevel@tonic-gate static char escapec; 392*7c478bd9Sstevel@tonic-gate 393*7c478bd9Sstevel@tonic-gate int 394*7c478bd9Sstevel@tonic-gate main(int argc, char **argv) 395*7c478bd9Sstevel@tonic-gate { 396*7c478bd9Sstevel@tonic-gate int c; 397*7c478bd9Sstevel@tonic-gate int retval = 0; 398*7c478bd9Sstevel@tonic-gate int cflag, kflag, aflag, mflag; 399*7c478bd9Sstevel@tonic-gate 400*7c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 401*7c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) 402*7c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" 403*7c478bd9Sstevel@tonic-gate #endif 404*7c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 405*7c478bd9Sstevel@tonic-gate 406*7c478bd9Sstevel@tonic-gate cflag = kflag = aflag = mflag = 0; 407*7c478bd9Sstevel@tonic-gate 408*7c478bd9Sstevel@tonic-gate while ((c = getopt(argc, argv, "amck")) != EOF) { 409*7c478bd9Sstevel@tonic-gate switch (c) { 410*7c478bd9Sstevel@tonic-gate case 'a': 411*7c478bd9Sstevel@tonic-gate aflag = 1; 412*7c478bd9Sstevel@tonic-gate break; 413*7c478bd9Sstevel@tonic-gate case 'm': 414*7c478bd9Sstevel@tonic-gate mflag = 1; 415*7c478bd9Sstevel@tonic-gate break; 416*7c478bd9Sstevel@tonic-gate case 'c': 417*7c478bd9Sstevel@tonic-gate cflag = 1; 418*7c478bd9Sstevel@tonic-gate break; 419*7c478bd9Sstevel@tonic-gate case 'k': 420*7c478bd9Sstevel@tonic-gate kflag = 1; 421*7c478bd9Sstevel@tonic-gate break; 422*7c478bd9Sstevel@tonic-gate default: 423*7c478bd9Sstevel@tonic-gate usage(); 424*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 425*7c478bd9Sstevel@tonic-gate break; 426*7c478bd9Sstevel@tonic-gate } 427*7c478bd9Sstevel@tonic-gate } 428*7c478bd9Sstevel@tonic-gate 429*7c478bd9Sstevel@tonic-gate /* -a OR -m OR (-c and/or -k) */ 430*7c478bd9Sstevel@tonic-gate if ((aflag && mflag) || ((aflag || mflag) && (cflag || kflag))) { 431*7c478bd9Sstevel@tonic-gate usage(); 432*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 433*7c478bd9Sstevel@tonic-gate } 434*7c478bd9Sstevel@tonic-gate 435*7c478bd9Sstevel@tonic-gate escapec = get_escapechar(); 436*7c478bd9Sstevel@tonic-gate 437*7c478bd9Sstevel@tonic-gate if (aflag) { 438*7c478bd9Sstevel@tonic-gate print_all_info(GET_LOCALE); 439*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 440*7c478bd9Sstevel@tonic-gate } 441*7c478bd9Sstevel@tonic-gate 442*7c478bd9Sstevel@tonic-gate if (mflag) { 443*7c478bd9Sstevel@tonic-gate print_all_info(GET_CHARMAP); 444*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 445*7c478bd9Sstevel@tonic-gate } 446*7c478bd9Sstevel@tonic-gate 447*7c478bd9Sstevel@tonic-gate if (optind == argc && !cflag && !kflag) { 448*7c478bd9Sstevel@tonic-gate print_cur_locale(); 449*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 450*7c478bd9Sstevel@tonic-gate } 451*7c478bd9Sstevel@tonic-gate if (optind == argc) { 452*7c478bd9Sstevel@tonic-gate usage(); 453*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 454*7c478bd9Sstevel@tonic-gate } 455*7c478bd9Sstevel@tonic-gate 456*7c478bd9Sstevel@tonic-gate for (; optind < argc; optind++) { 457*7c478bd9Sstevel@tonic-gate retval += print_locale_info(argv[optind], cflag, kflag); 458*7c478bd9Sstevel@tonic-gate } 459*7c478bd9Sstevel@tonic-gate return (retval); 460*7c478bd9Sstevel@tonic-gate } 461*7c478bd9Sstevel@tonic-gate 462*7c478bd9Sstevel@tonic-gate /* 463*7c478bd9Sstevel@tonic-gate * No options or operands. 464*7c478bd9Sstevel@tonic-gate * Print out the current locale names from the environment, or implied. 465*7c478bd9Sstevel@tonic-gate * Variables directly set in the environment are printed as-is, those 466*7c478bd9Sstevel@tonic-gate * implied are printed in quotes. 467*7c478bd9Sstevel@tonic-gate * The strings are printed ``appropriately quoted for possible later re-entry 468*7c478bd9Sstevel@tonic-gate * to the shell''. We use the routine outstr to do this -- however we 469*7c478bd9Sstevel@tonic-gate * want the shell escape character, the backslash, not the locale escape 470*7c478bd9Sstevel@tonic-gate * character, so we quietly save and restore the locale escape character. 471*7c478bd9Sstevel@tonic-gate */ 472*7c478bd9Sstevel@tonic-gate static void 473*7c478bd9Sstevel@tonic-gate print_cur_locale(void) 474*7c478bd9Sstevel@tonic-gate { 475*7c478bd9Sstevel@tonic-gate char *lc_allp; 476*7c478bd9Sstevel@tonic-gate char *env, *eff; 477*7c478bd9Sstevel@tonic-gate int i; 478*7c478bd9Sstevel@tonic-gate 479*7c478bd9Sstevel@tonic-gate if ((env = getenv("LANG")) != NULL) { 480*7c478bd9Sstevel@tonic-gate (void) printf("LANG=%s\n", env); 481*7c478bd9Sstevel@tonic-gate } else { 482*7c478bd9Sstevel@tonic-gate (void) printf("LANG=\n"); 483*7c478bd9Sstevel@tonic-gate } 484*7c478bd9Sstevel@tonic-gate 485*7c478bd9Sstevel@tonic-gate lc_allp = getenv("LC_ALL"); 486*7c478bd9Sstevel@tonic-gate 487*7c478bd9Sstevel@tonic-gate for (i = 0; i < LC_ALL; i++) { 488*7c478bd9Sstevel@tonic-gate (void) printf("%s=", locale_name[i].name); 489*7c478bd9Sstevel@tonic-gate eff = setlocale(i, NULL); 490*7c478bd9Sstevel@tonic-gate if (eff == NULL) { 491*7c478bd9Sstevel@tonic-gate eff = ""; 492*7c478bd9Sstevel@tonic-gate } 493*7c478bd9Sstevel@tonic-gate env = getenv(locale_name[i].name); 494*7c478bd9Sstevel@tonic-gate 495*7c478bd9Sstevel@tonic-gate if (env == NULL) { 496*7c478bd9Sstevel@tonic-gate (void) putchar('"'); 497*7c478bd9Sstevel@tonic-gate outstr(eff); 498*7c478bd9Sstevel@tonic-gate (void) putchar('"'); 499*7c478bd9Sstevel@tonic-gate } else { 500*7c478bd9Sstevel@tonic-gate if (strcmp(env, eff) != 0) { 501*7c478bd9Sstevel@tonic-gate (void) putchar('"'); 502*7c478bd9Sstevel@tonic-gate outstr(eff); 503*7c478bd9Sstevel@tonic-gate (void) putchar('"'); 504*7c478bd9Sstevel@tonic-gate } else { 505*7c478bd9Sstevel@tonic-gate outstr(eff); 506*7c478bd9Sstevel@tonic-gate } 507*7c478bd9Sstevel@tonic-gate } 508*7c478bd9Sstevel@tonic-gate (void) putchar('\n'); 509*7c478bd9Sstevel@tonic-gate } 510*7c478bd9Sstevel@tonic-gate 511*7c478bd9Sstevel@tonic-gate (void) printf("LC_ALL="); 512*7c478bd9Sstevel@tonic-gate if (lc_allp != NULL) { 513*7c478bd9Sstevel@tonic-gate outstr(lc_allp); 514*7c478bd9Sstevel@tonic-gate } 515*7c478bd9Sstevel@tonic-gate (void) putchar('\n'); 516*7c478bd9Sstevel@tonic-gate exit(0); 517*7c478bd9Sstevel@tonic-gate } 518*7c478bd9Sstevel@tonic-gate 519*7c478bd9Sstevel@tonic-gate static int num_of_loc = 0; 520*7c478bd9Sstevel@tonic-gate static int num_of_entries = 0; 521*7c478bd9Sstevel@tonic-gate static char **entries = NULL; 522*7c478bd9Sstevel@tonic-gate 523*7c478bd9Sstevel@tonic-gate static void 524*7c478bd9Sstevel@tonic-gate add_loc_entry(char *loc) 525*7c478bd9Sstevel@tonic-gate { 526*7c478bd9Sstevel@tonic-gate #define _INC_NUM 10 527*7c478bd9Sstevel@tonic-gate char *s; 528*7c478bd9Sstevel@tonic-gate 529*7c478bd9Sstevel@tonic-gate if (num_of_loc >= num_of_entries) { 530*7c478bd9Sstevel@tonic-gate char **tmp; 531*7c478bd9Sstevel@tonic-gate num_of_entries += _INC_NUM; 532*7c478bd9Sstevel@tonic-gate tmp = realloc(entries, sizeof (char *) * num_of_entries); 533*7c478bd9Sstevel@tonic-gate if (tmp == NULL) { 534*7c478bd9Sstevel@tonic-gate /* restoring original locale */ 535*7c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, save_loc); 536*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 537*7c478bd9Sstevel@tonic-gate gettext("locale: cannot allocate buffer")); 538*7c478bd9Sstevel@tonic-gate exit(1); 539*7c478bd9Sstevel@tonic-gate } 540*7c478bd9Sstevel@tonic-gate entries = tmp; 541*7c478bd9Sstevel@tonic-gate } 542*7c478bd9Sstevel@tonic-gate s = strdup(loc); 543*7c478bd9Sstevel@tonic-gate if (s == NULL) { 544*7c478bd9Sstevel@tonic-gate /* restoring original locale */ 545*7c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, save_loc); 546*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 547*7c478bd9Sstevel@tonic-gate gettext("locale: cannot allocate buffer")); 548*7c478bd9Sstevel@tonic-gate exit(1); 549*7c478bd9Sstevel@tonic-gate } 550*7c478bd9Sstevel@tonic-gate entries[num_of_loc] = s; 551*7c478bd9Sstevel@tonic-gate 552*7c478bd9Sstevel@tonic-gate num_of_loc++; 553*7c478bd9Sstevel@tonic-gate } 554*7c478bd9Sstevel@tonic-gate 555*7c478bd9Sstevel@tonic-gate static int 556*7c478bd9Sstevel@tonic-gate loccmp(const char **str1, const char **str2) 557*7c478bd9Sstevel@tonic-gate { 558*7c478bd9Sstevel@tonic-gate return (strcmp(*str1, *str2)); 559*7c478bd9Sstevel@tonic-gate } 560*7c478bd9Sstevel@tonic-gate 561*7c478bd9Sstevel@tonic-gate static void 562*7c478bd9Sstevel@tonic-gate show_loc_entry(void) 563*7c478bd9Sstevel@tonic-gate { 564*7c478bd9Sstevel@tonic-gate int i; 565*7c478bd9Sstevel@tonic-gate 566*7c478bd9Sstevel@tonic-gate qsort(entries, num_of_loc, sizeof (char *), 567*7c478bd9Sstevel@tonic-gate (int (*)(const void *, const void *))loccmp); 568*7c478bd9Sstevel@tonic-gate for (i = 0; i < num_of_loc; i++) { 569*7c478bd9Sstevel@tonic-gate (void) printf("%s\n", entries[i]); 570*7c478bd9Sstevel@tonic-gate } 571*7c478bd9Sstevel@tonic-gate } 572*7c478bd9Sstevel@tonic-gate 573*7c478bd9Sstevel@tonic-gate static void 574*7c478bd9Sstevel@tonic-gate check_loc(char *loc) 575*7c478bd9Sstevel@tonic-gate { 576*7c478bd9Sstevel@tonic-gate int cat; 577*7c478bd9Sstevel@tonic-gate 578*7c478bd9Sstevel@tonic-gate /* first, try LC_ALL */ 579*7c478bd9Sstevel@tonic-gate if (setlocale(LC_ALL, loc) != NULL) { 580*7c478bd9Sstevel@tonic-gate /* succeeded */ 581*7c478bd9Sstevel@tonic-gate add_loc_entry(loc); 582*7c478bd9Sstevel@tonic-gate return; 583*7c478bd9Sstevel@tonic-gate } 584*7c478bd9Sstevel@tonic-gate 585*7c478bd9Sstevel@tonic-gate /* 586*7c478bd9Sstevel@tonic-gate * LC_ALL failed. 587*7c478bd9Sstevel@tonic-gate * try each category. 588*7c478bd9Sstevel@tonic-gate */ 589*7c478bd9Sstevel@tonic-gate for (cat = 0; cat <= _LastCategory; cat++) { 590*7c478bd9Sstevel@tonic-gate if (setlocale(cat, loc) != NULL) { 591*7c478bd9Sstevel@tonic-gate /* succeeded */ 592*7c478bd9Sstevel@tonic-gate add_loc_entry(loc); 593*7c478bd9Sstevel@tonic-gate return; 594*7c478bd9Sstevel@tonic-gate } 595*7c478bd9Sstevel@tonic-gate } 596*7c478bd9Sstevel@tonic-gate 597*7c478bd9Sstevel@tonic-gate /* loc is not a valid locale */ 598*7c478bd9Sstevel@tonic-gate } 599*7c478bd9Sstevel@tonic-gate 600*7c478bd9Sstevel@tonic-gate /* 601*7c478bd9Sstevel@tonic-gate * print_all_info(): Print out all the locales and 602*7c478bd9Sstevel@tonic-gate * charmaps supported by the system 603*7c478bd9Sstevel@tonic-gate */ 604*7c478bd9Sstevel@tonic-gate static void 605*7c478bd9Sstevel@tonic-gate print_all_info(int flag) 606*7c478bd9Sstevel@tonic-gate { 607*7c478bd9Sstevel@tonic-gate struct dirent *direntp; 608*7c478bd9Sstevel@tonic-gate DIR *dirp; 609*7c478bd9Sstevel@tonic-gate char *filename; /* filename[PATH_MAX] */ 610*7c478bd9Sstevel@tonic-gate char *p; 611*7c478bd9Sstevel@tonic-gate 612*7c478bd9Sstevel@tonic-gate if ((filename = malloc(PATH_MAX)) == NULL) { 613*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 614*7c478bd9Sstevel@tonic-gate gettext("locale: cannot allocate buffer")); 615*7c478bd9Sstevel@tonic-gate exit(1); 616*7c478bd9Sstevel@tonic-gate } 617*7c478bd9Sstevel@tonic-gate 618*7c478bd9Sstevel@tonic-gate (void) memset(filename, 0, PATH_MAX); 619*7c478bd9Sstevel@tonic-gate 620*7c478bd9Sstevel@tonic-gate if (flag == GET_LOCALE) { 621*7c478bd9Sstevel@tonic-gate /* save the current locale */ 622*7c478bd9Sstevel@tonic-gate save_loc = setlocale(LC_ALL, NULL); 623*7c478bd9Sstevel@tonic-gate 624*7c478bd9Sstevel@tonic-gate (void) strcpy(filename, LOCALE_DIR); 625*7c478bd9Sstevel@tonic-gate add_loc_entry("POSIX"); 626*7c478bd9Sstevel@tonic-gate } else { /* CHARMAP */ 627*7c478bd9Sstevel@tonic-gate (void) strcpy(filename, CHARMAP_DIR); 628*7c478bd9Sstevel@tonic-gate } 629*7c478bd9Sstevel@tonic-gate 630*7c478bd9Sstevel@tonic-gate if ((dirp = opendir(filename)) == NULL) { 631*7c478bd9Sstevel@tonic-gate if (flag == GET_LOCALE) 632*7c478bd9Sstevel@tonic-gate exit(0); 633*7c478bd9Sstevel@tonic-gate else { /* CHARMAP */ 634*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 635*7c478bd9Sstevel@tonic-gate "locale: charmap information not available.\n")); 636*7c478bd9Sstevel@tonic-gate exit(2); 637*7c478bd9Sstevel@tonic-gate } 638*7c478bd9Sstevel@tonic-gate } 639*7c478bd9Sstevel@tonic-gate 640*7c478bd9Sstevel@tonic-gate p = filename + strlen(filename); 641*7c478bd9Sstevel@tonic-gate while ((direntp = readdir(dirp)) != NULL) { 642*7c478bd9Sstevel@tonic-gate struct stat stbuf; 643*7c478bd9Sstevel@tonic-gate 644*7c478bd9Sstevel@tonic-gate (void) strcpy(p, direntp->d_name); 645*7c478bd9Sstevel@tonic-gate if (stat(filename, &stbuf) < 0) { 646*7c478bd9Sstevel@tonic-gate continue; 647*7c478bd9Sstevel@tonic-gate } 648*7c478bd9Sstevel@tonic-gate 649*7c478bd9Sstevel@tonic-gate if (flag == GET_LOCALE) { 650*7c478bd9Sstevel@tonic-gate if (S_ISDIR(stbuf.st_mode) && 651*7c478bd9Sstevel@tonic-gate (direntp->d_name[0] != '.') && 652*7c478bd9Sstevel@tonic-gate /* "POSIX" has already been printed out */ 653*7c478bd9Sstevel@tonic-gate strcmp(direntp->d_name, "POSIX") != 0) { 654*7c478bd9Sstevel@tonic-gate check_loc(direntp->d_name); 655*7c478bd9Sstevel@tonic-gate } 656*7c478bd9Sstevel@tonic-gate } else { /* CHARMAP */ 657*7c478bd9Sstevel@tonic-gate if (S_ISDIR(stbuf.st_mode) && 658*7c478bd9Sstevel@tonic-gate direntp->d_name[0] != '.') { 659*7c478bd9Sstevel@tonic-gate struct dirent *direntc; 660*7c478bd9Sstevel@tonic-gate DIR *dirc; 661*7c478bd9Sstevel@tonic-gate char *charmap; 662*7c478bd9Sstevel@tonic-gate char *c; 663*7c478bd9Sstevel@tonic-gate 664*7c478bd9Sstevel@tonic-gate if ((charmap = malloc(PATH_MAX)) == NULL) { 665*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 666*7c478bd9Sstevel@tonic-gate gettext("locale: cannot allocate buffer")); 667*7c478bd9Sstevel@tonic-gate exit(1); 668*7c478bd9Sstevel@tonic-gate } 669*7c478bd9Sstevel@tonic-gate 670*7c478bd9Sstevel@tonic-gate (void) memset(charmap, 0, PATH_MAX); 671*7c478bd9Sstevel@tonic-gate 672*7c478bd9Sstevel@tonic-gate (void) strcpy(charmap, filename); 673*7c478bd9Sstevel@tonic-gate 674*7c478bd9Sstevel@tonic-gate if ((dirc = opendir(charmap)) == NULL) { 675*7c478bd9Sstevel@tonic-gate exit(0); 676*7c478bd9Sstevel@tonic-gate } 677*7c478bd9Sstevel@tonic-gate 678*7c478bd9Sstevel@tonic-gate c = charmap + strlen(charmap); 679*7c478bd9Sstevel@tonic-gate *c++ = '/'; 680*7c478bd9Sstevel@tonic-gate while ((direntc = readdir(dirc)) != NULL) { 681*7c478bd9Sstevel@tonic-gate struct stat stbuf; 682*7c478bd9Sstevel@tonic-gate 683*7c478bd9Sstevel@tonic-gate (void) strcpy(c, direntc->d_name); 684*7c478bd9Sstevel@tonic-gate if (stat(charmap, &stbuf) < 0) { 685*7c478bd9Sstevel@tonic-gate continue; 686*7c478bd9Sstevel@tonic-gate } 687*7c478bd9Sstevel@tonic-gate 688*7c478bd9Sstevel@tonic-gate if (S_ISREG(stbuf.st_mode) && 689*7c478bd9Sstevel@tonic-gate (strcmp(direntc->d_name, 690*7c478bd9Sstevel@tonic-gate CHARMAP_NAME) == 0) && 691*7c478bd9Sstevel@tonic-gate (direntc->d_name[0] != '.')) { 692*7c478bd9Sstevel@tonic-gate (void) printf("%s/%s\n", 693*7c478bd9Sstevel@tonic-gate p, direntc->d_name); 694*7c478bd9Sstevel@tonic-gate } 695*7c478bd9Sstevel@tonic-gate } 696*7c478bd9Sstevel@tonic-gate (void) closedir(dirc); 697*7c478bd9Sstevel@tonic-gate free(charmap); 698*7c478bd9Sstevel@tonic-gate } 699*7c478bd9Sstevel@tonic-gate } 700*7c478bd9Sstevel@tonic-gate } 701*7c478bd9Sstevel@tonic-gate if (flag == GET_LOCALE) { 702*7c478bd9Sstevel@tonic-gate /* restore the saved loc */ 703*7c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, save_loc); 704*7c478bd9Sstevel@tonic-gate show_loc_entry(); 705*7c478bd9Sstevel@tonic-gate } 706*7c478bd9Sstevel@tonic-gate (void) closedir(dirp); 707*7c478bd9Sstevel@tonic-gate free(filename); 708*7c478bd9Sstevel@tonic-gate exit(0); 709*7c478bd9Sstevel@tonic-gate } 710*7c478bd9Sstevel@tonic-gate 711*7c478bd9Sstevel@tonic-gate /* 712*7c478bd9Sstevel@tonic-gate * Print out the keyword value or category info. 713*7c478bd9Sstevel@tonic-gate * Call print_category() to print the entire locale category, if the name 714*7c478bd9Sstevel@tonic-gate * given is recognized as a category. 715*7c478bd9Sstevel@tonic-gate * Otherwise, assume that it is a keyword, and call print_keyword(). 716*7c478bd9Sstevel@tonic-gate */ 717*7c478bd9Sstevel@tonic-gate static int 718*7c478bd9Sstevel@tonic-gate print_locale_info(char *name, int cflag, int kflag) 719*7c478bd9Sstevel@tonic-gate { 720*7c478bd9Sstevel@tonic-gate int i; 721*7c478bd9Sstevel@tonic-gate 722*7c478bd9Sstevel@tonic-gate for (i = 0; locale_name[i].name != NULL; i++) { 723*7c478bd9Sstevel@tonic-gate if (strcmp(locale_name[i].name, name) == 0) { 724*7c478bd9Sstevel@tonic-gate /* 725*7c478bd9Sstevel@tonic-gate * name is a category name 726*7c478bd9Sstevel@tonic-gate * print out all keywords in this category 727*7c478bd9Sstevel@tonic-gate */ 728*7c478bd9Sstevel@tonic-gate return (print_category(locale_name[i].category, 729*7c478bd9Sstevel@tonic-gate cflag, kflag)); 730*7c478bd9Sstevel@tonic-gate } 731*7c478bd9Sstevel@tonic-gate } 732*7c478bd9Sstevel@tonic-gate 733*7c478bd9Sstevel@tonic-gate /* The name is a keyword name */ 734*7c478bd9Sstevel@tonic-gate return (print_keyword(name, cflag, kflag)); 735*7c478bd9Sstevel@tonic-gate } 736*7c478bd9Sstevel@tonic-gate 737*7c478bd9Sstevel@tonic-gate /* 738*7c478bd9Sstevel@tonic-gate * Print out the value of the keyword 739*7c478bd9Sstevel@tonic-gate */ 740*7c478bd9Sstevel@tonic-gate static int 741*7c478bd9Sstevel@tonic-gate print_keyword(char *name, int cflag, int kflag) 742*7c478bd9Sstevel@tonic-gate { 743*7c478bd9Sstevel@tonic-gate int i, j; 744*7c478bd9Sstevel@tonic-gate int first_flag = 1; 745*7c478bd9Sstevel@tonic-gate int found = 0; 746*7c478bd9Sstevel@tonic-gate 747*7c478bd9Sstevel@tonic-gate for (i = 0; key[i].name != NULL; i++) { 748*7c478bd9Sstevel@tonic-gate if (strcmp(key[i].name, name) != 0) { 749*7c478bd9Sstevel@tonic-gate continue; 750*7c478bd9Sstevel@tonic-gate } 751*7c478bd9Sstevel@tonic-gate 752*7c478bd9Sstevel@tonic-gate found = 1; 753*7c478bd9Sstevel@tonic-gate if (first_flag && cflag && key[i].category != LC_LOCDEF) { 754*7c478bd9Sstevel@tonic-gate /* print out this category's name */ 755*7c478bd9Sstevel@tonic-gate (void) printf("%s\n", 756*7c478bd9Sstevel@tonic-gate locale_name[key[i].category].name); 757*7c478bd9Sstevel@tonic-gate } 758*7c478bd9Sstevel@tonic-gate if (kflag) { 759*7c478bd9Sstevel@tonic-gate (void) printf("%s=", name); 760*7c478bd9Sstevel@tonic-gate } 761*7c478bd9Sstevel@tonic-gate switch (key[i].type) { 762*7c478bd9Sstevel@tonic-gate 763*7c478bd9Sstevel@tonic-gate /* 764*7c478bd9Sstevel@tonic-gate * The grouping fields are a set of bytes, each of which 765*7c478bd9Sstevel@tonic-gate * is the numeric value of the next group size, terminated 766*7c478bd9Sstevel@tonic-gate * by a \0, or by CHAR_MAX 767*7c478bd9Sstevel@tonic-gate */ 768*7c478bd9Sstevel@tonic-gate case TYPE_GROUP: 769*7c478bd9Sstevel@tonic-gate { 770*7c478bd9Sstevel@tonic-gate void *s; 771*7c478bd9Sstevel@tonic-gate char *q; 772*7c478bd9Sstevel@tonic-gate int first = 1; 773*7c478bd9Sstevel@tonic-gate 774*7c478bd9Sstevel@tonic-gate s = (*key[i].structure)(); 775*7c478bd9Sstevel@tonic-gate /* LINTED */ 776*7c478bd9Sstevel@tonic-gate q = *(char **)((char *)s + key[i].offset); 777*7c478bd9Sstevel@tonic-gate if (*q == '\0') { 778*7c478bd9Sstevel@tonic-gate (void) printf("-1"); 779*7c478bd9Sstevel@tonic-gate break; 780*7c478bd9Sstevel@tonic-gate } 781*7c478bd9Sstevel@tonic-gate while (*q != '\0' && *q != CHAR_MAX) { 782*7c478bd9Sstevel@tonic-gate if (!first) { 783*7c478bd9Sstevel@tonic-gate (void) putchar(';'); 784*7c478bd9Sstevel@tonic-gate } 785*7c478bd9Sstevel@tonic-gate first = 0; 786*7c478bd9Sstevel@tonic-gate (void) printf("%u", 787*7c478bd9Sstevel@tonic-gate *(unsigned char *)q++); 788*7c478bd9Sstevel@tonic-gate } 789*7c478bd9Sstevel@tonic-gate /* CHAR_MAX: no further grouping performed. */ 790*7c478bd9Sstevel@tonic-gate if (!first) { 791*7c478bd9Sstevel@tonic-gate (void) putchar(';'); 792*7c478bd9Sstevel@tonic-gate } 793*7c478bd9Sstevel@tonic-gate if (*q == CHAR_MAX) { 794*7c478bd9Sstevel@tonic-gate (void) printf("-1"); 795*7c478bd9Sstevel@tonic-gate } else { 796*7c478bd9Sstevel@tonic-gate (void) putchar('0'); 797*7c478bd9Sstevel@tonic-gate } 798*7c478bd9Sstevel@tonic-gate } 799*7c478bd9Sstevel@tonic-gate break; 800*7c478bd9Sstevel@tonic-gate 801*7c478bd9Sstevel@tonic-gate /* 802*7c478bd9Sstevel@tonic-gate * Entries like decimal_point states ``the decimal-point 803*7c478bd9Sstevel@tonic-gate * character...'' not string. However, it is a char *. 804*7c478bd9Sstevel@tonic-gate * This assumes single, narrow, character. 805*7c478bd9Sstevel@tonic-gate * Should it permit multibyte characters? 806*7c478bd9Sstevel@tonic-gate * Should it permit a whole string, in that case? 807*7c478bd9Sstevel@tonic-gate */ 808*7c478bd9Sstevel@tonic-gate case TYPE_STR: 809*7c478bd9Sstevel@tonic-gate { 810*7c478bd9Sstevel@tonic-gate void *s; 811*7c478bd9Sstevel@tonic-gate char **q; 812*7c478bd9Sstevel@tonic-gate 813*7c478bd9Sstevel@tonic-gate s = (*key[i].structure)(); 814*7c478bd9Sstevel@tonic-gate /* LINTED */ 815*7c478bd9Sstevel@tonic-gate q = (char **)((char *)s + key[i].offset); 816*7c478bd9Sstevel@tonic-gate for (j = 0; j < key[i].count; j++) { 817*7c478bd9Sstevel@tonic-gate if (j != 0) { 818*7c478bd9Sstevel@tonic-gate (void) printf(";"); 819*7c478bd9Sstevel@tonic-gate } 820*7c478bd9Sstevel@tonic-gate if (kflag) { 821*7c478bd9Sstevel@tonic-gate (void) printf("\""); 822*7c478bd9Sstevel@tonic-gate outstr(q[j]); 823*7c478bd9Sstevel@tonic-gate (void) printf("\""); 824*7c478bd9Sstevel@tonic-gate } else { 825*7c478bd9Sstevel@tonic-gate (void) printf("%s", q[j]); 826*7c478bd9Sstevel@tonic-gate } 827*7c478bd9Sstevel@tonic-gate } 828*7c478bd9Sstevel@tonic-gate } 829*7c478bd9Sstevel@tonic-gate break; 830*7c478bd9Sstevel@tonic-gate 831*7c478bd9Sstevel@tonic-gate case TYPE_INT: 832*7c478bd9Sstevel@tonic-gate { 833*7c478bd9Sstevel@tonic-gate void *s; 834*7c478bd9Sstevel@tonic-gate int *q; 835*7c478bd9Sstevel@tonic-gate 836*7c478bd9Sstevel@tonic-gate s = (*key[i].structure)(); 837*7c478bd9Sstevel@tonic-gate /* LINTED */ 838*7c478bd9Sstevel@tonic-gate q = (int *)((char *)s + key[i].offset); 839*7c478bd9Sstevel@tonic-gate (void) printf("%d", *q); 840*7c478bd9Sstevel@tonic-gate } 841*7c478bd9Sstevel@tonic-gate break; 842*7c478bd9Sstevel@tonic-gate 843*7c478bd9Sstevel@tonic-gate /* 844*7c478bd9Sstevel@tonic-gate * TYPE_CHR: Single byte integer. 845*7c478bd9Sstevel@tonic-gate */ 846*7c478bd9Sstevel@tonic-gate case TYPE_CHR: 847*7c478bd9Sstevel@tonic-gate { 848*7c478bd9Sstevel@tonic-gate void *s; 849*7c478bd9Sstevel@tonic-gate char *q; 850*7c478bd9Sstevel@tonic-gate 851*7c478bd9Sstevel@tonic-gate s = (*key[i].structure)(); 852*7c478bd9Sstevel@tonic-gate q = (char *)((char *)s + key[i].offset); 853*7c478bd9Sstevel@tonic-gate if (*q == CHAR_MAX) { 854*7c478bd9Sstevel@tonic-gate (void) printf("-1"); 855*7c478bd9Sstevel@tonic-gate } else { 856*7c478bd9Sstevel@tonic-gate (void) printf("%u", 857*7c478bd9Sstevel@tonic-gate *(unsigned char *)q); 858*7c478bd9Sstevel@tonic-gate } 859*7c478bd9Sstevel@tonic-gate } 860*7c478bd9Sstevel@tonic-gate break; 861*7c478bd9Sstevel@tonic-gate 862*7c478bd9Sstevel@tonic-gate /* 863*7c478bd9Sstevel@tonic-gate * TYPE_PCHR: Single byte, printed as a character if printable 864*7c478bd9Sstevel@tonic-gate */ 865*7c478bd9Sstevel@tonic-gate case TYPE_PCHR: 866*7c478bd9Sstevel@tonic-gate { 867*7c478bd9Sstevel@tonic-gate void *s; 868*7c478bd9Sstevel@tonic-gate char *q; 869*7c478bd9Sstevel@tonic-gate 870*7c478bd9Sstevel@tonic-gate s = (*key[i].structure)(); 871*7c478bd9Sstevel@tonic-gate q = (char *)((char *)s + key[i].offset); 872*7c478bd9Sstevel@tonic-gate if (isprint(*(unsigned char *)q)) { 873*7c478bd9Sstevel@tonic-gate if (kflag) { 874*7c478bd9Sstevel@tonic-gate (void) printf("\""); 875*7c478bd9Sstevel@tonic-gate if ((*q == '\\') || 876*7c478bd9Sstevel@tonic-gate (*q == ';') || 877*7c478bd9Sstevel@tonic-gate (*q == '"')) { 878*7c478bd9Sstevel@tonic-gate (void) putchar(escapec); 879*7c478bd9Sstevel@tonic-gate (void) printf("%c", 880*7c478bd9Sstevel@tonic-gate *(unsigned char *)q); 881*7c478bd9Sstevel@tonic-gate } else { 882*7c478bd9Sstevel@tonic-gate (void) printf("%c", 883*7c478bd9Sstevel@tonic-gate *(unsigned char *)q); 884*7c478bd9Sstevel@tonic-gate } 885*7c478bd9Sstevel@tonic-gate (void) printf("\""); 886*7c478bd9Sstevel@tonic-gate } else { 887*7c478bd9Sstevel@tonic-gate (void) printf("%c", 888*7c478bd9Sstevel@tonic-gate *(unsigned char *)q); 889*7c478bd9Sstevel@tonic-gate } 890*7c478bd9Sstevel@tonic-gate } else if (*q == (char)-1) { 891*7c478bd9Sstevel@tonic-gate /* In case no signed chars */ 892*7c478bd9Sstevel@tonic-gate (void) printf("-1"); 893*7c478bd9Sstevel@tonic-gate } else { 894*7c478bd9Sstevel@tonic-gate (void) printf("%u", 895*7c478bd9Sstevel@tonic-gate *(unsigned char *)q); 896*7c478bd9Sstevel@tonic-gate } 897*7c478bd9Sstevel@tonic-gate } 898*7c478bd9Sstevel@tonic-gate break; 899*7c478bd9Sstevel@tonic-gate 900*7c478bd9Sstevel@tonic-gate case TYPE_CTP: 901*7c478bd9Sstevel@tonic-gate { 902*7c478bd9Sstevel@tonic-gate prt_ctp(key[i].name); 903*7c478bd9Sstevel@tonic-gate } 904*7c478bd9Sstevel@tonic-gate break; 905*7c478bd9Sstevel@tonic-gate 906*7c478bd9Sstevel@tonic-gate case TYPE_CNVU: 907*7c478bd9Sstevel@tonic-gate { 908*7c478bd9Sstevel@tonic-gate prt_cnv(key[i].name); 909*7c478bd9Sstevel@tonic-gate } 910*7c478bd9Sstevel@tonic-gate break; 911*7c478bd9Sstevel@tonic-gate 912*7c478bd9Sstevel@tonic-gate case TYPE_CNVL: 913*7c478bd9Sstevel@tonic-gate { 914*7c478bd9Sstevel@tonic-gate prt_cnv(key[i].name); 915*7c478bd9Sstevel@tonic-gate } 916*7c478bd9Sstevel@tonic-gate break; 917*7c478bd9Sstevel@tonic-gate 918*7c478bd9Sstevel@tonic-gate case TYPE_COLLEL: 919*7c478bd9Sstevel@tonic-gate { 920*7c478bd9Sstevel@tonic-gate prt_collel(key[i].name); 921*7c478bd9Sstevel@tonic-gate } 922*7c478bd9Sstevel@tonic-gate break; 923*7c478bd9Sstevel@tonic-gate } 924*7c478bd9Sstevel@tonic-gate } 925*7c478bd9Sstevel@tonic-gate if (found) { 926*7c478bd9Sstevel@tonic-gate (void) printf("\n"); 927*7c478bd9Sstevel@tonic-gate return (0); 928*7c478bd9Sstevel@tonic-gate } else { 929*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 930*7c478bd9Sstevel@tonic-gate gettext("Unknown keyword name '%s'.\n"), name); 931*7c478bd9Sstevel@tonic-gate return (1); 932*7c478bd9Sstevel@tonic-gate } 933*7c478bd9Sstevel@tonic-gate } 934*7c478bd9Sstevel@tonic-gate 935*7c478bd9Sstevel@tonic-gate /* 936*7c478bd9Sstevel@tonic-gate * Strings being outputed have to use an unambiguous format -- escape 937*7c478bd9Sstevel@tonic-gate * any potentially bad output characters. 938*7c478bd9Sstevel@tonic-gate * The standard says that any control character shall be preceeded by 939*7c478bd9Sstevel@tonic-gate * the escape character. But it doesn't say that you can format that 940*7c478bd9Sstevel@tonic-gate * character at all. 941*7c478bd9Sstevel@tonic-gate * Question: If the multibyte character contains a quoting character, 942*7c478bd9Sstevel@tonic-gate * should that *byte* be escaped? 943*7c478bd9Sstevel@tonic-gate */ 944*7c478bd9Sstevel@tonic-gate static void 945*7c478bd9Sstevel@tonic-gate outstr(char *s) 946*7c478bd9Sstevel@tonic-gate { 947*7c478bd9Sstevel@tonic-gate wchar_t ws; 948*7c478bd9Sstevel@tonic-gate int c; 949*7c478bd9Sstevel@tonic-gate size_t mbcurmax = MB_CUR_MAX; 950*7c478bd9Sstevel@tonic-gate 951*7c478bd9Sstevel@tonic-gate while (*s != '\0') { 952*7c478bd9Sstevel@tonic-gate c = mbtowc(&ws, s, mbcurmax); 953*7c478bd9Sstevel@tonic-gate if (c < 0) { 954*7c478bd9Sstevel@tonic-gate s++; 955*7c478bd9Sstevel@tonic-gate } else if (c == 1) { 956*7c478bd9Sstevel@tonic-gate outchar(*s++); 957*7c478bd9Sstevel@tonic-gate } else { 958*7c478bd9Sstevel@tonic-gate for (; c > 0; c--) { 959*7c478bd9Sstevel@tonic-gate (void) putchar(*s++); 960*7c478bd9Sstevel@tonic-gate } 961*7c478bd9Sstevel@tonic-gate } 962*7c478bd9Sstevel@tonic-gate } 963*7c478bd9Sstevel@tonic-gate } 964*7c478bd9Sstevel@tonic-gate 965*7c478bd9Sstevel@tonic-gate static void 966*7c478bd9Sstevel@tonic-gate outchar(int c) 967*7c478bd9Sstevel@tonic-gate { 968*7c478bd9Sstevel@tonic-gate unsigned char uc; 969*7c478bd9Sstevel@tonic-gate 970*7c478bd9Sstevel@tonic-gate uc = (unsigned char) c; 971*7c478bd9Sstevel@tonic-gate 972*7c478bd9Sstevel@tonic-gate if ((uc == '\\') || (uc == ';') || (uc == '"')) { 973*7c478bd9Sstevel@tonic-gate (void) putchar(escapec); 974*7c478bd9Sstevel@tonic-gate (void) putchar(uc); 975*7c478bd9Sstevel@tonic-gate } else if (iscntrl(uc)) { 976*7c478bd9Sstevel@tonic-gate (void) printf("%cx%02x", escapec, uc); 977*7c478bd9Sstevel@tonic-gate } else { 978*7c478bd9Sstevel@tonic-gate (void) putchar(uc); 979*7c478bd9Sstevel@tonic-gate } 980*7c478bd9Sstevel@tonic-gate } 981*7c478bd9Sstevel@tonic-gate 982*7c478bd9Sstevel@tonic-gate /* 983*7c478bd9Sstevel@tonic-gate * print_category(): Print out all the keyword's value 984*7c478bd9Sstevel@tonic-gate * in the given category 985*7c478bd9Sstevel@tonic-gate */ 986*7c478bd9Sstevel@tonic-gate static int 987*7c478bd9Sstevel@tonic-gate print_category(int category, int cflag, int kflag) 988*7c478bd9Sstevel@tonic-gate { 989*7c478bd9Sstevel@tonic-gate int i; 990*7c478bd9Sstevel@tonic-gate int retval = 0; 991*7c478bd9Sstevel@tonic-gate 992*7c478bd9Sstevel@tonic-gate if (category == LC_ALL) { 993*7c478bd9Sstevel@tonic-gate retval += print_category(LC_CTYPE, cflag, kflag); 994*7c478bd9Sstevel@tonic-gate retval += print_category(LC_NUMERIC, cflag, kflag); 995*7c478bd9Sstevel@tonic-gate retval += print_category(LC_TIME, cflag, kflag); 996*7c478bd9Sstevel@tonic-gate retval += print_category(LC_COLLATE, cflag, kflag); 997*7c478bd9Sstevel@tonic-gate retval += print_category(LC_MONETARY, cflag, kflag); 998*7c478bd9Sstevel@tonic-gate retval += print_category(LC_MESSAGES, cflag, kflag); 999*7c478bd9Sstevel@tonic-gate } else { 1000*7c478bd9Sstevel@tonic-gate if (cflag) { 1001*7c478bd9Sstevel@tonic-gate (void) printf("%s\n", 1002*7c478bd9Sstevel@tonic-gate locale_name[category].name); 1003*7c478bd9Sstevel@tonic-gate } 1004*7c478bd9Sstevel@tonic-gate 1005*7c478bd9Sstevel@tonic-gate for (i = 0; key[i].name != NULL; i++) { 1006*7c478bd9Sstevel@tonic-gate if (key[i].category == category) { 1007*7c478bd9Sstevel@tonic-gate retval += print_keyword(key[i].name, 0, kflag); 1008*7c478bd9Sstevel@tonic-gate } 1009*7c478bd9Sstevel@tonic-gate } 1010*7c478bd9Sstevel@tonic-gate } 1011*7c478bd9Sstevel@tonic-gate return (retval); 1012*7c478bd9Sstevel@tonic-gate } 1013*7c478bd9Sstevel@tonic-gate 1014*7c478bd9Sstevel@tonic-gate /* 1015*7c478bd9Sstevel@tonic-gate * usage message for locale 1016*7c478bd9Sstevel@tonic-gate */ 1017*7c478bd9Sstevel@tonic-gate static void 1018*7c478bd9Sstevel@tonic-gate usage(void) 1019*7c478bd9Sstevel@tonic-gate { 1020*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 1021*7c478bd9Sstevel@tonic-gate "Usage: locale [-a|-m]\n" 1022*7c478bd9Sstevel@tonic-gate " locale [-ck] name ...\n")); 1023*7c478bd9Sstevel@tonic-gate exit(2); 1024*7c478bd9Sstevel@tonic-gate } 1025*7c478bd9Sstevel@tonic-gate 1026*7c478bd9Sstevel@tonic-gate static void 1027*7c478bd9Sstevel@tonic-gate prt_ctp(char *name) 1028*7c478bd9Sstevel@tonic-gate { 1029*7c478bd9Sstevel@tonic-gate int idx, i, mem; 1030*7c478bd9Sstevel@tonic-gate int first = 1; 1031*7c478bd9Sstevel@tonic-gate 1032*7c478bd9Sstevel@tonic-gate static const char *reg_names[] = { 1033*7c478bd9Sstevel@tonic-gate "upper", "lower", "alpha", "digit", "space", "cntrl", 1034*7c478bd9Sstevel@tonic-gate "punct", "graph", "print", "xdigit", "blank", NULL 1035*7c478bd9Sstevel@tonic-gate }; 1036*7c478bd9Sstevel@tonic-gate for (idx = 0; reg_names[idx] != NULL; idx++) { 1037*7c478bd9Sstevel@tonic-gate if (strcmp(name, reg_names[idx]) == 0) { 1038*7c478bd9Sstevel@tonic-gate break; 1039*7c478bd9Sstevel@tonic-gate } 1040*7c478bd9Sstevel@tonic-gate } 1041*7c478bd9Sstevel@tonic-gate if (reg_names[idx] == NULL) { 1042*7c478bd9Sstevel@tonic-gate return; 1043*7c478bd9Sstevel@tonic-gate } 1044*7c478bd9Sstevel@tonic-gate 1045*7c478bd9Sstevel@tonic-gate for (i = 0; i < CSSIZE; i++) { 1046*7c478bd9Sstevel@tonic-gate mem = 0; 1047*7c478bd9Sstevel@tonic-gate switch (idx) { 1048*7c478bd9Sstevel@tonic-gate case 0: 1049*7c478bd9Sstevel@tonic-gate mem = isupper(i); 1050*7c478bd9Sstevel@tonic-gate break; 1051*7c478bd9Sstevel@tonic-gate case 1: 1052*7c478bd9Sstevel@tonic-gate mem = islower(i); 1053*7c478bd9Sstevel@tonic-gate break; 1054*7c478bd9Sstevel@tonic-gate case 2: 1055*7c478bd9Sstevel@tonic-gate mem = isalpha(i); 1056*7c478bd9Sstevel@tonic-gate break; 1057*7c478bd9Sstevel@tonic-gate case 3: 1058*7c478bd9Sstevel@tonic-gate mem = isdigit(i); 1059*7c478bd9Sstevel@tonic-gate break; 1060*7c478bd9Sstevel@tonic-gate case 4: 1061*7c478bd9Sstevel@tonic-gate mem = isspace(i); 1062*7c478bd9Sstevel@tonic-gate break; 1063*7c478bd9Sstevel@tonic-gate case 5: 1064*7c478bd9Sstevel@tonic-gate mem = iscntrl(i); 1065*7c478bd9Sstevel@tonic-gate break; 1066*7c478bd9Sstevel@tonic-gate case 6: 1067*7c478bd9Sstevel@tonic-gate mem = ispunct(i); 1068*7c478bd9Sstevel@tonic-gate break; 1069*7c478bd9Sstevel@tonic-gate case 7: 1070*7c478bd9Sstevel@tonic-gate mem = isgraph(i); 1071*7c478bd9Sstevel@tonic-gate break; 1072*7c478bd9Sstevel@tonic-gate case 8: 1073*7c478bd9Sstevel@tonic-gate mem = isprint(i); 1074*7c478bd9Sstevel@tonic-gate break; 1075*7c478bd9Sstevel@tonic-gate case 9: 1076*7c478bd9Sstevel@tonic-gate mem = isxdigit(i); 1077*7c478bd9Sstevel@tonic-gate break; 1078*7c478bd9Sstevel@tonic-gate case 10: 1079*7c478bd9Sstevel@tonic-gate mem = isblank(i); 1080*7c478bd9Sstevel@tonic-gate break; 1081*7c478bd9Sstevel@tonic-gate } 1082*7c478bd9Sstevel@tonic-gate if (mem) { 1083*7c478bd9Sstevel@tonic-gate if (!first) { 1084*7c478bd9Sstevel@tonic-gate (void) putchar(';'); 1085*7c478bd9Sstevel@tonic-gate } 1086*7c478bd9Sstevel@tonic-gate first = 0; 1087*7c478bd9Sstevel@tonic-gate (void) printf("\""); 1088*7c478bd9Sstevel@tonic-gate outchar(i); 1089*7c478bd9Sstevel@tonic-gate (void) printf("\""); 1090*7c478bd9Sstevel@tonic-gate } 1091*7c478bd9Sstevel@tonic-gate } 1092*7c478bd9Sstevel@tonic-gate } 1093*7c478bd9Sstevel@tonic-gate 1094*7c478bd9Sstevel@tonic-gate static void 1095*7c478bd9Sstevel@tonic-gate prt_cnv(char *name) 1096*7c478bd9Sstevel@tonic-gate { 1097*7c478bd9Sstevel@tonic-gate int idx, i, q; 1098*7c478bd9Sstevel@tonic-gate int first = 1; 1099*7c478bd9Sstevel@tonic-gate 1100*7c478bd9Sstevel@tonic-gate static const char *reg_names[] = { 1101*7c478bd9Sstevel@tonic-gate "toupper", "tolower", NULL 1102*7c478bd9Sstevel@tonic-gate }; 1103*7c478bd9Sstevel@tonic-gate for (idx = 0; reg_names[idx] != NULL; idx++) { 1104*7c478bd9Sstevel@tonic-gate if (strcmp(name, reg_names[idx]) == 0) { 1105*7c478bd9Sstevel@tonic-gate break; 1106*7c478bd9Sstevel@tonic-gate } 1107*7c478bd9Sstevel@tonic-gate } 1108*7c478bd9Sstevel@tonic-gate if (reg_names[idx] == NULL) { 1109*7c478bd9Sstevel@tonic-gate return; 1110*7c478bd9Sstevel@tonic-gate } 1111*7c478bd9Sstevel@tonic-gate 1112*7c478bd9Sstevel@tonic-gate for (i = 0; i < CSSIZE; i++) { 1113*7c478bd9Sstevel@tonic-gate switch (idx) { 1114*7c478bd9Sstevel@tonic-gate case 0: 1115*7c478bd9Sstevel@tonic-gate q = toupper(i); 1116*7c478bd9Sstevel@tonic-gate if (q == i) { 1117*7c478bd9Sstevel@tonic-gate continue; 1118*7c478bd9Sstevel@tonic-gate } 1119*7c478bd9Sstevel@tonic-gate if (!first) { 1120*7c478bd9Sstevel@tonic-gate (void) putchar(';'); 1121*7c478bd9Sstevel@tonic-gate } 1122*7c478bd9Sstevel@tonic-gate first = 0; 1123*7c478bd9Sstevel@tonic-gate /* BEGIN CSTYLED */ 1124*7c478bd9Sstevel@tonic-gate (void) printf("\"<'"); 1125*7c478bd9Sstevel@tonic-gate /* END CSTYLED */ 1126*7c478bd9Sstevel@tonic-gate outchar(i); 1127*7c478bd9Sstevel@tonic-gate (void) printf("','"); 1128*7c478bd9Sstevel@tonic-gate outchar(q); 1129*7c478bd9Sstevel@tonic-gate (void) printf("'>\""); 1130*7c478bd9Sstevel@tonic-gate break; 1131*7c478bd9Sstevel@tonic-gate case 1: 1132*7c478bd9Sstevel@tonic-gate q = tolower(i); 1133*7c478bd9Sstevel@tonic-gate if (q == i) { 1134*7c478bd9Sstevel@tonic-gate continue; 1135*7c478bd9Sstevel@tonic-gate } 1136*7c478bd9Sstevel@tonic-gate if (!first) { 1137*7c478bd9Sstevel@tonic-gate (void) putchar(';'); 1138*7c478bd9Sstevel@tonic-gate } 1139*7c478bd9Sstevel@tonic-gate first = 0; 1140*7c478bd9Sstevel@tonic-gate /* BEGIN CSTYLED */ 1141*7c478bd9Sstevel@tonic-gate (void) printf("\"<'"); 1142*7c478bd9Sstevel@tonic-gate /* END CSTYLED */ 1143*7c478bd9Sstevel@tonic-gate outchar(i); 1144*7c478bd9Sstevel@tonic-gate (void) printf("','"); 1145*7c478bd9Sstevel@tonic-gate outchar(q); 1146*7c478bd9Sstevel@tonic-gate (void) printf("'>\""); 1147*7c478bd9Sstevel@tonic-gate break; 1148*7c478bd9Sstevel@tonic-gate } 1149*7c478bd9Sstevel@tonic-gate } 1150*7c478bd9Sstevel@tonic-gate } 1151*7c478bd9Sstevel@tonic-gate 1152*7c478bd9Sstevel@tonic-gate /* 1153*7c478bd9Sstevel@tonic-gate * prt_collel(): Stub for the collate class which does nothing. 1154*7c478bd9Sstevel@tonic-gate */ 1155*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 1156*7c478bd9Sstevel@tonic-gate static void 1157*7c478bd9Sstevel@tonic-gate prt_collel(char *name) 1158*7c478bd9Sstevel@tonic-gate { 1159*7c478bd9Sstevel@tonic-gate } 1160*7c478bd9Sstevel@tonic-gate 1161*7c478bd9Sstevel@tonic-gate static char 1162*7c478bd9Sstevel@tonic-gate get_escapechar(void) 1163*7c478bd9Sstevel@tonic-gate { 1164*7c478bd9Sstevel@tonic-gate return ('\\'); 1165*7c478bd9Sstevel@tonic-gate } 1166*7c478bd9Sstevel@tonic-gate 1167*7c478bd9Sstevel@tonic-gate static char 1168*7c478bd9Sstevel@tonic-gate get_commentchar(void) 1169*7c478bd9Sstevel@tonic-gate { 1170*7c478bd9Sstevel@tonic-gate return ('#'); 1171*7c478bd9Sstevel@tonic-gate } 1172