xref: /illumos-gate/usr/src/lib/libc/port/gen/fmtmsg.c (revision 004388ebfdfe2ed7dfd2d153a876dfcc22d2c006)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*004388ebScasper  * Common Development and Distribution License (the "License").
6*004388ebScasper  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22*004388ebScasper  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
277c478bd9Sstevel@tonic-gate 
287c478bd9Sstevel@tonic-gate /*	Copyright (c) 1988 AT&T	*/
297c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
307c478bd9Sstevel@tonic-gate 
317c478bd9Sstevel@tonic-gate 
327c478bd9Sstevel@tonic-gate /*
337c478bd9Sstevel@tonic-gate  * fmtmsg.c
347c478bd9Sstevel@tonic-gate  *
357c478bd9Sstevel@tonic-gate  *  Contains:
367c478bd9Sstevel@tonic-gate  *	fmtmsg()	Writes a message in standard format.
377c478bd9Sstevel@tonic-gate  *	addseverity()	Adds a severity definition to the list of known
387c478bd9Sstevel@tonic-gate  *			severity definitions.
397c478bd9Sstevel@tonic-gate  *
407c478bd9Sstevel@tonic-gate  *	Notes:
417c478bd9Sstevel@tonic-gate  *	  - None of these functions can use strtok().
427c478bd9Sstevel@tonic-gate  */
437c478bd9Sstevel@tonic-gate 
447c478bd9Sstevel@tonic-gate /*
457c478bd9Sstevel@tonic-gate  * Header Files Referenced:
467c478bd9Sstevel@tonic-gate  *	<stdio.h>		C Standard I/O Definitions
477c478bd9Sstevel@tonic-gate  *	<string.h>		C string handling definitions
487c478bd9Sstevel@tonic-gate  *	<fcntl.h>		UNIX file control definitions
497c478bd9Sstevel@tonic-gate  *	<errno.h>		UNIX error numbers and definitions
507c478bd9Sstevel@tonic-gate  *	<fmtmsg.h>		Global definitions for fmtmsg()
517c478bd9Sstevel@tonic-gate  *	<stdlib.h>		miscellaneous function declarations
527c478bd9Sstevel@tonic-gate  */
537c478bd9Sstevel@tonic-gate 
547c478bd9Sstevel@tonic-gate #pragma weak fmtmsg = _fmtmsg
557c478bd9Sstevel@tonic-gate #pragma weak addseverity = _addseverity
567c478bd9Sstevel@tonic-gate #include "synonyms.h"
577c478bd9Sstevel@tonic-gate #include "mtlib.h"
587c478bd9Sstevel@tonic-gate #include "libc.h"
597c478bd9Sstevel@tonic-gate #include <sys/types.h>
607c478bd9Sstevel@tonic-gate #include <stddef.h>
617c478bd9Sstevel@tonic-gate #include <stdio.h>
627c478bd9Sstevel@tonic-gate #include <string.h>
637c478bd9Sstevel@tonic-gate #include <fcntl.h>
647c478bd9Sstevel@tonic-gate #include <errno.h>
657c478bd9Sstevel@tonic-gate #include <fmtmsg.h>
667c478bd9Sstevel@tonic-gate #include <stdlib.h>
677c478bd9Sstevel@tonic-gate #include <thread.h>
687c478bd9Sstevel@tonic-gate #include <synch.h>
697c478bd9Sstevel@tonic-gate #include <alloca.h>
707c478bd9Sstevel@tonic-gate 
717c478bd9Sstevel@tonic-gate /*
727c478bd9Sstevel@tonic-gate  * External functions referenced:
737c478bd9Sstevel@tonic-gate  *	(Others may be defined in header files above)
747c478bd9Sstevel@tonic-gate  *
757c478bd9Sstevel@tonic-gate  *	getenv		Extracts data from the environment
767c478bd9Sstevel@tonic-gate  *	libc_malloc	Allocates space from main memory
777c478bd9Sstevel@tonic-gate  *	libc_free	Frees space allocated via libc_malloc()
787c478bd9Sstevel@tonic-gate  *	strtol		Convert string to "long"
797c478bd9Sstevel@tonic-gate  *	clearerr	Clears an error on a stream (this is to make "lint"
807c478bd9Sstevel@tonic-gate  *			happy)
817c478bd9Sstevel@tonic-gate  */
827c478bd9Sstevel@tonic-gate 
837c478bd9Sstevel@tonic-gate 
847c478bd9Sstevel@tonic-gate /*
857c478bd9Sstevel@tonic-gate  * Local Constant Definitions
867c478bd9Sstevel@tonic-gate  */
877c478bd9Sstevel@tonic-gate 
887c478bd9Sstevel@tonic-gate /*
897c478bd9Sstevel@tonic-gate  * Boolean constants
907c478bd9Sstevel@tonic-gate  *	TRUE	Boolean value for "true" (any bits on)
917c478bd9Sstevel@tonic-gate  *	FALSE	Boolean value for "false" (all bits off)
927c478bd9Sstevel@tonic-gate  */
937c478bd9Sstevel@tonic-gate 
947c478bd9Sstevel@tonic-gate #ifndef	FALSE
957c478bd9Sstevel@tonic-gate #define	FALSE		(0)
967c478bd9Sstevel@tonic-gate #endif
977c478bd9Sstevel@tonic-gate 
987c478bd9Sstevel@tonic-gate #ifndef TRUE
997c478bd9Sstevel@tonic-gate #define	TRUE		(1)
1007c478bd9Sstevel@tonic-gate #endif
1017c478bd9Sstevel@tonic-gate 
1027c478bd9Sstevel@tonic-gate #define	MAX_MSG_SIZE	1024
1037c478bd9Sstevel@tonic-gate 
1047c478bd9Sstevel@tonic-gate /*
1057c478bd9Sstevel@tonic-gate  * Keywords for fields named in the MSGVERB environment variable.
1067c478bd9Sstevel@tonic-gate  */
1077c478bd9Sstevel@tonic-gate 
1087c478bd9Sstevel@tonic-gate #define	ST_LBL		"label"
1097c478bd9Sstevel@tonic-gate #define	ST_SEV		"severity"
1107c478bd9Sstevel@tonic-gate #define	ST_TXT		"text"
1117c478bd9Sstevel@tonic-gate #define	ST_TAG		"tag"
1127c478bd9Sstevel@tonic-gate #define	ST_ACT		"action"
1137c478bd9Sstevel@tonic-gate 
1147c478bd9Sstevel@tonic-gate 
1157c478bd9Sstevel@tonic-gate /*
1167c478bd9Sstevel@tonic-gate  *	The following constants define the value of the "msgverb"
1177c478bd9Sstevel@tonic-gate  *	variable.  This variable tells fmtmsg() which parts of the
1187c478bd9Sstevel@tonic-gate  *	standard message it is to display.  If !(msgverb&MV_SET),
1197c478bd9Sstevel@tonic-gate  *	fmtmsg() will interrogate the "MSGVERB" environment variable
1207c478bd9Sstevel@tonic-gate  *	and set "msgverb" accordingly.
1217c478bd9Sstevel@tonic-gate  *
1227c478bd9Sstevel@tonic-gate  *	NOTE:  This means that if MSGVERB changes after the first call
1237c478bd9Sstevel@tonic-gate  *	       to fmtmsg(), it will be ignored.
1247c478bd9Sstevel@tonic-gate  *
1257c478bd9Sstevel@tonic-gate  *	Constants:
1267c478bd9Sstevel@tonic-gate  *		MV_INV	Check MSGVERB environment variable (invalidates value)
1277c478bd9Sstevel@tonic-gate  *		MV_SET	MSGVERB checked, msgverb value valid
1287c478bd9Sstevel@tonic-gate  *		MV_LBL	"label" selected
1297c478bd9Sstevel@tonic-gate  *		MV_SEV	"severity" selected
1307c478bd9Sstevel@tonic-gate  *		MV_TXT	"text" selected
1317c478bd9Sstevel@tonic-gate  *		MV_TAG	"messageID" selected
1327c478bd9Sstevel@tonic-gate  *		MV_ACT	"action" selected
1337c478bd9Sstevel@tonic-gate  *
1347c478bd9Sstevel@tonic-gate  *		MV_ALL	All components selected
1357c478bd9Sstevel@tonic-gate  *		MV_DFLT	Default value for MSGVERB
1367c478bd9Sstevel@tonic-gate  */
1377c478bd9Sstevel@tonic-gate 
1387c478bd9Sstevel@tonic-gate #define	MV_INV		0
1397c478bd9Sstevel@tonic-gate #define	MV_SET		0x0001
1407c478bd9Sstevel@tonic-gate #define	MV_LBL		0x0002
1417c478bd9Sstevel@tonic-gate #define	MV_SEV		0x0004
1427c478bd9Sstevel@tonic-gate #define	MV_TXT		0x0008
1437c478bd9Sstevel@tonic-gate #define	MV_TAG		0x0010
1447c478bd9Sstevel@tonic-gate #define	MV_ACT		0x0020
1457c478bd9Sstevel@tonic-gate 
1467c478bd9Sstevel@tonic-gate #define	MV_ALL		(MV_LBL|MV_SEV|MV_TXT|MV_TAG|MV_ACT)
1477c478bd9Sstevel@tonic-gate #define	MV_DFLT		(MV_LBL|MV_SEV|MV_TXT|MV_TAG|MV_ACT)
1487c478bd9Sstevel@tonic-gate 
1497c478bd9Sstevel@tonic-gate 
1507c478bd9Sstevel@tonic-gate 
1517c478bd9Sstevel@tonic-gate /*
1527c478bd9Sstevel@tonic-gate  * Strings defining the different severities of a message.
1537c478bd9Sstevel@tonic-gate  * Internationalization may demand that these come from the message database
1547c478bd9Sstevel@tonic-gate  */
1557c478bd9Sstevel@tonic-gate 
1567c478bd9Sstevel@tonic-gate #define	SV_UNK		"UNKNOWN"
1577c478bd9Sstevel@tonic-gate #define	SV_HALT		"HALT"
1587c478bd9Sstevel@tonic-gate #define	SV_ERROR	"ERROR"
1597c478bd9Sstevel@tonic-gate #define	SV_WARN		"WARNING"
1607c478bd9Sstevel@tonic-gate #define	SV_INF		"INFO"
1617c478bd9Sstevel@tonic-gate 
1627c478bd9Sstevel@tonic-gate 
1637c478bd9Sstevel@tonic-gate /*
1647c478bd9Sstevel@tonic-gate  * Text string if none is provided:
1657c478bd9Sstevel@tonic-gate  */
1667c478bd9Sstevel@tonic-gate 
1677c478bd9Sstevel@tonic-gate #define	DEFLT_TEXT	"No text provided with this message"
1687c478bd9Sstevel@tonic-gate 
1697c478bd9Sstevel@tonic-gate 
1707c478bd9Sstevel@tonic-gate /*
1717c478bd9Sstevel@tonic-gate  * Text string introduction for "action".  This may have to come from
1727c478bd9Sstevel@tonic-gate  * the message database because of internationalization.
1737c478bd9Sstevel@tonic-gate  */
1747c478bd9Sstevel@tonic-gate 
1757c478bd9Sstevel@tonic-gate #define	ACTINTRO	"TO FIX: "
1767c478bd9Sstevel@tonic-gate #define	ACTINTROLN	8
1777c478bd9Sstevel@tonic-gate 
1787c478bd9Sstevel@tonic-gate 
1797c478bd9Sstevel@tonic-gate /*
1807c478bd9Sstevel@tonic-gate  * SEPSTR is the string that separates the "label" from what follows it,
1817c478bd9Sstevel@tonic-gate  * and the severity from what follows it.
1827c478bd9Sstevel@tonic-gate  */
1837c478bd9Sstevel@tonic-gate 
1847c478bd9Sstevel@tonic-gate #define	SEPSTR		": "
1857c478bd9Sstevel@tonic-gate #define	SEPSTRLN	2
1867c478bd9Sstevel@tonic-gate 
1877c478bd9Sstevel@tonic-gate 
1887c478bd9Sstevel@tonic-gate /*
1897c478bd9Sstevel@tonic-gate  * Miscellaneous constants:
1907c478bd9Sstevel@tonic-gate  *	CONNAME		Filesystem entry name for the system console
1917c478bd9Sstevel@tonic-gate  */
1927c478bd9Sstevel@tonic-gate 
1937c478bd9Sstevel@tonic-gate #define	CONNAME		"/dev/console"
1947c478bd9Sstevel@tonic-gate 
1957c478bd9Sstevel@tonic-gate /*
1967c478bd9Sstevel@tonic-gate  * Local data type definitions
1977c478bd9Sstevel@tonic-gate  */
1987c478bd9Sstevel@tonic-gate 
1997c478bd9Sstevel@tonic-gate /*
2007c478bd9Sstevel@tonic-gate  * Severity string structure
2017c478bd9Sstevel@tonic-gate  *
2027c478bd9Sstevel@tonic-gate  *	struct sevstr
2037c478bd9Sstevel@tonic-gate  *		sevvalue	Value of the severity-level being defined
2047c478bd9Sstevel@tonic-gate  *		sevkywd		Keyword identifying the severity
2057c478bd9Sstevel@tonic-gate  *		sevprptr	Pointer to the string associated with the value
2067c478bd9Sstevel@tonic-gate  *		sevnext		Pointer to the next value in the list.
2077c478bd9Sstevel@tonic-gate  *
2087c478bd9Sstevel@tonic-gate  *	Restrictions:
2097c478bd9Sstevel@tonic-gate  *		sevvalue	Must be a non-negative integer (>=0)
2107c478bd9Sstevel@tonic-gate  *
2117c478bd9Sstevel@tonic-gate  *	There are three (possibly null) lists of these structures.
2127c478bd9Sstevel@tonic-gate  *	  1)	is the list of standard severities
2137c478bd9Sstevel@tonic-gate  *	  2)	is the list of severity-levels defined by SEV_LEVEL
2147c478bd9Sstevel@tonic-gate  *	  3)	is the list of severity-levels defined by calls to
2157c478bd9Sstevel@tonic-gate  *		addseverity()
2167c478bd9Sstevel@tonic-gate  */
2177c478bd9Sstevel@tonic-gate 
2187c478bd9Sstevel@tonic-gate struct sevstr {
2197c478bd9Sstevel@tonic-gate 	int		sevvalue;
2207c478bd9Sstevel@tonic-gate 	const char	*sevkywd;
2217c478bd9Sstevel@tonic-gate 	const char	*sevprstr;
2227c478bd9Sstevel@tonic-gate 	struct sevstr  *sevnext;
2237c478bd9Sstevel@tonic-gate };
2247c478bd9Sstevel@tonic-gate 
2257c478bd9Sstevel@tonic-gate /*
2267c478bd9Sstevel@tonic-gate  * Local Static Data
2277c478bd9Sstevel@tonic-gate  *	msgverb		int
2287c478bd9Sstevel@tonic-gate  *			Contains the internal representation or the
2297c478bd9Sstevel@tonic-gate  *			MSGVERB environment variable.
2307c478bd9Sstevel@tonic-gate  *	sevlook		TRUE if fmtmsg() has to look at SEV_LEVEL the
2317c478bd9Sstevel@tonic-gate  *			next time it is called.
2327c478bd9Sstevel@tonic-gate  *	paugsevs	struct sevstr *
2337c478bd9Sstevel@tonic-gate  *			Head of the linked list of structures that define
2347c478bd9Sstevel@tonic-gate  *			severities that augment the standard severities,
2357c478bd9Sstevel@tonic-gate  *			as defined by addseverity().
2367c478bd9Sstevel@tonic-gate  *	penvsevs	struct sevstrs *
2377c478bd9Sstevel@tonic-gate  *			Head of the linked list of structures that define
2387c478bd9Sstevel@tonic-gate  *			severities that augment the standard severities,
2397c478bd9Sstevel@tonic-gate  *			as defined by SEV_LEVEL.
2407c478bd9Sstevel@tonic-gate  *	pstdsevs	struct sevstrs *
2417c478bd9Sstevel@tonic-gate  *			Head of the linked list of structures that define
2427c478bd9Sstevel@tonic-gate  *			the standard severities.
2437c478bd9Sstevel@tonic-gate  */
2447c478bd9Sstevel@tonic-gate 
2457c478bd9Sstevel@tonic-gate static mutex_t fmt_lock = DEFAULTMUTEX;
2467c478bd9Sstevel@tonic-gate 
2477c478bd9Sstevel@tonic-gate static	int		msgverb		= 0;
2487c478bd9Sstevel@tonic-gate static	int		sevlook		= TRUE;
2497c478bd9Sstevel@tonic-gate 
2507c478bd9Sstevel@tonic-gate static	struct sevstr  *paugsevs	= (struct sevstr *)NULL;
2517c478bd9Sstevel@tonic-gate static	struct sevstr  *penvsevs	= (struct sevstr *)NULL;
2527c478bd9Sstevel@tonic-gate 
2537c478bd9Sstevel@tonic-gate static	struct sevstr	sevstrs[]	= {
2547c478bd9Sstevel@tonic-gate 	{ MM_HALT,	"", SV_HALT,	&sevstrs[1]},
2557c478bd9Sstevel@tonic-gate 	{ MM_ERROR,    "", SV_ERROR,	&sevstrs[2]},
2567c478bd9Sstevel@tonic-gate 	{ MM_WARNING,  "", SV_WARN, 	&sevstrs[3]},
2577c478bd9Sstevel@tonic-gate 	{ MM_INFO,	"", SV_INF,  	(struct sevstr *)NULL},
2587c478bd9Sstevel@tonic-gate };
2597c478bd9Sstevel@tonic-gate static	struct sevstr  *pstdsevs	= &sevstrs[0];
2607c478bd9Sstevel@tonic-gate 
2617c478bd9Sstevel@tonic-gate /*
2627c478bd9Sstevel@tonic-gate  * static char *exttok(str, delims)
2637c478bd9Sstevel@tonic-gate  *	const char   *str
2647c478bd9Sstevel@tonic-gate  *	const char   *delims
2657c478bd9Sstevel@tonic-gate  *
2667c478bd9Sstevel@tonic-gate  *	This function examines the string pointed to by "str", looking
2677c478bd9Sstevel@tonic-gate  *	for the first occurrence of any of the characters in the string
2687c478bd9Sstevel@tonic-gate  *	whose address is "delims".  It returns the address of that
2697c478bd9Sstevel@tonic-gate  *	character or (char *)NULL if there was nothing to search.
2707c478bd9Sstevel@tonic-gate  *
2717c478bd9Sstevel@tonic-gate  * Arguments:
2727c478bd9Sstevel@tonic-gate  *	str	Address of the string to search
2737c478bd9Sstevel@tonic-gate  *	delims	Address of the string containing delimiters
2747c478bd9Sstevel@tonic-gate  *
2757c478bd9Sstevel@tonic-gate  * Returns:  char *
2767c478bd9Sstevel@tonic-gate  *	Returns the address of the first occurrence of any of the characters
2777c478bd9Sstevel@tonic-gate  *	in "delim" in the string "str" (incl '\0').  If there was nothing
2787c478bd9Sstevel@tonic-gate  *	to search, the function returns (char *)NULL.
2797c478bd9Sstevel@tonic-gate  *
2807c478bd9Sstevel@tonic-gate  * Notes:
2817c478bd9Sstevel@tonic-gate  *    - This function is needed because strtok() can't be used inside a
2827c478bd9Sstevel@tonic-gate  *	function.  Besides, strtok() is destructive in the string, which
2837c478bd9Sstevel@tonic-gate  *	is undesirable in many circumstances.
2847c478bd9Sstevel@tonic-gate  *    - This function understands escaped delimiters as non-delimiters.
2857c478bd9Sstevel@tonic-gate  *	Delimiters are escaped by preceding them with '\' characters.
2867c478bd9Sstevel@tonic-gate  *	The '\' character also must be escaped.
2877c478bd9Sstevel@tonic-gate  */
2887c478bd9Sstevel@tonic-gate 
2897c478bd9Sstevel@tonic-gate static char *
2907c478bd9Sstevel@tonic-gate exttok(const char *tok, const char *delims)
2917c478bd9Sstevel@tonic-gate {
2927c478bd9Sstevel@tonic-gate 	char	*tokend;	/* Ptr to the end of the token */
2937c478bd9Sstevel@tonic-gate 	char	*p, *q;		/* Temp pointers */
2947c478bd9Sstevel@tonic-gate 
2957c478bd9Sstevel@tonic-gate 	/*
2967c478bd9Sstevel@tonic-gate 	 * Algorithm:
2977c478bd9Sstevel@tonic-gate 	 *    1.  Get the starting address(new string or where we
2987c478bd9Sstevel@tonic-gate 	 *	  left off).  If nothing to search, return(char *)NULL
2997c478bd9Sstevel@tonic-gate 	 *    2.  Find the end of the string
3007c478bd9Sstevel@tonic-gate 	 *    3.  Look for the first unescaped delimiter closest to the
3017c478bd9Sstevel@tonic-gate 	 *	  beginning of the string
3027c478bd9Sstevel@tonic-gate 	 *    4.  Remember where we left off
3037c478bd9Sstevel@tonic-gate 	 *    5.  Return a pointer to the delimiter we found
3047c478bd9Sstevel@tonic-gate 	 */
3057c478bd9Sstevel@tonic-gate 
3067c478bd9Sstevel@tonic-gate 	/* Begin at the beginning, if any */
3077c478bd9Sstevel@tonic-gate 	if (tok == (char *)NULL) {
3087c478bd9Sstevel@tonic-gate 		return ((char *)NULL);
3097c478bd9Sstevel@tonic-gate 	}
3107c478bd9Sstevel@tonic-gate 
3117c478bd9Sstevel@tonic-gate 	/* Find end of the token string */
3127c478bd9Sstevel@tonic-gate 	tokend = (char *)tok + (ptrdiff_t)strlen(tok);
3137c478bd9Sstevel@tonic-gate 
3147c478bd9Sstevel@tonic-gate 	/* Look for the 1st occurrence of any delimiter */
3157c478bd9Sstevel@tonic-gate 	for (p = (char *)delims; *p != '\0'; p++) {
3167c478bd9Sstevel@tonic-gate 		for (q = strchr(tok, (int)*p);
3177c478bd9Sstevel@tonic-gate 		    (q != 0) && (q != tok) && (*(q - (ptrdiff_t)1) == '\\');
3187c478bd9Sstevel@tonic-gate 		    q = strchr(q + (ptrdiff_t)1, (int)*p))
3197c478bd9Sstevel@tonic-gate 			;
3207c478bd9Sstevel@tonic-gate 		if ((q != 0) && (q < tokend))
3217c478bd9Sstevel@tonic-gate 			tokend = q;
3227c478bd9Sstevel@tonic-gate 	}
3237c478bd9Sstevel@tonic-gate 
3247c478bd9Sstevel@tonic-gate 	/* Done */
3257c478bd9Sstevel@tonic-gate 	return (tokend);
3267c478bd9Sstevel@tonic-gate }
3277c478bd9Sstevel@tonic-gate 
3287c478bd9Sstevel@tonic-gate /*
3297c478bd9Sstevel@tonic-gate  * char *noesc(str)
3307c478bd9Sstevel@tonic-gate  *
3317c478bd9Sstevel@tonic-gate  *	This function squeezes out all of the escaped character sequences
3327c478bd9Sstevel@tonic-gate  *	from the string <str>.  It returns a pointer to that string.
3337c478bd9Sstevel@tonic-gate  *
3347c478bd9Sstevel@tonic-gate  *  Arguments:
3357c478bd9Sstevel@tonic-gate  *	str	char *
3367c478bd9Sstevel@tonic-gate  *		The string that is to have its escaped characters removed.
3377c478bd9Sstevel@tonic-gate  *
3387c478bd9Sstevel@tonic-gate  *  Returns:  char *
3397c478bd9Sstevel@tonic-gate  *	This function returns its argument <str> always.
3407c478bd9Sstevel@tonic-gate  *
3417c478bd9Sstevel@tonic-gate  *  Notes:
3427c478bd9Sstevel@tonic-gate  *	This function potentially modifies the string it is given.
3437c478bd9Sstevel@tonic-gate  */
3447c478bd9Sstevel@tonic-gate 
3457c478bd9Sstevel@tonic-gate static char *
3467c478bd9Sstevel@tonic-gate noesc(char *str)
3477c478bd9Sstevel@tonic-gate {
3487c478bd9Sstevel@tonic-gate 	char   *p;		/* Temp string pointer */
3497c478bd9Sstevel@tonic-gate 	char   *q;		/* Temp string pointer */
3507c478bd9Sstevel@tonic-gate 
3517c478bd9Sstevel@tonic-gate 	/* Look for an escaped character */
3527c478bd9Sstevel@tonic-gate 	p = str;
3537c478bd9Sstevel@tonic-gate 	while (*p && (*p != '\\')) p++;
3547c478bd9Sstevel@tonic-gate 
3557c478bd9Sstevel@tonic-gate 
3567c478bd9Sstevel@tonic-gate 	/*
3577c478bd9Sstevel@tonic-gate 	 * If there was at least one, squeeze them out
3587c478bd9Sstevel@tonic-gate 	 * Otherwise, don't touch the argument string
3597c478bd9Sstevel@tonic-gate 	 */
3607c478bd9Sstevel@tonic-gate 
3617c478bd9Sstevel@tonic-gate 	if (*p) {
3627c478bd9Sstevel@tonic-gate 		q = p++;
3637c478bd9Sstevel@tonic-gate 		while (*q++ = *p++) {
3647c478bd9Sstevel@tonic-gate 			if (*p == '\\')
3657c478bd9Sstevel@tonic-gate 				p++;
3667c478bd9Sstevel@tonic-gate 		}
3677c478bd9Sstevel@tonic-gate 	}
3687c478bd9Sstevel@tonic-gate 
3697c478bd9Sstevel@tonic-gate 	/* Finished.  Return our argument */
3707c478bd9Sstevel@tonic-gate 	return (str);
3717c478bd9Sstevel@tonic-gate }
3727c478bd9Sstevel@tonic-gate 
3737c478bd9Sstevel@tonic-gate /*
3747c478bd9Sstevel@tonic-gate  * struct sevstr *getauxsevs(ptr)
3757c478bd9Sstevel@tonic-gate  *
3767c478bd9Sstevel@tonic-gate  *	Parses a string that is in the format of the severity definitions.
3777c478bd9Sstevel@tonic-gate  *	Returns a pointer to a (malloc'd) structure that contains the
3787c478bd9Sstevel@tonic-gate  *	definition, or (struct sevstr *)NULL if none was parsed.
3797c478bd9Sstevel@tonic-gate  *
3807c478bd9Sstevel@tonic-gate  * Arguments:
3817c478bd9Sstevel@tonic-gate  *	ptr	char *
3827c478bd9Sstevel@tonic-gate  *		References the string from which data is to be extracted.
3837c478bd9Sstevel@tonic-gate  *		If (char *)NULL, continue where we left off.  Otherwise,
3847c478bd9Sstevel@tonic-gate  *		start with the string referenced by ptr.
3857c478bd9Sstevel@tonic-gate  *
3867c478bd9Sstevel@tonic-gate  * Returns: struct sevstr *
3877c478bd9Sstevel@tonic-gate  *	A pointer to a malloc'd structure containing the severity definition
3887c478bd9Sstevel@tonic-gate  *	parsed from string, or (struct sevstr *)NULL if none.
3897c478bd9Sstevel@tonic-gate  *
3907c478bd9Sstevel@tonic-gate  * Notes:
3917c478bd9Sstevel@tonic-gate  *    - This function is destructive to the string referenced by its argument.
3927c478bd9Sstevel@tonic-gate  */
3937c478bd9Sstevel@tonic-gate 
3947c478bd9Sstevel@tonic-gate /* Static data */
3957c478bd9Sstevel@tonic-gate static	char		*leftoff = (char *)NULL;
3967c478bd9Sstevel@tonic-gate 
3977c478bd9Sstevel@tonic-gate static	struct sevstr *
3987c478bd9Sstevel@tonic-gate getauxsevs(char *ptr)
3997c478bd9Sstevel@tonic-gate {
4007c478bd9Sstevel@tonic-gate 	char		*current;	/* Ptr to current sev def'n */
4017c478bd9Sstevel@tonic-gate 	char		*tokend;	/* Ptr to end of current sev def'n */
4027c478bd9Sstevel@tonic-gate 	char		*kywd;		/* Ptr to extracted kywd */
4037c478bd9Sstevel@tonic-gate 	char		*valstr;		/* Ptr to extracted sev value */
4047c478bd9Sstevel@tonic-gate 	char		*prstr;		/* Ptr to extracted print str */
4057c478bd9Sstevel@tonic-gate 	char		*p;		/* Temp pointer */
4067c478bd9Sstevel@tonic-gate 	int		val;		/* Converted severity value */
4077c478bd9Sstevel@tonic-gate 	int		done;		/* Flag, sev def'n found and ok? */
4087c478bd9Sstevel@tonic-gate 	struct sevstr  *rtnval;		/* Value to return */
4097c478bd9Sstevel@tonic-gate 
4107c478bd9Sstevel@tonic-gate 
4117c478bd9Sstevel@tonic-gate 	/* Start anew or start where we left off? */
4127c478bd9Sstevel@tonic-gate 	current = (ptr == (char *)NULL) ? leftoff : ptr;
4137c478bd9Sstevel@tonic-gate 
4147c478bd9Sstevel@tonic-gate 
4157c478bd9Sstevel@tonic-gate 	/* If nothing to parse, return (char *)NULL */
4167c478bd9Sstevel@tonic-gate 	if (current == (char *)NULL) {
4177c478bd9Sstevel@tonic-gate 		return ((struct sevstr *)NULL);
4187c478bd9Sstevel@tonic-gate 	}
4197c478bd9Sstevel@tonic-gate 
4207c478bd9Sstevel@tonic-gate 
4217c478bd9Sstevel@tonic-gate 	/*
4227c478bd9Sstevel@tonic-gate 	 * Look through the string "current" for a token of the form
4237c478bd9Sstevel@tonic-gate 	 * <kywd>,<sev>,<printstring> delimited by ':' or '\0'
4247c478bd9Sstevel@tonic-gate 	 */
4257c478bd9Sstevel@tonic-gate 
4267c478bd9Sstevel@tonic-gate 	/* Loop initializations */
4277c478bd9Sstevel@tonic-gate 	done = FALSE;
4287c478bd9Sstevel@tonic-gate 	rtnval = (struct sevstr *)NULL;
4297c478bd9Sstevel@tonic-gate 	while (!done) {
4307c478bd9Sstevel@tonic-gate 		/* Eat leading junk */
4317c478bd9Sstevel@tonic-gate 		while (*(tokend = exttok(current, ":,")) == ':') {
4327c478bd9Sstevel@tonic-gate 			current = tokend + (ptrdiff_t)1;
4337c478bd9Sstevel@tonic-gate 		}
4347c478bd9Sstevel@tonic-gate 
4357c478bd9Sstevel@tonic-gate 		/* If we've found a <kywd>,... */
4367c478bd9Sstevel@tonic-gate 		if (*tokend == ',') {
4377c478bd9Sstevel@tonic-gate 			kywd = current;
4387c478bd9Sstevel@tonic-gate 			*tokend = '\0';
4397c478bd9Sstevel@tonic-gate 
4407c478bd9Sstevel@tonic-gate 			/* Look for <kywd>,<sev>,... */
4417c478bd9Sstevel@tonic-gate 			current = tokend + (ptrdiff_t)1;
4427c478bd9Sstevel@tonic-gate 			if (*(tokend = exttok(current, ":,")) == ',') {
4437c478bd9Sstevel@tonic-gate 				valstr = current;
4447c478bd9Sstevel@tonic-gate 				*tokend = '\0';
4457c478bd9Sstevel@tonic-gate 
4467c478bd9Sstevel@tonic-gate 				current = tokend + (ptrdiff_t)1;
4477c478bd9Sstevel@tonic-gate 				prstr = current;
4487c478bd9Sstevel@tonic-gate 
4497c478bd9Sstevel@tonic-gate 				/* Make sure <sev> > 4 */
4507c478bd9Sstevel@tonic-gate 				val = (int)strtol(noesc(valstr), &p, 0);
4517c478bd9Sstevel@tonic-gate 				if ((val > 4) && (p == tokend)) {
4527c478bd9Sstevel@tonic-gate 
4537c478bd9Sstevel@tonic-gate 					/*
4547c478bd9Sstevel@tonic-gate 					 * Found <kywd>,<sev>,<printstring>.
4557c478bd9Sstevel@tonic-gate 					 * remember where we left off
4567c478bd9Sstevel@tonic-gate 					 */
4577c478bd9Sstevel@tonic-gate 
4587c478bd9Sstevel@tonic-gate 					if (*(tokend =
4597c478bd9Sstevel@tonic-gate 						exttok(current, ":")) == ':') {
4607c478bd9Sstevel@tonic-gate 						*tokend = '\0';
4617c478bd9Sstevel@tonic-gate 						leftoff = tokend +
4627c478bd9Sstevel@tonic-gate 						    (ptrdiff_t)1;
4637c478bd9Sstevel@tonic-gate 					} else {
4647c478bd9Sstevel@tonic-gate 						leftoff = (char *)NULL;
4657c478bd9Sstevel@tonic-gate 					}
4667c478bd9Sstevel@tonic-gate 
4677c478bd9Sstevel@tonic-gate 					/*
4687c478bd9Sstevel@tonic-gate 					 * Alloc structure to contain
4697c478bd9Sstevel@tonic-gate 					 * severity definition
4707c478bd9Sstevel@tonic-gate 					 */
4717c478bd9Sstevel@tonic-gate 					rtnval = libc_malloc(
4727c478bd9Sstevel@tonic-gate 					    sizeof (struct sevstr));
4737c478bd9Sstevel@tonic-gate 					if (rtnval != NULL) {
4747c478bd9Sstevel@tonic-gate 
4757c478bd9Sstevel@tonic-gate 						/* Fill in structure */
4767c478bd9Sstevel@tonic-gate 						rtnval->sevkywd = noesc(kywd);
4777c478bd9Sstevel@tonic-gate 						rtnval->sevvalue = val;
4787c478bd9Sstevel@tonic-gate 						rtnval->sevprstr = noesc(prstr);
4797c478bd9Sstevel@tonic-gate 						rtnval->sevnext =
4807c478bd9Sstevel@tonic-gate 						    (struct sevstr *)NULL;
4817c478bd9Sstevel@tonic-gate 					}
4827c478bd9Sstevel@tonic-gate 					done = TRUE;
4837c478bd9Sstevel@tonic-gate 				} else {
4847c478bd9Sstevel@tonic-gate 					/*
4857c478bd9Sstevel@tonic-gate 					 * Invalid severity value,
4867c478bd9Sstevel@tonic-gate 					 * eat thru end of token
4877c478bd9Sstevel@tonic-gate 					 */
4887c478bd9Sstevel@tonic-gate 					current = tokend;
4897c478bd9Sstevel@tonic-gate 					if (*(tokend = exttok(prstr, ":")) ==
4907c478bd9Sstevel@tonic-gate 					    ':') {
4917c478bd9Sstevel@tonic-gate 						current++;
4927c478bd9Sstevel@tonic-gate 					}
4937c478bd9Sstevel@tonic-gate 				}
4947c478bd9Sstevel@tonic-gate 			} else {
4957c478bd9Sstevel@tonic-gate 				/*
4967c478bd9Sstevel@tonic-gate 				 * Invalid severity definition,
4977c478bd9Sstevel@tonic-gate 				 * eat thru end of token
4987c478bd9Sstevel@tonic-gate 				 */
4997c478bd9Sstevel@tonic-gate 				current = tokend;
5007c478bd9Sstevel@tonic-gate 				if (*tokend == ':')
5017c478bd9Sstevel@tonic-gate 					current++;
5027c478bd9Sstevel@tonic-gate 			}
5037c478bd9Sstevel@tonic-gate 		} else {
5047c478bd9Sstevel@tonic-gate 			/* End of string found */
5057c478bd9Sstevel@tonic-gate 			done = TRUE;
5067c478bd9Sstevel@tonic-gate 			leftoff = (char *)NULL;
5077c478bd9Sstevel@tonic-gate 		}
5087c478bd9Sstevel@tonic-gate 	} /* while (!done) */
5097c478bd9Sstevel@tonic-gate 
5107c478bd9Sstevel@tonic-gate 	/* Finished */
5117c478bd9Sstevel@tonic-gate 	return (rtnval);
5127c478bd9Sstevel@tonic-gate }
5137c478bd9Sstevel@tonic-gate 
5147c478bd9Sstevel@tonic-gate /*
5157c478bd9Sstevel@tonic-gate  * void msgverbset()
5167c478bd9Sstevel@tonic-gate  *
5177c478bd9Sstevel@tonic-gate  *	Parces the argument of the MSGVERB environment variable and places
5187c478bd9Sstevel@tonic-gate  *	a representation of the value of that value in "msgverb"
5197c478bd9Sstevel@tonic-gate  *
5207c478bd9Sstevel@tonic-gate  * Arguments:
5217c478bd9Sstevel@tonic-gate  *	None:
5227c478bd9Sstevel@tonic-gate  *
5237c478bd9Sstevel@tonic-gate  * Returns: void
5247c478bd9Sstevel@tonic-gate  *
5257c478bd9Sstevel@tonic-gate  * Notes:
5267c478bd9Sstevel@tonic-gate  */
5277c478bd9Sstevel@tonic-gate 
5287c478bd9Sstevel@tonic-gate static void
5297c478bd9Sstevel@tonic-gate msgverbset(void)
5307c478bd9Sstevel@tonic-gate {
5317c478bd9Sstevel@tonic-gate 	char   *opts;			/* Pointer to MSGVERB's value */
5327c478bd9Sstevel@tonic-gate 	char   *alloced;		/* Pointer to MSGVERB's value */
5337c478bd9Sstevel@tonic-gate 	char   *tok;			/* Pointer to current token */
5347c478bd9Sstevel@tonic-gate 	char   *tokend;			/* Pointer to end of current token */
5357c478bd9Sstevel@tonic-gate 	char   *nexttok;		/* Pointer to next token */
5367c478bd9Sstevel@tonic-gate 
5377c478bd9Sstevel@tonic-gate 
5387c478bd9Sstevel@tonic-gate 	/* Rid ourselves of junk in "msgverb" */
5397c478bd9Sstevel@tonic-gate 	msgverb = 0;
5407c478bd9Sstevel@tonic-gate 
5417c478bd9Sstevel@tonic-gate 	/* Get the value of MSGVERB.  If none, use default value */
5427c478bd9Sstevel@tonic-gate 	if ((opts = getenv(MSGVERB)) == (char *)NULL) {
5437c478bd9Sstevel@tonic-gate 		msgverb = MV_DFLT;
5447c478bd9Sstevel@tonic-gate 	} else { /* MSGVERB has a value.  Interpret it */
5457c478bd9Sstevel@tonic-gate 		if ((alloced = libc_malloc(strlen(opts) + 1)) == NULL) {
5467c478bd9Sstevel@tonic-gate 			msgverb = MV_DFLT;
5477c478bd9Sstevel@tonic-gate 		} else {
5487c478bd9Sstevel@tonic-gate 			/* Make a copy of the value of MSGVERB */
5497c478bd9Sstevel@tonic-gate 			nexttok = strcpy(alloced, opts);
5507c478bd9Sstevel@tonic-gate 
5517c478bd9Sstevel@tonic-gate 			/* Parse the options given by the user */
5527c478bd9Sstevel@tonic-gate 			while ((tok = nexttok) != (char *)NULL) {
5537c478bd9Sstevel@tonic-gate 				/*
5547c478bd9Sstevel@tonic-gate 				 * Find end of the next token and squeeze
5557c478bd9Sstevel@tonic-gate 				 * out escaped characters
5567c478bd9Sstevel@tonic-gate 				 */
5577c478bd9Sstevel@tonic-gate 				tokend = exttok(tok, ":");
5587c478bd9Sstevel@tonic-gate 				tok = noesc(tok);
5597c478bd9Sstevel@tonic-gate 
5607c478bd9Sstevel@tonic-gate 				/* Delimit token and mark next, if any */
5617c478bd9Sstevel@tonic-gate 				if (*tokend == ':') {
5627c478bd9Sstevel@tonic-gate 					nexttok = tokend + (ptrdiff_t)1;
5637c478bd9Sstevel@tonic-gate 					*tokend = '\0';
5647c478bd9Sstevel@tonic-gate 				} else {
5657c478bd9Sstevel@tonic-gate 					nexttok = (char *)NULL;
5667c478bd9Sstevel@tonic-gate 				}
5677c478bd9Sstevel@tonic-gate 
5687c478bd9Sstevel@tonic-gate 				/* Check for "text" */
5697c478bd9Sstevel@tonic-gate 				if (strcmp(tok, ST_TXT) == 0) {
5707c478bd9Sstevel@tonic-gate 					msgverb |= MV_TXT;
5717c478bd9Sstevel@tonic-gate 
5727c478bd9Sstevel@tonic-gate 					/* Check for "label" */
5737c478bd9Sstevel@tonic-gate 				} else if (strcmp(tok, ST_LBL) == 0) {
5747c478bd9Sstevel@tonic-gate 					msgverb |= MV_LBL;
5757c478bd9Sstevel@tonic-gate 
5767c478bd9Sstevel@tonic-gate 					/* Check for "action */
5777c478bd9Sstevel@tonic-gate 				} else if (strcmp(tok, ST_ACT) == 0) {
5787c478bd9Sstevel@tonic-gate 					msgverb |= MV_ACT;
5797c478bd9Sstevel@tonic-gate 
5807c478bd9Sstevel@tonic-gate 					/* Check for "severity" */
5817c478bd9Sstevel@tonic-gate 				} else if (strcmp(tok, ST_SEV) == 0) {
5827c478bd9Sstevel@tonic-gate 					msgverb |= MV_SEV;
5837c478bd9Sstevel@tonic-gate 
5847c478bd9Sstevel@tonic-gate 					/* Check for "tag" */
5857c478bd9Sstevel@tonic-gate 				} else if (strcmp(tok, ST_TAG) == 0) {
5867c478bd9Sstevel@tonic-gate 					msgverb |= MV_TAG;
5877c478bd9Sstevel@tonic-gate 
5887c478bd9Sstevel@tonic-gate 					/* Unknown, ignore MSGVERB value */
5897c478bd9Sstevel@tonic-gate 				} else {
5907c478bd9Sstevel@tonic-gate 					msgverb = MV_DFLT;
5917c478bd9Sstevel@tonic-gate 					nexttok = (char *)NULL;
5927c478bd9Sstevel@tonic-gate 				}
5937c478bd9Sstevel@tonic-gate 			} /* do while */
5947c478bd9Sstevel@tonic-gate 
5957c478bd9Sstevel@tonic-gate 			/*
5967c478bd9Sstevel@tonic-gate 			 * Use default if no keywords on MSGVERB
5977c478bd9Sstevel@tonic-gate 			 * environment variable
5987c478bd9Sstevel@tonic-gate 			 */
5997c478bd9Sstevel@tonic-gate 			if (msgverb == 0)
6007c478bd9Sstevel@tonic-gate 				msgverb = MV_DFLT;
6017c478bd9Sstevel@tonic-gate 
6027c478bd9Sstevel@tonic-gate 			/* Free allocated space */
6037c478bd9Sstevel@tonic-gate 			libc_free(alloced);
6047c478bd9Sstevel@tonic-gate 		}
6057c478bd9Sstevel@tonic-gate 	}
6067c478bd9Sstevel@tonic-gate 	/* Finished */
6077c478bd9Sstevel@tonic-gate 	/* return; */
6087c478bd9Sstevel@tonic-gate }
6097c478bd9Sstevel@tonic-gate 
6107c478bd9Sstevel@tonic-gate /*
6117c478bd9Sstevel@tonic-gate  * void sevstrset()
6127c478bd9Sstevel@tonic-gate  *
6137c478bd9Sstevel@tonic-gate  *	This function builds a structure containing auxillary severity
6147c478bd9Sstevel@tonic-gate  *	definitions.
6157c478bd9Sstevel@tonic-gate  *
6167c478bd9Sstevel@tonic-gate  *  Arguments:  None
6177c478bd9Sstevel@tonic-gate  *
6187c478bd9Sstevel@tonic-gate  *  Returns:  Void
6197c478bd9Sstevel@tonic-gate  */
6207c478bd9Sstevel@tonic-gate 
6217c478bd9Sstevel@tonic-gate static char *sevspace = (char *)NULL;
6227c478bd9Sstevel@tonic-gate 
6237c478bd9Sstevel@tonic-gate static void
6247c478bd9Sstevel@tonic-gate sevstrset(void)
6257c478bd9Sstevel@tonic-gate {
6267c478bd9Sstevel@tonic-gate 	struct sevstr  *plast;
6277c478bd9Sstevel@tonic-gate 	struct sevstr  *psev;
6287c478bd9Sstevel@tonic-gate 	char		*value;
6297c478bd9Sstevel@tonic-gate 
6307c478bd9Sstevel@tonic-gate 
6317c478bd9Sstevel@tonic-gate 	/* Look for SEV_LEVEL definition */
6327c478bd9Sstevel@tonic-gate 	if ((value = getenv(SEV_LEVEL)) != (char *)NULL) {
6337c478bd9Sstevel@tonic-gate 
6347c478bd9Sstevel@tonic-gate 		/* Allocate space and make a copy of the value of SEV_LEVEL */
6357c478bd9Sstevel@tonic-gate 		if ((sevspace = libc_malloc(strlen(value) + 1)) != NULL) {
6367c478bd9Sstevel@tonic-gate 			(void) strcpy(sevspace, value);
6377c478bd9Sstevel@tonic-gate 
6387c478bd9Sstevel@tonic-gate 			/* Continue for all severity descriptions */
6397c478bd9Sstevel@tonic-gate 			psev = getauxsevs(sevspace);
6407c478bd9Sstevel@tonic-gate 			plast = (struct sevstr *)NULL;
6417c478bd9Sstevel@tonic-gate 			if (psev != (struct sevstr *)NULL) {
6427c478bd9Sstevel@tonic-gate 				penvsevs = psev;
6437c478bd9Sstevel@tonic-gate 				plast = psev;
6447c478bd9Sstevel@tonic-gate 				while (psev = getauxsevs((char *)NULL)) {
6457c478bd9Sstevel@tonic-gate 					plast->sevnext = psev;
6467c478bd9Sstevel@tonic-gate 					plast = psev;
6477c478bd9Sstevel@tonic-gate 				}
6487c478bd9Sstevel@tonic-gate 			}
6497c478bd9Sstevel@tonic-gate 		} /* if sevspace != (char *)NULL */
6507c478bd9Sstevel@tonic-gate 	} /* if value != (char *)NULL */
6517c478bd9Sstevel@tonic-gate }
6527c478bd9Sstevel@tonic-gate 
6537c478bd9Sstevel@tonic-gate /*
6547c478bd9Sstevel@tonic-gate  * int addseverity(value, string)
6557c478bd9Sstevel@tonic-gate  *	int	value		Value of the severity
6567c478bd9Sstevel@tonic-gate  *	const char   *string	Print-string for the severity
6577c478bd9Sstevel@tonic-gate  *
6587c478bd9Sstevel@tonic-gate  *  Arguments:
6597c478bd9Sstevel@tonic-gate  *	value		int
6607c478bd9Sstevel@tonic-gate  *			The integer value of the severity being added
6617c478bd9Sstevel@tonic-gate  *	string		char *
6627c478bd9Sstevel@tonic-gate  *			A pointer to the character-string to be printed
6637c478bd9Sstevel@tonic-gate  *			whenever a severity of "value" is printed
6647c478bd9Sstevel@tonic-gate  *
6657c478bd9Sstevel@tonic-gate  *  Returns:  int
6667c478bd9Sstevel@tonic-gate  *	Zero if successful, -1 if failed. The function can fail under
6677c478bd9Sstevel@tonic-gate  *	the following circumstances:
6687c478bd9Sstevel@tonic-gate  *	  - libc_malloc() fails
6697c478bd9Sstevel@tonic-gate  *	  - The "value" is one of the reserved values.
6707c478bd9Sstevel@tonic-gate  *
6717c478bd9Sstevel@tonic-gate  *	This function permits C applications to define severity-levels
6727c478bd9Sstevel@tonic-gate  *	that augment the standard levels and those defined by the
6737c478bd9Sstevel@tonic-gate  *	SEV_LEVEL environment variable.
6747c478bd9Sstevel@tonic-gate  */
6757c478bd9Sstevel@tonic-gate 
6767c478bd9Sstevel@tonic-gate int
6777c478bd9Sstevel@tonic-gate addseverity(int value, const char *string)
6787c478bd9Sstevel@tonic-gate {
6797c478bd9Sstevel@tonic-gate 	struct sevstr  *p;		/* Temp ptr to severity structs */
6807c478bd9Sstevel@tonic-gate 	struct sevstr  *q;		/* Temp ptr(follower) to severity */
6817c478bd9Sstevel@tonic-gate 	int		found;		/* FLAG, element found in the list */
6827c478bd9Sstevel@tonic-gate 	int		rtnval;		/* Value to return to the caller */
6837c478bd9Sstevel@tonic-gate 
6847c478bd9Sstevel@tonic-gate 	/* Make sure we're not trying to redefine one of the reserved values */
6857c478bd9Sstevel@tonic-gate 	if (value <= 4) {
6867c478bd9Sstevel@tonic-gate 		errno = EINVAL;
6877c478bd9Sstevel@tonic-gate 		return (-1);
6887c478bd9Sstevel@tonic-gate 	}
6897c478bd9Sstevel@tonic-gate 
6907c478bd9Sstevel@tonic-gate 	lmutex_lock(&fmt_lock);
6917c478bd9Sstevel@tonic-gate 
6927c478bd9Sstevel@tonic-gate 	/* Make sure we've interpreted SEV_LEVEL */
6937c478bd9Sstevel@tonic-gate 
6947c478bd9Sstevel@tonic-gate 	if (sevlook) {
6957c478bd9Sstevel@tonic-gate 		sevstrset();
6967c478bd9Sstevel@tonic-gate 		sevlook = FALSE;
6977c478bd9Sstevel@tonic-gate 	}
6987c478bd9Sstevel@tonic-gate 
6997c478bd9Sstevel@tonic-gate 
7007c478bd9Sstevel@tonic-gate 	/*
7017c478bd9Sstevel@tonic-gate 	 * Leaf through the list.  We may be redefining or removing a
7027c478bd9Sstevel@tonic-gate 	 * definition
7037c478bd9Sstevel@tonic-gate 	 */
7047c478bd9Sstevel@tonic-gate 	q = (struct sevstr *)NULL;
7057c478bd9Sstevel@tonic-gate 	found = FALSE;
7067c478bd9Sstevel@tonic-gate 	for (p = paugsevs; !found && (p != (struct sevstr *)NULL);
7077c478bd9Sstevel@tonic-gate 	    p = p->sevnext) {
7087c478bd9Sstevel@tonic-gate 		if (p->sevvalue == value) {
7097c478bd9Sstevel@tonic-gate 			/* We've a match.  Remove or modify the entry */
7107c478bd9Sstevel@tonic-gate 			if (string == (char *)NULL) {
7117c478bd9Sstevel@tonic-gate 				if (q == (struct sevstr *)NULL) {
7127c478bd9Sstevel@tonic-gate 					paugsevs = p->sevnext;
7137c478bd9Sstevel@tonic-gate 				} else {
7147c478bd9Sstevel@tonic-gate 					q->sevnext = p->sevnext;
7157c478bd9Sstevel@tonic-gate 				}
7167c478bd9Sstevel@tonic-gate 				libc_free(p);
7177c478bd9Sstevel@tonic-gate 			} else {
7187c478bd9Sstevel@tonic-gate 				p->sevprstr = string;
7197c478bd9Sstevel@tonic-gate 			}
7207c478bd9Sstevel@tonic-gate 			found = TRUE;
7217c478bd9Sstevel@tonic-gate 		}
7227c478bd9Sstevel@tonic-gate 		q = p;
7237c478bd9Sstevel@tonic-gate 	}
7247c478bd9Sstevel@tonic-gate 
7257c478bd9Sstevel@tonic-gate 	/* Adding a definition */
7267c478bd9Sstevel@tonic-gate 	if (!found && (string != (char *)NULL)) {
7277c478bd9Sstevel@tonic-gate 		/* Allocate space for the severity structure */
7287c478bd9Sstevel@tonic-gate 		if ((p = libc_malloc(sizeof (struct sevstr))) == NULL) {
7297c478bd9Sstevel@tonic-gate 			lmutex_unlock(&fmt_lock);
7307c478bd9Sstevel@tonic-gate 			return (-1);
7317c478bd9Sstevel@tonic-gate 		}
7327c478bd9Sstevel@tonic-gate 
7337c478bd9Sstevel@tonic-gate 		/*
7347c478bd9Sstevel@tonic-gate 		 * Fill in the new structure with the data supplied and add to
7357c478bd9Sstevel@tonic-gate 		 * the head of the augmented severity list.
7367c478bd9Sstevel@tonic-gate 		 */
7377c478bd9Sstevel@tonic-gate 
7387c478bd9Sstevel@tonic-gate 		p->sevkywd = (char *)NULL;
7397c478bd9Sstevel@tonic-gate 		p->sevprstr = string;
7407c478bd9Sstevel@tonic-gate 		p->sevvalue = value;
7417c478bd9Sstevel@tonic-gate 		p->sevnext = paugsevs;
7427c478bd9Sstevel@tonic-gate 		paugsevs = p;
7437c478bd9Sstevel@tonic-gate 
7447c478bd9Sstevel@tonic-gate 		/* Successfully added a new severity */
7457c478bd9Sstevel@tonic-gate 		rtnval = 0;
7467c478bd9Sstevel@tonic-gate 	} else if (string == (char *)NULL) {
7477c478bd9Sstevel@tonic-gate 		/* Attempting to undefined a non-defined severity */
7487c478bd9Sstevel@tonic-gate 		rtnval = -1;
7497c478bd9Sstevel@tonic-gate 		errno = EINVAL;
7507c478bd9Sstevel@tonic-gate 	} else {
7517c478bd9Sstevel@tonic-gate 		/* Successfully redefined a severity */
7527c478bd9Sstevel@tonic-gate 		rtnval = 0;
7537c478bd9Sstevel@tonic-gate 	}
7547c478bd9Sstevel@tonic-gate 	/* Finished, successful */
7557c478bd9Sstevel@tonic-gate 	lmutex_unlock(&fmt_lock);
7567c478bd9Sstevel@tonic-gate 	return (rtnval);
7577c478bd9Sstevel@tonic-gate }
7587c478bd9Sstevel@tonic-gate 
7597c478bd9Sstevel@tonic-gate /*
7607c478bd9Sstevel@tonic-gate  * Utility function for converting an integer to a string, avoiding stdio.
7617c478bd9Sstevel@tonic-gate  */
7627c478bd9Sstevel@tonic-gate static void
7637c478bd9Sstevel@tonic-gate itoa(int n, char *s)
7647c478bd9Sstevel@tonic-gate {
7657c478bd9Sstevel@tonic-gate 	char buf[12];		/* 32 bits fits in 10 decimal digits */
7667c478bd9Sstevel@tonic-gate 	char *cp = buf;
7677c478bd9Sstevel@tonic-gate 	uint_t un = (n < 0)? -n : n;
7687c478bd9Sstevel@tonic-gate 
7697c478bd9Sstevel@tonic-gate 	do {
7707c478bd9Sstevel@tonic-gate 		*cp++ = "0123456789"[un % 10];
7717c478bd9Sstevel@tonic-gate 		un /= 10;
7727c478bd9Sstevel@tonic-gate 	} while (un);
7737c478bd9Sstevel@tonic-gate 
7747c478bd9Sstevel@tonic-gate 	if (n < 0)
7757c478bd9Sstevel@tonic-gate 		*s++ = '-';
7767c478bd9Sstevel@tonic-gate 
7777c478bd9Sstevel@tonic-gate 	do {
7787c478bd9Sstevel@tonic-gate 		*s++ = *--cp;
7797c478bd9Sstevel@tonic-gate 	} while (cp > buf);
7807c478bd9Sstevel@tonic-gate 
7817c478bd9Sstevel@tonic-gate 	*s = '\0';
7827c478bd9Sstevel@tonic-gate }
7837c478bd9Sstevel@tonic-gate 
7847c478bd9Sstevel@tonic-gate /*
7857c478bd9Sstevel@tonic-gate  * void writemsg(buf, size, verbosity, label, severity, text, action, tag)
7867c478bd9Sstevel@tonic-gate  *
7877c478bd9Sstevel@tonic-gate  * Arguments:
7887c478bd9Sstevel@tonic-gate  *	char	*buf		The buffer in which to format the message
7897c478bd9Sstevel@tonic-gate  *	size_t	size		The size of the buffer
7907c478bd9Sstevel@tonic-gate  * 	int	verbosity	A bit-string that indicates which components
7917c478bd9Sstevel@tonic-gate  *				are to be written
7927c478bd9Sstevel@tonic-gate  * 	const char   *label	The address of the label-component
7937c478bd9Sstevel@tonic-gate  * 	int	severity	The severity value of the message
7947c478bd9Sstevel@tonic-gate  * 	const char   *text	The address of the text-component
7957c478bd9Sstevel@tonic-gate  * 	const char   *action	The address of the action-component
7967c478bd9Sstevel@tonic-gate  * 	const char   *tag	The address of the tag-component
7977c478bd9Sstevel@tonic-gate  *
7987c478bd9Sstevel@tonic-gate  *	This function formats the message consisting of the label-component,
7997c478bd9Sstevel@tonic-gate  *	severity-component, text-component, action-component, and tag-
8007c478bd9Sstevel@tonic-gate  *	component into the provided buffer.  The "verbosity" argument
8017c478bd9Sstevel@tonic-gate  *	tells which components can be selected.  Any or all of the
8027c478bd9Sstevel@tonic-gate  *	components can be their null-values.
8037c478bd9Sstevel@tonic-gate  *
8047c478bd9Sstevel@tonic-gate  * Returns:  void
8057c478bd9Sstevel@tonic-gate  *
8067c478bd9Sstevel@tonic-gate  * Notes:
8077c478bd9Sstevel@tonic-gate  */
8087c478bd9Sstevel@tonic-gate 
8097c478bd9Sstevel@tonic-gate static void
8107c478bd9Sstevel@tonic-gate writemsg(char *buf, size_t size,
8117c478bd9Sstevel@tonic-gate 	int verbosity, const char *label, int severity,
8127c478bd9Sstevel@tonic-gate 	const char *text, const char *action, const char *tag)
8137c478bd9Sstevel@tonic-gate {
8147c478bd9Sstevel@tonic-gate 	struct sevstr  *psev;		/* Ptr for severity str list */
8157c478bd9Sstevel@tonic-gate 	char		*p;		/* General purpose pointer */
8167c478bd9Sstevel@tonic-gate 	char		*sevpstr = NULL;  /* Pointer to severity string */
8177c478bd9Sstevel@tonic-gate 	int		l1indent;	/* # chars to indent line 1 */
8187c478bd9Sstevel@tonic-gate 	int		l2indent;	/* # chars to indent line 2 */
8197c478bd9Sstevel@tonic-gate 	int		textindent;	/* # spaces to indent text */
8207c478bd9Sstevel@tonic-gate 	int		actindent = 0;	/* # spaces to indent action */
8217c478bd9Sstevel@tonic-gate 	int		i;		/* General purpose counter */
8227c478bd9Sstevel@tonic-gate 	int		dolabel;	/* TRUE if label to be written */
8237c478bd9Sstevel@tonic-gate 	int		dotext;		/* TRUE if text to be written */
8247c478bd9Sstevel@tonic-gate 	int		dosev;		/* TRUE if severity to be written */
8257c478bd9Sstevel@tonic-gate 	int		doaction;	/* TRUE if action to be written */
8267c478bd9Sstevel@tonic-gate 	int		dotag;		/* TRUE if tag to be written */
8277c478bd9Sstevel@tonic-gate 	char		c;		/* Temp, multiuse character */
8287c478bd9Sstevel@tonic-gate 	char		sevpstrbuf[15];	/* Space for SV=%d */
8297c478bd9Sstevel@tonic-gate 
8307c478bd9Sstevel@tonic-gate 	char		lcllbl[MM_MXLABELLN+1];	/* Space for (possibly */
8317c478bd9Sstevel@tonic-gate 						/* truncated) label */
8327c478bd9Sstevel@tonic-gate 	char		lcltag[MM_MXTAGLN+1];	/* Space for (possibly */
8337c478bd9Sstevel@tonic-gate 						/* truncated) tag */
8347c478bd9Sstevel@tonic-gate 	char		*ebuf = buf + size - 2;
8357c478bd9Sstevel@tonic-gate 
8367c478bd9Sstevel@tonic-gate 	/*
8377c478bd9Sstevel@tonic-gate 	 * initialize variables.
8387c478bd9Sstevel@tonic-gate 	 */
8397c478bd9Sstevel@tonic-gate 	sevpstrbuf[0] = (char)0;
8407c478bd9Sstevel@tonic-gate 	lcllbl[0] = (char)0;
8417c478bd9Sstevel@tonic-gate 	lcltag[0] = (char)0;
8427c478bd9Sstevel@tonic-gate 
8437c478bd9Sstevel@tonic-gate 	/*
8447c478bd9Sstevel@tonic-gate 	 * Figure out what fields are to be written (all are optional)
8457c478bd9Sstevel@tonic-gate 	 */
8467c478bd9Sstevel@tonic-gate 
8477c478bd9Sstevel@tonic-gate 	dolabel  = (verbosity & MV_LBL) && (label != MM_NULLLBL);
8487c478bd9Sstevel@tonic-gate 	dosev    = (verbosity & MV_SEV) && (severity != MM_NULLSEV);
8497c478bd9Sstevel@tonic-gate 	dotext   = (verbosity & MV_TXT) && (text != MM_NULLTXT);
8507c478bd9Sstevel@tonic-gate 	doaction = (verbosity & MV_ACT) && (action != MM_NULLACT);
8517c478bd9Sstevel@tonic-gate 	dotag    = (verbosity & MV_TAG) && (tag != MM_NULLTAG);
8527c478bd9Sstevel@tonic-gate 
8537c478bd9Sstevel@tonic-gate 	/*
8547c478bd9Sstevel@tonic-gate 	 * Figure out how much we'll need to indent the text of the message
8557c478bd9Sstevel@tonic-gate 	 */
8567c478bd9Sstevel@tonic-gate 
8577c478bd9Sstevel@tonic-gate 	/* Count the label of the message, if requested */
8587c478bd9Sstevel@tonic-gate 	textindent = 0;
8597c478bd9Sstevel@tonic-gate 	if (dolabel) {
8607c478bd9Sstevel@tonic-gate 		(void) strncpy(lcllbl, label, (size_t)MM_MXLABELLN);
8617c478bd9Sstevel@tonic-gate 		lcllbl[MM_MXLABELLN] = '\0';
8627c478bd9Sstevel@tonic-gate 		textindent = (int)strlen(lcllbl) + SEPSTRLN;
8637c478bd9Sstevel@tonic-gate 	}
8647c478bd9Sstevel@tonic-gate 
8657c478bd9Sstevel@tonic-gate 	/*
8667c478bd9Sstevel@tonic-gate 	 * If severity req'd, determine the severity string and factor
8677c478bd9Sstevel@tonic-gate 	 * into indent count.  Severity string generated by:
8687c478bd9Sstevel@tonic-gate 	 *	1.  Search the standard list of severities.
8697c478bd9Sstevel@tonic-gate 	 *	2.  Search the severities added by the application.
8707c478bd9Sstevel@tonic-gate 	 *	3.  Search the severities added by the environment.
8717c478bd9Sstevel@tonic-gate 	 *	4.  Use the default (SV=n where n is the value of the severity).
8727c478bd9Sstevel@tonic-gate 	 */
8737c478bd9Sstevel@tonic-gate 
8747c478bd9Sstevel@tonic-gate 	if (dosev) {
8757c478bd9Sstevel@tonic-gate 		/* Search the default severity definitions */
8767c478bd9Sstevel@tonic-gate 		psev = pstdsevs;
8777c478bd9Sstevel@tonic-gate 		while (psev != (struct sevstr *)NULL) {
8787c478bd9Sstevel@tonic-gate 			if (psev->sevvalue == severity)
8797c478bd9Sstevel@tonic-gate 				break;
8807c478bd9Sstevel@tonic-gate 			psev = psev->sevnext;
8817c478bd9Sstevel@tonic-gate 		}
8827c478bd9Sstevel@tonic-gate 
8837c478bd9Sstevel@tonic-gate 		if (psev == (struct sevstr *)NULL) {
8847c478bd9Sstevel@tonic-gate 			/*
8857c478bd9Sstevel@tonic-gate 			 * Search the severity definitions
8867c478bd9Sstevel@tonic-gate 			 * added by the application
8877c478bd9Sstevel@tonic-gate 			 */
8887c478bd9Sstevel@tonic-gate 			psev = paugsevs;
8897c478bd9Sstevel@tonic-gate 			while (psev != (struct sevstr *)NULL) {
8907c478bd9Sstevel@tonic-gate 				if (psev->sevvalue == severity)
8917c478bd9Sstevel@tonic-gate 					break;
8927c478bd9Sstevel@tonic-gate 				psev = psev->sevnext;
8937c478bd9Sstevel@tonic-gate 			}
8947c478bd9Sstevel@tonic-gate 			if (psev == (struct sevstr *)NULL) {
8957c478bd9Sstevel@tonic-gate 				/*
8967c478bd9Sstevel@tonic-gate 				 * Search the severity definitions
8977c478bd9Sstevel@tonic-gate 				 * added by the environment
8987c478bd9Sstevel@tonic-gate 				 */
8997c478bd9Sstevel@tonic-gate 				psev = penvsevs;
9007c478bd9Sstevel@tonic-gate 				while (psev != (struct sevstr *)NULL) {
9017c478bd9Sstevel@tonic-gate 					if (psev->sevvalue == severity)
9027c478bd9Sstevel@tonic-gate 						break;
9037c478bd9Sstevel@tonic-gate 					psev = psev->sevnext;
9047c478bd9Sstevel@tonic-gate 				}
9057c478bd9Sstevel@tonic-gate 				if (psev == (struct sevstr *)NULL) {
9067c478bd9Sstevel@tonic-gate 					/* Use default string, SV=severity */
9077c478bd9Sstevel@tonic-gate 					(void) strcpy(sevpstrbuf, "SV=");
9087c478bd9Sstevel@tonic-gate 					itoa(severity, &sevpstrbuf[3]);
9097c478bd9Sstevel@tonic-gate 					sevpstr = sevpstrbuf;
9107c478bd9Sstevel@tonic-gate 				} else {
9117c478bd9Sstevel@tonic-gate 					sevpstr = (char *)psev->sevprstr;
9127c478bd9Sstevel@tonic-gate 				}
9137c478bd9Sstevel@tonic-gate 			} else {
9147c478bd9Sstevel@tonic-gate 				sevpstr = (char *)psev->sevprstr;
9157c478bd9Sstevel@tonic-gate 			}
9167c478bd9Sstevel@tonic-gate 		} else {
9177c478bd9Sstevel@tonic-gate 			sevpstr = (char *)psev->sevprstr;
9187c478bd9Sstevel@tonic-gate 		}
9197c478bd9Sstevel@tonic-gate 		/* Factor into indent counts */
9207c478bd9Sstevel@tonic-gate 		textindent += (int)strlen(sevpstr) + SEPSTRLN;
9217c478bd9Sstevel@tonic-gate 	}
9227c478bd9Sstevel@tonic-gate 
9237c478bd9Sstevel@tonic-gate 	/*
9247c478bd9Sstevel@tonic-gate 	 * Figure out the indents.
9257c478bd9Sstevel@tonic-gate 	 */
9267c478bd9Sstevel@tonic-gate 
9277c478bd9Sstevel@tonic-gate 	if (doaction && dotext) {
9287c478bd9Sstevel@tonic-gate 		if (textindent > ACTINTROLN) {
9297c478bd9Sstevel@tonic-gate 			l1indent = 0;
9307c478bd9Sstevel@tonic-gate 			l2indent = textindent - ACTINTROLN;
9317c478bd9Sstevel@tonic-gate 			actindent = textindent;
9327c478bd9Sstevel@tonic-gate 		} else {
9337c478bd9Sstevel@tonic-gate 			l2indent = 0;
9347c478bd9Sstevel@tonic-gate 			actindent = ACTINTROLN;
9357c478bd9Sstevel@tonic-gate 			if (dosev || dolabel) {
9367c478bd9Sstevel@tonic-gate 				l1indent = ACTINTROLN - textindent;
9377c478bd9Sstevel@tonic-gate 				textindent = ACTINTROLN;
9387c478bd9Sstevel@tonic-gate 			} else {
9397c478bd9Sstevel@tonic-gate 				textindent = 0;
9407c478bd9Sstevel@tonic-gate 				l1indent = 0;
9417c478bd9Sstevel@tonic-gate 			}
9427c478bd9Sstevel@tonic-gate 		}
9437c478bd9Sstevel@tonic-gate 	} else {
9447c478bd9Sstevel@tonic-gate 		l1indent = 0;
9457c478bd9Sstevel@tonic-gate 		l2indent = 0;
9467c478bd9Sstevel@tonic-gate 		if (doaction) {
9477c478bd9Sstevel@tonic-gate 			actindent = textindent + ACTINTROLN;
9487c478bd9Sstevel@tonic-gate 		} else if (dotext) {
9497c478bd9Sstevel@tonic-gate 			actindent = 0;
9507c478bd9Sstevel@tonic-gate 		}
9517c478bd9Sstevel@tonic-gate 	}
9527c478bd9Sstevel@tonic-gate 
9537c478bd9Sstevel@tonic-gate 	/*
9547c478bd9Sstevel@tonic-gate 	 * Write the message.
9557c478bd9Sstevel@tonic-gate 	 */
9567c478bd9Sstevel@tonic-gate 
9577c478bd9Sstevel@tonic-gate 	/* Write the LABEL, if requested */
9587c478bd9Sstevel@tonic-gate 	if (dolabel) {
9597c478bd9Sstevel@tonic-gate 		/* Write spaces to align on the ':' char, if needed */
9607c478bd9Sstevel@tonic-gate 		while (--l1indent >= 0 && buf < ebuf)
9617c478bd9Sstevel@tonic-gate 			*buf++ = ' ';
9627c478bd9Sstevel@tonic-gate 
9637c478bd9Sstevel@tonic-gate 		/* Write the label */
9647c478bd9Sstevel@tonic-gate 		buf += strlcpy(buf, lcllbl, ebuf - buf);
9657c478bd9Sstevel@tonic-gate 
9667c478bd9Sstevel@tonic-gate 		/*
9677c478bd9Sstevel@tonic-gate 		 * Write the separator string
9687c478bd9Sstevel@tonic-gate 		 * (if another component is to follow)
9697c478bd9Sstevel@tonic-gate 		 */
9707c478bd9Sstevel@tonic-gate 		if (dosev || dotext || doaction || dotag)
9717c478bd9Sstevel@tonic-gate 			buf += strlcpy(buf, SEPSTR, ebuf - buf);
9727c478bd9Sstevel@tonic-gate 	}
9737c478bd9Sstevel@tonic-gate 
9747c478bd9Sstevel@tonic-gate 	/* Write the SEVERITY, if requested */
9757c478bd9Sstevel@tonic-gate 	if (dosev) {
9767c478bd9Sstevel@tonic-gate 		/* Write spaces to align on the ':' char, if needed */
9777c478bd9Sstevel@tonic-gate 		while (--l1indent >= 0 && buf < ebuf)
9787c478bd9Sstevel@tonic-gate 			*buf++ = ' ';
9797c478bd9Sstevel@tonic-gate 
9807c478bd9Sstevel@tonic-gate 		/* Write the severity print-string */
9817c478bd9Sstevel@tonic-gate 		buf += strlcpy(buf, sevpstr, ebuf - buf);
9827c478bd9Sstevel@tonic-gate 
9837c478bd9Sstevel@tonic-gate 		/*
9847c478bd9Sstevel@tonic-gate 		 * Write the separator string
9857c478bd9Sstevel@tonic-gate 		 * (if another component is to follow)
9867c478bd9Sstevel@tonic-gate 		 */
9877c478bd9Sstevel@tonic-gate 		if (dotext || doaction || dotag)
9887c478bd9Sstevel@tonic-gate 			buf += strlcpy(buf, SEPSTR, ebuf - buf);
9897c478bd9Sstevel@tonic-gate 	}
9907c478bd9Sstevel@tonic-gate 
9917c478bd9Sstevel@tonic-gate 	/* Write the TEXT, if requested */
9927c478bd9Sstevel@tonic-gate 	if (dotext) {
9937c478bd9Sstevel@tonic-gate 		p = (char *)text;
9947c478bd9Sstevel@tonic-gate 		for (c = *p++; c != NULL && buf < ebuf; c = *p++) {
9957c478bd9Sstevel@tonic-gate 			*buf++ = c;
9967c478bd9Sstevel@tonic-gate 			if (c == '\n') {
9977c478bd9Sstevel@tonic-gate 				for (i = 0; i < textindent && buf < ebuf; i++)
9987c478bd9Sstevel@tonic-gate 					*buf++ = ' ';
9997c478bd9Sstevel@tonic-gate 			}
10007c478bd9Sstevel@tonic-gate 		}
10017c478bd9Sstevel@tonic-gate 	}
10027c478bd9Sstevel@tonic-gate 
10037c478bd9Sstevel@tonic-gate 	/*
10047c478bd9Sstevel@tonic-gate 	 * Write ACTION if requested.
10057c478bd9Sstevel@tonic-gate 	 */
10067c478bd9Sstevel@tonic-gate 
10077c478bd9Sstevel@tonic-gate 	if (doaction) {
10087c478bd9Sstevel@tonic-gate 		if (dotext && buf < ebuf) {
10097c478bd9Sstevel@tonic-gate 			*buf++ = '\n';
10107c478bd9Sstevel@tonic-gate 			while (--l2indent >= 0 && buf < ebuf)
10117c478bd9Sstevel@tonic-gate 				*buf++ = ' ';
10127c478bd9Sstevel@tonic-gate 		}
10137c478bd9Sstevel@tonic-gate 
10147c478bd9Sstevel@tonic-gate 		/* Write the action-string's introduction */
10157c478bd9Sstevel@tonic-gate 		buf += strlcpy(buf, ACTINTRO, ebuf - buf);
10167c478bd9Sstevel@tonic-gate 
10177c478bd9Sstevel@tonic-gate 		/* Write the "action" string */
10187c478bd9Sstevel@tonic-gate 		p = (char *)action;
10197c478bd9Sstevel@tonic-gate 		for (c = *p++; c != NULL && buf < ebuf; c = *p++) {
10207c478bd9Sstevel@tonic-gate 			*buf++ = c;
10217c478bd9Sstevel@tonic-gate 			if (c == '\n') {
10227c478bd9Sstevel@tonic-gate 				for (i = 0; i < actindent && buf < ebuf; i++)
10237c478bd9Sstevel@tonic-gate 					*buf++ = ' ';
10247c478bd9Sstevel@tonic-gate 			}
10257c478bd9Sstevel@tonic-gate 		}
10267c478bd9Sstevel@tonic-gate 	}
10277c478bd9Sstevel@tonic-gate 
10287c478bd9Sstevel@tonic-gate 	/*
10297c478bd9Sstevel@tonic-gate 	 * Write the TAG if requested
10307c478bd9Sstevel@tonic-gate 	 */
10317c478bd9Sstevel@tonic-gate 
10327c478bd9Sstevel@tonic-gate 	if (dotag) {
10337c478bd9Sstevel@tonic-gate 		if (doaction)
10347c478bd9Sstevel@tonic-gate 			buf += strlcpy(buf, "  ", ebuf - buf);
10357c478bd9Sstevel@tonic-gate 		else if (dotext && buf < ebuf)
10367c478bd9Sstevel@tonic-gate 			*buf++ = '\n';
10377c478bd9Sstevel@tonic-gate 		(void) strncpy(lcltag, tag, (size_t)MM_MXTAGLN);
10387c478bd9Sstevel@tonic-gate 		lcltag[MM_MXTAGLN] = '\0';
10397c478bd9Sstevel@tonic-gate 		buf += strlcpy(buf, lcltag, ebuf - buf);
10407c478bd9Sstevel@tonic-gate 	}
10417c478bd9Sstevel@tonic-gate 
10427c478bd9Sstevel@tonic-gate 	/*
10437c478bd9Sstevel@tonic-gate 	 * Write terminating newline and null byte.
10447c478bd9Sstevel@tonic-gate 	 * We reserved space for these at the start.
10457c478bd9Sstevel@tonic-gate 	 */
10467c478bd9Sstevel@tonic-gate 	*buf++ = '\n';
10477c478bd9Sstevel@tonic-gate 	*buf++ = '\0';
10487c478bd9Sstevel@tonic-gate }
10497c478bd9Sstevel@tonic-gate 
10507c478bd9Sstevel@tonic-gate /*
10517c478bd9Sstevel@tonic-gate  * int	fmtmsg(class, label, severity, text, action, tag)
10527c478bd9Sstevel@tonic-gate  *	long	class
10537c478bd9Sstevel@tonic-gate  *	const char   *label
10547c478bd9Sstevel@tonic-gate  *	int	severity
10557c478bd9Sstevel@tonic-gate  *	const char   *text
10567c478bd9Sstevel@tonic-gate  *	const char   *action
10577c478bd9Sstevel@tonic-gate  *	const char   *tag
10587c478bd9Sstevel@tonic-gate  *
10597c478bd9Sstevel@tonic-gate  *	If requested, the fmtmsg() function writes a message to the standard
10607c478bd9Sstevel@tonic-gate  *      error stream in the standard message format.  Also if requested, it
10617c478bd9Sstevel@tonic-gate  *	will write a message to the system console.
10627c478bd9Sstevel@tonic-gate  *
10637c478bd9Sstevel@tonic-gate  *	Arguments:
10647c478bd9Sstevel@tonic-gate  *	    class	Fields which classify the message for the system
10657c478bd9Sstevel@tonic-gate  *			logging facility
10667c478bd9Sstevel@tonic-gate  *	    label	A character-string that is printed as the "label"
10677c478bd9Sstevel@tonic-gate  *			of the message.  Typically identifies the source
10687c478bd9Sstevel@tonic-gate  *			of the message
10697c478bd9Sstevel@tonic-gate  *	    severity	Identifies the severity of the message.  Either one
10707c478bd9Sstevel@tonic-gate  *			of the standard severities, or possibly one of the
10717c478bd9Sstevel@tonic-gate  *			augmented severities
10727c478bd9Sstevel@tonic-gate  *	    text	Pointer to the text of the message
10737c478bd9Sstevel@tonic-gate  *	    action	Pointer to a char string that describes some type
10747c478bd9Sstevel@tonic-gate  *			of corrective action.
10757c478bd9Sstevel@tonic-gate  *	    tag		A character-string that is printed as the "tag" or
10767c478bd9Sstevel@tonic-gate  *			the message.  Typically a pointer to documentation
10777c478bd9Sstevel@tonic-gate  *
10787c478bd9Sstevel@tonic-gate  *	Returns:
10797c478bd9Sstevel@tonic-gate  *	    -1 if nothing was generated, 0 if everything requested was
10807c478bd9Sstevel@tonic-gate  *	    generated, or flags if partially generated.
10817c478bd9Sstevel@tonic-gate  *
10827c478bd9Sstevel@tonic-gate  *	Needs:
10837c478bd9Sstevel@tonic-gate  *	  - Nothing special for 4.0.
10847c478bd9Sstevel@tonic-gate  */
10857c478bd9Sstevel@tonic-gate 
10867c478bd9Sstevel@tonic-gate int
10877c478bd9Sstevel@tonic-gate fmtmsg(long class, const char *label, int severity,
10887c478bd9Sstevel@tonic-gate const char *text, const char *action, const char *tag)
10897c478bd9Sstevel@tonic-gate {
10907c478bd9Sstevel@tonic-gate 	int	rtnval;		/* Value to return */
10917c478bd9Sstevel@tonic-gate 	FILE	*console;	/* Ptr to "console" stream */
10927c478bd9Sstevel@tonic-gate 	char	*message1;
10937c478bd9Sstevel@tonic-gate 	char	*message2;
10947c478bd9Sstevel@tonic-gate 
10957c478bd9Sstevel@tonic-gate 	/*
10967c478bd9Sstevel@tonic-gate 	 * Determine the "verbosity" of the message.  If "msgverb" is
10977c478bd9Sstevel@tonic-gate 	 * already set, don't interrogate the "MSGVERB" environment vbl.
10987c478bd9Sstevel@tonic-gate 	 * If so, interrogate "MSGVERB" and do initialization stuff also.
10997c478bd9Sstevel@tonic-gate 	 */
11007c478bd9Sstevel@tonic-gate 
11017c478bd9Sstevel@tonic-gate 	lmutex_lock(&fmt_lock);
11027c478bd9Sstevel@tonic-gate 
11037c478bd9Sstevel@tonic-gate 	if (!(msgverb & MV_SET)) {
11047c478bd9Sstevel@tonic-gate 		msgverbset();
11057c478bd9Sstevel@tonic-gate 		msgverb |= MV_SET;
11067c478bd9Sstevel@tonic-gate 	}
11077c478bd9Sstevel@tonic-gate 
11087c478bd9Sstevel@tonic-gate 
11097c478bd9Sstevel@tonic-gate 	/*
11107c478bd9Sstevel@tonic-gate 	 * Extract the severity definitions from the SEV_LEVEL
11117c478bd9Sstevel@tonic-gate 	 * environment variable and save away for later.
11127c478bd9Sstevel@tonic-gate 	 */
11137c478bd9Sstevel@tonic-gate 
11147c478bd9Sstevel@tonic-gate 	if (sevlook) {
11157c478bd9Sstevel@tonic-gate 		sevstrset();
11167c478bd9Sstevel@tonic-gate 		sevlook = FALSE;
11177c478bd9Sstevel@tonic-gate 	}
11187c478bd9Sstevel@tonic-gate 
11197c478bd9Sstevel@tonic-gate 
11207c478bd9Sstevel@tonic-gate 	/* Set up the default text component [if text==(char *)NULL] */
11217c478bd9Sstevel@tonic-gate 	if (text == (char *)NULL)
11227c478bd9Sstevel@tonic-gate 		text = DEFLT_TEXT;
11237c478bd9Sstevel@tonic-gate 
11247c478bd9Sstevel@tonic-gate 	/* Prepare the message for stderr if requested */
11257c478bd9Sstevel@tonic-gate 	if (class & MM_PRINT) {
11267c478bd9Sstevel@tonic-gate 		message1 = alloca(MAX_MSG_SIZE);
11277c478bd9Sstevel@tonic-gate 		writemsg(message1, MAX_MSG_SIZE,
11287c478bd9Sstevel@tonic-gate 		    msgverb, label, severity, text, action, tag);
11297c478bd9Sstevel@tonic-gate 	}
11307c478bd9Sstevel@tonic-gate 
11317c478bd9Sstevel@tonic-gate 	/* Prepare the message for the console if requested */
11327c478bd9Sstevel@tonic-gate 	if (class & MM_CONSOLE) {
11337c478bd9Sstevel@tonic-gate 		message2 = alloca(MAX_MSG_SIZE);
11347c478bd9Sstevel@tonic-gate 		writemsg(message2, MAX_MSG_SIZE,
11357c478bd9Sstevel@tonic-gate 		    MV_ALL, label, severity, text, action, tag);
11367c478bd9Sstevel@tonic-gate 	}
11377c478bd9Sstevel@tonic-gate 
11387c478bd9Sstevel@tonic-gate 	lmutex_unlock(&fmt_lock);
11397c478bd9Sstevel@tonic-gate 
11407c478bd9Sstevel@tonic-gate 	rtnval = MM_OK;
11417c478bd9Sstevel@tonic-gate 
11427c478bd9Sstevel@tonic-gate 	/* Write the message to stderr if requested */
11437c478bd9Sstevel@tonic-gate 	if (class & MM_PRINT) {
11447c478bd9Sstevel@tonic-gate 		clearerr(stderr);
11457c478bd9Sstevel@tonic-gate 		(void) fputs(message1, stderr);
11467c478bd9Sstevel@tonic-gate 		if (ferror(stderr))
11477c478bd9Sstevel@tonic-gate 			rtnval |= MM_NOMSG;
11487c478bd9Sstevel@tonic-gate 	}
11497c478bd9Sstevel@tonic-gate 
11507c478bd9Sstevel@tonic-gate 	/* Write the message to the console if requested */
11517c478bd9Sstevel@tonic-gate 	if (class & MM_CONSOLE) {
1152*004388ebScasper 		if ((console = fopen(CONNAME, "wF")) != NULL) {
11537c478bd9Sstevel@tonic-gate 			clearerr(console);
11547c478bd9Sstevel@tonic-gate 			(void) fputs(message2, console);
11557c478bd9Sstevel@tonic-gate 			if (ferror(console))
11567c478bd9Sstevel@tonic-gate 				rtnval |= MM_NOCON;
11577c478bd9Sstevel@tonic-gate 			(void) fclose(console);
11587c478bd9Sstevel@tonic-gate 		} else {
11597c478bd9Sstevel@tonic-gate 			rtnval |= MM_NOCON;
11607c478bd9Sstevel@tonic-gate 		}
11617c478bd9Sstevel@tonic-gate 	}
11627c478bd9Sstevel@tonic-gate 
11637c478bd9Sstevel@tonic-gate 	if ((rtnval & (MM_NOCON | MM_NOMSG)) == (MM_NOCON | MM_NOMSG))
11647c478bd9Sstevel@tonic-gate 		rtnval = MM_NOTOK;
11657c478bd9Sstevel@tonic-gate 	return (rtnval);
11667c478bd9Sstevel@tonic-gate }
1167