Home | History | Annotate | Download | only in common
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  *
     21  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
     22  * Use is subject to license terms.
     23  */
     24 
     25 #include <libintl.h>
     26 #include <locale.h>
     27 #include <sys/varargs.h>
     28 #include <string.h>
     29 #include <stdlib.h>
     30 #include <stdio.h>
     31 #include <ctype.h>
     32 #include "mms_parser.h"
     33 #include "mms_strapp.h"
     34 #include "mms_trace.h"
     35 #include "mms_sym.h"
     36 #include "msg_sub.h"
     37 #include "mms_cat.h"
     38 
     39 static char	*_SrcFile = __FILE__;
     40 
     41 /*
     42  * Message Catalog
     43  */
     44 
     45 
     46 /*
     47  * Gettext is not redefined here so the C preprocessor output from
     48  * this file can be used for mms message catalog generation. The
     49  * MMS_CAT define is a C preprocessor flag.
     50  */
     51 #ifndef MMS_CAT
     52 #define	gettext(s) s
     53 #endif
     54 
     55 /*
     56  * Get the messsageids and message format strings when the message
     57  * header files are included below.
     58  */
     59 #define	MM_MSG(n, s)		s, n,
     60 #define	MMS_API_MSG(n, s)	s, n,
     61 #define	WCR_MSG(n, s)		s, n,
     62 #define	DM_MSG(n, s)		s, n,
     63 #define	LM_MSG(n, s)		s, n,
     64 
     65 /*
     66  * Message array used to lookup a message format string by messageid.
     67  */
     68 static mms_sym_t	_mms_msg_cat[] = {
     69 /*
     70  * Message header files
     71  */
     72 #include <mms_mm_msg.h>
     73 #include <mms_api_msg.h>
     74 #include <mms_wcr_msg.h>
     75 #include <mms_dm_msg.h>
     76 #include <mms_lm_msg.h>
     77 	NULL, 0
     78 };
     79 
     80 /*
     81  * Gettext is once again used to localize the message format string.
     82  */
     83 #ifndef MMS_CAT
     84 #undef gettext
     85 #endif
     86 
     87 static mms_sym_t	*mms_msg_cat = _mms_msg_cat;
     88 static int	mms_msg_cat_num = sizeof (_mms_msg_cat) / sizeof (mms_sym_t);
     89 
     90 void
     91 mms_cat_open(void)
     92 {
     93 	/*
     94 	 * Locale is "C" so the API, WCR, DM and LM use the
     95 	 * English (EN) language. MM will reset locale based
     96 	 * on client application preference.
     97 	 */
     98 	(void) setlocale(LC_MESSAGES, "C");
     99 
    100 	/*
    101 	 * Set the message catalog file name.
    102 	 */
    103 	(void) textdomain(TEXT_DOMAIN);
    104 
    105 	/*
    106 	 * Sort the message format strings.
    107 	 */
    108 	mms_sort_sym_code(mms_msg_cat, mms_msg_cat_num);
    109 }
    110 
    111 char *
    112 mms_get_cat_msg(int msgid)
    113 {
    114 	mms_sym_t	*mms_sym;
    115 	char		*fmt;
    116 
    117 	mms_sym = mms_lookup_sym_code(msgid, mms_msg_cat, mms_msg_cat_num);
    118 	if (mms_sym != NULL && mms_sym->sym_token != NULL) {
    119 		fmt = gettext(mms_sym->sym_token);
    120 	} else {
    121 		fmt = NULL;
    122 	}
    123 
    124 	return (fmt);
    125 }
    126 
    127 char *
    128 mms_get_msg(mms_par_node_t *message)
    129 {
    130 	int	msgid;
    131 
    132 	char	*p;
    133 	char	*fmt;
    134 	char	*text = NULL;
    135 	char	*man;
    136 	char	*model;
    137 	char	err_msg[128];
    138 
    139 	mms_par_node_t	*clause;
    140 	mms_par_node_t	*arg;
    141 	mms_par_node_t	*name;
    142 	mms_par_node_t	*value;
    143 	mms_par_node_t	*loc;
    144 
    145 	/*
    146 	 * Parse and localize command's message-clause
    147 	 */
    148 
    149 	MMS_PN_LOOKUP(arg, message, "id", MMS_PN_CLAUSE, NULL);
    150 	loc = NULL;
    151 	MMS_PN_LOOKUP(value, arg, NULL, MMS_PN_STRING, &loc);
    152 	man = value->pn_string;
    153 
    154 	MMS_PN_LOOKUP(value, arg, NULL, MMS_PN_STRING, &loc);
    155 	model = value->pn_string;
    156 
    157 	MMS_PN_LOOKUP(value, arg, NULL, MMS_PN_STRING, &loc);
    158 	msgid = atoi(value->pn_string);
    159 
    160 
    161 	/* lookup localized message */
    162 	fmt = mms_get_cat_msg(msgid);
    163 	if (fmt == NULL || fmt[0] == '\0') {
    164 			/* No message found in catalog, obtain loctext */
    165 			/* if one exists and output it */
    166 		goto get_loctext;
    167 	}
    168 
    169 		/* Make copy so args can be substituted */
    170 	text = strdup(fmt);
    171 
    172 		/* Get any arguments for message */
    173 	if (arg = mms_pn_lookup(message, "arguments", MMS_PN_CLAUSE,
    174 	    NULL)) {
    175 			/* Substitute each argument with value in message */
    176 		mms_list_pair_foreach(&arg->pn_arglist, name, value) {
    177 
    178 			if (name == NULL || value == NULL)
    179 				goto get_loctext;
    180 
    181 			if ((p = mms_msg_sub(text, name->pn_string,
    182 			    value->pn_string)) == NULL) {
    183 				mms_trace(MMS_ERR, "mms_get_msg: message "
    184 				    "argument substitution failed");
    185 				free(text);
    186 				goto get_loctext;
    187 			}
    188 			free(text);
    189 			text = p;
    190 		}
    191 	}
    192 
    193 	mms_trace(MMS_DEBUG,
    194 	    "mms_get_msg: %s %s %d - %s", man, model, msgid, text);
    195 	return (text);
    196 
    197 not_found:
    198 	mms_trace(MMS_ERR, "mms_get_msg: Missing components to message clause");
    199 	return (NULL);
    200 
    201 get_loctext:
    202 	clause = mms_pn_lookup(message, "loctext", MMS_PN_CLAUSE, NULL);
    203 	if (clause != NULL) {
    204 		loc = NULL;
    205 		value = mms_pn_lookup(clause, NULL, MMS_PN_STRING, &loc);
    206 		value = mms_pn_lookup(clause, NULL, MMS_PN_STRING, &loc);
    207 		if (value != NULL) {
    208 			if ((text = value->pn_string) != NULL) {
    209 				mms_trace(MMS_OPER, "mms_get_msg: loctext "
    210 				    "message is:\n%s", text);
    211 				return (text);
    212 			}
    213 		}
    214 	}
    215 	mms_trace(MMS_OPER, "mms_get_msg: No message found in catalog and "
    216 	    "no loctext found in message");
    217 	(void) snprintf(err_msg, sizeof (err_msg),
    218 	    "Unknown Message: Manufacturer: %s, Model: %s, "
    219 	    "Messageid: %d", man, model, msgid);
    220 	text = strdup(err_msg);
    221 	return (text);
    222 }
    223 
    224 static char *
    225 mms_get_locale(char *locale, int len)
    226 {
    227 	char	*lang;
    228 	int	i;
    229 
    230 	locale[0] = '\0';
    231 	lang = setlocale(LC_MESSAGES, NULL);
    232 	if (lang == NULL || lang[0] == 'C') {
    233 		(void) snprintf(locale, len, "EN");
    234 	} else {
    235 		for (i = 0; i < len - 1 && islower(lang[i]); i++) {
    236 			locale[i] = (char)toupper(lang[i]);
    237 			locale[i+1] = '\0';
    238 		}
    239 	}
    240 	return (locale);
    241 }
    242 
    243 char *
    244 mms_get_msgcl(int msgid, ...)
    245 {
    246 	char	*msg;
    247 	va_list	args;
    248 
    249 	va_start(args, msgid);
    250 	msg = mms_bld_msgcl(msgid, args);
    251 	va_end(args);
    252 	return (msg);
    253 }
    254 
    255 char *
    256 mms_buf_msgcl(char *buf, int len, int msgid, ...)
    257 {
    258 	char	*msg;
    259 	va_list	args;
    260 
    261 	if (buf != NULL && len > 0) {
    262 		va_start(args, msgid);
    263 		msg = mms_bld_msgcl(msgid, args);
    264 		va_end(args);
    265 
    266 		buf[0] = '\0';
    267 		if (msg != NULL) {
    268 			(void) snprintf(buf, len, "%s", msg);
    269 			free(msg);
    270 		}
    271 	}
    272 	return (buf);
    273 }
    274 
    275 char *
    276 mms_bld_msgcl(int msgid, va_list args)
    277 {
    278 	char		*msgcl = NULL;
    279 	char		*msgfmt;
    280 	char		*arg_key;
    281 	char		*arg_text;
    282 	char		*loctext = NULL;
    283 	char		*argcl = NULL;
    284 	char		*arglist = NULL;
    285 	va_list		argscp;
    286 	char		lang[20];
    287 
    288 	/*
    289 	 * Get language
    290 	 */
    291 	(void) mms_get_locale(lang, sizeof (lang));
    292 
    293 	/*
    294 	 * Get message format string
    295 	 */
    296 	msgfmt = mms_get_cat_msg(msgid);
    297 	if (msgfmt == NULL || msgfmt[0] == '\0') {
    298 		/* Undefined message */
    299 		mms_trace(MMS_ERR, "Undefined message id '%d'", msgid);
    300 		return (msgcl);
    301 	}
    302 
    303 	/*
    304 	 * Create argument list
    305 	 */
    306 	va_copy(argscp, args);
    307 	while ((arg_key = va_arg(argscp, char *)) != NULL) {
    308 		if ((arg_text = va_arg(argscp, char *)) == NULL) {
    309 			break;
    310 		}
    311 		arglist = mms_strapp(arglist, "'%s' '%s' ", arg_key, arg_text);
    312 	}
    313 	va_end(argscp);
    314 
    315 	if (arglist) {
    316 		argcl = mms_strnew("arguments [ %s ] ", arglist);
    317 		free(arglist);
    318 	} else {
    319 		argcl = strdup("");
    320 	}
    321 
    322 	/*
    323 	 * Localize message
    324 	 */
    325 	if ((loctext = mms_get_locstr(msgid, args)) == NULL) {
    326 		loctext = strdup("\0");
    327 	}
    328 
    329 	/*
    330 	 * Build message clause
    331 	 */
    332 	msgcl = mms_strapp(msgcl, "message [ id [ 'SUNW' 'MMS' '%d' ] %s "
    333 	    "loctext [ '%s' '%s' ]] ", msgid, argcl, lang, loctext);
    334 	free(argcl);
    335 	free(loctext);
    336 	return (msgcl);
    337 }
    338 
    339 char *
    340 mms_get_locstr(int msgid, va_list args)
    341 {
    342 	char	*s1;
    343 	char	*s2;
    344 	char	*arg_key;
    345 	char	*arg_text;
    346 	char	*msgfmt;
    347 
    348 	/*
    349 	 * Get localized message format string.
    350 	 */
    351 	msgfmt = mms_get_cat_msg(msgid);
    352 	if (msgfmt == NULL || msgfmt[0] == '\0') {
    353 		/* Undefined message */
    354 		mms_trace(MMS_ERR, "Undefined message id '%d'", msgid);
    355 		return (NULL);
    356 	}
    357 
    358 	/*
    359 	 * Substitute message arguments into message format string
    360 	 * to create a localized message string.
    361 	 */
    362 	s1 = strdup(msgfmt);
    363 	while ((arg_key = va_arg(args, char *)) != NULL) {
    364 		if ((arg_text = va_arg(args, char *)) == NULL) {
    365 			break;
    366 		}
    367 		s2 = mms_msg_sub(s1, arg_key, arg_text);
    368 		free(s1);
    369 		s1 = s2;
    370 	}
    371 	return (s1);
    372 }
    373