xref: /titanic_53/usr/src/cmd/fmtmsg/main.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
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 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
23*7c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
24*7c478bd9Sstevel@tonic-gate 
25*7c478bd9Sstevel@tonic-gate 
26*7c478bd9Sstevel@tonic-gate /*
27*7c478bd9Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
28*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
29*7c478bd9Sstevel@tonic-gate  */
30*7c478bd9Sstevel@tonic-gate 
31*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
32*7c478bd9Sstevel@tonic-gate 
33*7c478bd9Sstevel@tonic-gate 
34*7c478bd9Sstevel@tonic-gate /*
35*7c478bd9Sstevel@tonic-gate  * fmtmsg.c
36*7c478bd9Sstevel@tonic-gate  *
37*7c478bd9Sstevel@tonic-gate  * Contains:
38*7c478bd9Sstevel@tonic-gate  *	fmtmsg		Command that writes a message in the standard
39*7c478bd9Sstevel@tonic-gate  *			message format.  May in future make these
40*7c478bd9Sstevel@tonic-gate  *			messages available for logging.
41*7c478bd9Sstevel@tonic-gate  */
42*7c478bd9Sstevel@tonic-gate 
43*7c478bd9Sstevel@tonic-gate 
44*7c478bd9Sstevel@tonic-gate /*
45*7c478bd9Sstevel@tonic-gate  * Header files used:
46*7c478bd9Sstevel@tonic-gate  *	<stdio.h>	C Standard I/O function definitions
47*7c478bd9Sstevel@tonic-gate  *	<string.h>	C string-handling definitions
48*7c478bd9Sstevel@tonic-gate  *	<errno.h>	UNIX error-code "errno" definitions
49*7c478bd9Sstevel@tonic-gate  *	<fmtmsg.h>	Standard Message definitions
50*7c478bd9Sstevel@tonic-gate  */
51*7c478bd9Sstevel@tonic-gate 
52*7c478bd9Sstevel@tonic-gate #include	<stdio.h>
53*7c478bd9Sstevel@tonic-gate #include	<string.h>
54*7c478bd9Sstevel@tonic-gate #include	<errno.h>
55*7c478bd9Sstevel@tonic-gate #include	<fmtmsg.h>
56*7c478bd9Sstevel@tonic-gate 
57*7c478bd9Sstevel@tonic-gate 
58*7c478bd9Sstevel@tonic-gate /*
59*7c478bd9Sstevel@tonic-gate  * Externals referenced:
60*7c478bd9Sstevel@tonic-gate  *	strtol		Function that converts char strings to "long"
61*7c478bd9Sstevel@tonic-gate  *	fmtmsg		Function that writes a message in standard format
62*7c478bd9Sstevel@tonic-gate  *	getenv		Function that extracts an environment variable's
63*7c478bd9Sstevel@tonic-gate  *			value
64*7c478bd9Sstevel@tonic-gate  *	malloc		Allocate memory from the memory pool
65*7c478bd9Sstevel@tonic-gate  *	free		Frees allocated memory
66*7c478bd9Sstevel@tonic-gate  *	getopt		Function that extracts arguments from the command-
67*7c478bd9Sstevel@tonic-gate  *	optarg		Points to option's argument (from getopt())
68*7c478bd9Sstevel@tonic-gate  *	optind		Option's argument index (from getopt())
69*7c478bd9Sstevel@tonic-gate  *	opterr		FLAG, write error if invalid option (for getopt())
70*7c478bd9Sstevel@tonic-gate  *			line.
71*7c478bd9Sstevel@tonic-gate  *	exit		Exits the command
72*7c478bd9Sstevel@tonic-gate  */
73*7c478bd9Sstevel@tonic-gate 
74*7c478bd9Sstevel@tonic-gate extern	long		strtol();
75*7c478bd9Sstevel@tonic-gate extern	int		fmtmsg();
76*7c478bd9Sstevel@tonic-gate extern	char	       *getenv();
77*7c478bd9Sstevel@tonic-gate extern	void	       *malloc();
78*7c478bd9Sstevel@tonic-gate extern	void		free();
79*7c478bd9Sstevel@tonic-gate extern	int		getopt();
80*7c478bd9Sstevel@tonic-gate extern	char	       *optarg;
81*7c478bd9Sstevel@tonic-gate extern	int		optind;
82*7c478bd9Sstevel@tonic-gate extern	int		opterr;
83*7c478bd9Sstevel@tonic-gate extern	void		exit();
84*7c478bd9Sstevel@tonic-gate 
85*7c478bd9Sstevel@tonic-gate /*
86*7c478bd9Sstevel@tonic-gate  * Local definitions
87*7c478bd9Sstevel@tonic-gate  */
88*7c478bd9Sstevel@tonic-gate 
89*7c478bd9Sstevel@tonic-gate /*
90*7c478bd9Sstevel@tonic-gate  * Local constants
91*7c478bd9Sstevel@tonic-gate  */
92*7c478bd9Sstevel@tonic-gate 
93*7c478bd9Sstevel@tonic-gate 
94*7c478bd9Sstevel@tonic-gate /*
95*7c478bd9Sstevel@tonic-gate  * Boolean constants
96*7c478bd9Sstevel@tonic-gate  *	TRUE	Boolean value for "true" (any bits on)
97*7c478bd9Sstevel@tonic-gate  *	FALSE	Boolean value for "false" (all bits off)
98*7c478bd9Sstevel@tonic-gate  */
99*7c478bd9Sstevel@tonic-gate 
100*7c478bd9Sstevel@tonic-gate #ifndef	FALSE
101*7c478bd9Sstevel@tonic-gate #define	FALSE		(0)
102*7c478bd9Sstevel@tonic-gate #endif
103*7c478bd9Sstevel@tonic-gate 
104*7c478bd9Sstevel@tonic-gate #ifndef TRUE
105*7c478bd9Sstevel@tonic-gate #define	TRUE		(1)
106*7c478bd9Sstevel@tonic-gate #endif
107*7c478bd9Sstevel@tonic-gate 
108*7c478bd9Sstevel@tonic-gate 
109*7c478bd9Sstevel@tonic-gate #define	CLASS		(MM_PRINT|MM_SOFT|MM_NRECOV|MM_UTIL)
110*7c478bd9Sstevel@tonic-gate #define BIGUSAGE	"fmtmsg [-a action] [-c class] [-l label] [-s severity] [-t tag]\n       [-u subclass[,subclass[,...]]] [text]\n"
111*7c478bd9Sstevel@tonic-gate 
112*7c478bd9Sstevel@tonic-gate 
113*7c478bd9Sstevel@tonic-gate /*
114*7c478bd9Sstevel@tonic-gate  * Local data-type definitions
115*7c478bd9Sstevel@tonic-gate  */
116*7c478bd9Sstevel@tonic-gate 
117*7c478bd9Sstevel@tonic-gate /*
118*7c478bd9Sstevel@tonic-gate  * Structure used for tables containing keywords and integer values
119*7c478bd9Sstevel@tonic-gate  */
120*7c478bd9Sstevel@tonic-gate 
121*7c478bd9Sstevel@tonic-gate struct sev_info {
122*7c478bd9Sstevel@tonic-gate 	char   *keyword;
123*7c478bd9Sstevel@tonic-gate 	int	value;
124*7c478bd9Sstevel@tonic-gate };
125*7c478bd9Sstevel@tonic-gate 
126*7c478bd9Sstevel@tonic-gate 
127*7c478bd9Sstevel@tonic-gate /*
128*7c478bd9Sstevel@tonic-gate  * Structure used for tables containing keywords, long values
129*7c478bd9Sstevel@tonic-gate  */
130*7c478bd9Sstevel@tonic-gate 
131*7c478bd9Sstevel@tonic-gate struct class_info {
132*7c478bd9Sstevel@tonic-gate 	char   *keyword;
133*7c478bd9Sstevel@tonic-gate 	long	value;
134*7c478bd9Sstevel@tonic-gate 	long	conflict;
135*7c478bd9Sstevel@tonic-gate };
136*7c478bd9Sstevel@tonic-gate 
137*7c478bd9Sstevel@tonic-gate 
138*7c478bd9Sstevel@tonic-gate /*
139*7c478bd9Sstevel@tonic-gate  * Severity string structure
140*7c478bd9Sstevel@tonic-gate  *
141*7c478bd9Sstevel@tonic-gate  *	struct sevstr
142*7c478bd9Sstevel@tonic-gate  *		sevvalue	Value of the severity-level being defined
143*7c478bd9Sstevel@tonic-gate  *		sevkywd		Keyword identifying the severity
144*7c478bd9Sstevel@tonic-gate  *		sevprptr	Pointer to the string associated with the value
145*7c478bd9Sstevel@tonic-gate  *		sevnext		Pointer to the next value in the list.
146*7c478bd9Sstevel@tonic-gate  */
147*7c478bd9Sstevel@tonic-gate 
148*7c478bd9Sstevel@tonic-gate struct sevstr {
149*7c478bd9Sstevel@tonic-gate 	int		sevvalue;
150*7c478bd9Sstevel@tonic-gate 	char           *sevkywd;
151*7c478bd9Sstevel@tonic-gate 	char	       *sevprstr;
152*7c478bd9Sstevel@tonic-gate 	struct sevstr  *sevnext;
153*7c478bd9Sstevel@tonic-gate };
154*7c478bd9Sstevel@tonic-gate 
155*7c478bd9Sstevel@tonic-gate 
156*7c478bd9Sstevel@tonic-gate /*
157*7c478bd9Sstevel@tonic-gate  * Local static data
158*7c478bd9Sstevel@tonic-gate  */
159*7c478bd9Sstevel@tonic-gate 
160*7c478bd9Sstevel@tonic-gate 
161*7c478bd9Sstevel@tonic-gate /*
162*7c478bd9Sstevel@tonic-gate  * Table contains the keywords for the classes of a message
163*7c478bd9Sstevel@tonic-gate  */
164*7c478bd9Sstevel@tonic-gate 
165*7c478bd9Sstevel@tonic-gate static	struct class_info	classes[] = {
166*7c478bd9Sstevel@tonic-gate 
167*7c478bd9Sstevel@tonic-gate 	{"hard", 	MM_HARD,	MM_SOFT|MM_FIRM},	/* hardware */
168*7c478bd9Sstevel@tonic-gate 	{"soft", 	MM_SOFT,	MM_HARD|MM_FIRM},	/* software */
169*7c478bd9Sstevel@tonic-gate 	{"firm", 	MM_FIRM,	MM_SOFT|MM_FIRM},	/* firmware */
170*7c478bd9Sstevel@tonic-gate 
171*7c478bd9Sstevel@tonic-gate 	{(char *) NULL,	0L,		0L}			/* end of list */
172*7c478bd9Sstevel@tonic-gate 
173*7c478bd9Sstevel@tonic-gate };
174*7c478bd9Sstevel@tonic-gate 
175*7c478bd9Sstevel@tonic-gate 
176*7c478bd9Sstevel@tonic-gate /*
177*7c478bd9Sstevel@tonic-gate  * Table contains the keywords for the subclasses for a message
178*7c478bd9Sstevel@tonic-gate  */
179*7c478bd9Sstevel@tonic-gate 
180*7c478bd9Sstevel@tonic-gate static	struct class_info	subclasses[] = 	{
181*7c478bd9Sstevel@tonic-gate 
182*7c478bd9Sstevel@tonic-gate 	{"appl",     	MM_APPL,	MM_UTIL|MM_OPSYS},	/* Application */
183*7c478bd9Sstevel@tonic-gate 	{"util",     	MM_UTIL,	MM_APPL|MM_OPSYS},	/* Utility */
184*7c478bd9Sstevel@tonic-gate 	{"opsys",    	MM_OPSYS,	MM_APPL|MM_UTIL},	/* Operating System */
185*7c478bd9Sstevel@tonic-gate 
186*7c478bd9Sstevel@tonic-gate 	{"recov",    	MM_RECOVER,	MM_NRECOV},		/* Recoverable */
187*7c478bd9Sstevel@tonic-gate 	{"nrecov",   	MM_NRECOV,	MM_RECOVER},		/* Non-recoverable */
188*7c478bd9Sstevel@tonic-gate 
189*7c478bd9Sstevel@tonic-gate 	{"print",    	MM_PRINT,	0L}, 			/* Write message to stderr */
190*7c478bd9Sstevel@tonic-gate 	{"console",  	MM_CONSOLE,	0L},			/* Write message on /dev/console */
191*7c478bd9Sstevel@tonic-gate 	{(char *) NULL,	0L,		0L}			/* End of list */
192*7c478bd9Sstevel@tonic-gate 
193*7c478bd9Sstevel@tonic-gate };
194*7c478bd9Sstevel@tonic-gate 
195*7c478bd9Sstevel@tonic-gate 
196*7c478bd9Sstevel@tonic-gate /*
197*7c478bd9Sstevel@tonic-gate  * Table contains the keywords for the standard severities of a message.
198*7c478bd9Sstevel@tonic-gate  * User may supply more through the SEV_LEVEL environment variable.
199*7c478bd9Sstevel@tonic-gate  */
200*7c478bd9Sstevel@tonic-gate 
201*7c478bd9Sstevel@tonic-gate static  struct sev_info		severities[] =  {
202*7c478bd9Sstevel@tonic-gate 	{"halt",	MM_HALT},	/* halt */
203*7c478bd9Sstevel@tonic-gate 	{"error",	MM_ERROR},	/* error */
204*7c478bd9Sstevel@tonic-gate 	{"warn",	MM_WARNING},	/* warn */
205*7c478bd9Sstevel@tonic-gate 	{"info",	MM_INFO},	/* info */
206*7c478bd9Sstevel@tonic-gate 	{(char *) NULL,	0}		/* end of list */
207*7c478bd9Sstevel@tonic-gate };
208*7c478bd9Sstevel@tonic-gate 
209*7c478bd9Sstevel@tonic-gate 
210*7c478bd9Sstevel@tonic-gate /*
211*7c478bd9Sstevel@tonic-gate  * Buffers used by the command
212*7c478bd9Sstevel@tonic-gate  */
213*7c478bd9Sstevel@tonic-gate 
214*7c478bd9Sstevel@tonic-gate static	char	labelbuf[128];		/* Buf for message label */
215*7c478bd9Sstevel@tonic-gate static	char	msgbuf[256];		/* Buf for messages */
216*7c478bd9Sstevel@tonic-gate 
217*7c478bd9Sstevel@tonic-gate /*
218*7c478bd9Sstevel@tonic-gate  * static char *exttok(str, delims)
219*7c478bd9Sstevel@tonic-gate  *	char   *str
220*7c478bd9Sstevel@tonic-gate  *	char   *delims
221*7c478bd9Sstevel@tonic-gate  *
222*7c478bd9Sstevel@tonic-gate  *	This function examines the string pointed to by "str", looking
223*7c478bd9Sstevel@tonic-gate  *	for the first occurrence of any of the characters in the string
224*7c478bd9Sstevel@tonic-gate  *	whose address is "delims".  It returns the address of that
225*7c478bd9Sstevel@tonic-gate  *	character or (char *) NULL if there was nothing to search.
226*7c478bd9Sstevel@tonic-gate  *
227*7c478bd9Sstevel@tonic-gate  * Arguments:
228*7c478bd9Sstevel@tonic-gate  *	str	Address of the string to search
229*7c478bd9Sstevel@tonic-gate  *	delims	Address of the string containing delimiters
230*7c478bd9Sstevel@tonic-gate  *
231*7c478bd9Sstevel@tonic-gate  * Returns:  char *
232*7c478bd9Sstevel@tonic-gate  *	Returns the address of the first occurrence of any of the characters
233*7c478bd9Sstevel@tonic-gate  *	in "delim" in the string "str" (incl '\0').  If there was nothing
234*7c478bd9Sstevel@tonic-gate  *	to search, the function returns (char *) NULL.
235*7c478bd9Sstevel@tonic-gate  *
236*7c478bd9Sstevel@tonic-gate  * Notes:
237*7c478bd9Sstevel@tonic-gate  *    - This function is needed because strtok() can't be used inside a
238*7c478bd9Sstevel@tonic-gate  *	function.  Besides, strtok() is destructive in the string, which
239*7c478bd9Sstevel@tonic-gate  *	is undesirable in many circumstances.
240*7c478bd9Sstevel@tonic-gate  *    - This function understands escaped delimiters as non-delimiters.
241*7c478bd9Sstevel@tonic-gate  *	Delimiters are escaped by preceding them with '\' characters.
242*7c478bd9Sstevel@tonic-gate  *	The '\' character also must be escaped.
243*7c478bd9Sstevel@tonic-gate  */
244*7c478bd9Sstevel@tonic-gate 
245*7c478bd9Sstevel@tonic-gate static char *
246*7c478bd9Sstevel@tonic-gate exttok(tok, delims)
247*7c478bd9Sstevel@tonic-gate 	char   *tok;		/* Ptr to the token we're parsing */
248*7c478bd9Sstevel@tonic-gate 	char   *delims;		/* Ptr to string with delimiters */
249*7c478bd9Sstevel@tonic-gate {
250*7c478bd9Sstevel@tonic-gate 
251*7c478bd9Sstevel@tonic-gate 	/* Automatic Data */
252*7c478bd9Sstevel@tonic-gate 	char   *tokend;		/* Ptr to the end of the token */
253*7c478bd9Sstevel@tonic-gate 	char   *p, *q;	 	/* Temp pointers */
254*7c478bd9Sstevel@tonic-gate 
255*7c478bd9Sstevel@tonic-gate 
256*7c478bd9Sstevel@tonic-gate 	/* Algorithm:
257*7c478bd9Sstevel@tonic-gate 	 *    1.  Get the starting address (new string or where we
258*7c478bd9Sstevel@tonic-gate 	 *	  left off).  If nothing to search, return (char *) NULL
259*7c478bd9Sstevel@tonic-gate 	 *    2.  Find the end of the string
260*7c478bd9Sstevel@tonic-gate 	 *    3.  Look for the first unescaped delimiter closest to the
261*7c478bd9Sstevel@tonic-gate 	 *	  beginning of the string
262*7c478bd9Sstevel@tonic-gate 	 *    4.  Remember where we left off
263*7c478bd9Sstevel@tonic-gate 	 *    5.  Return a pointer to the delimiter we found
264*7c478bd9Sstevel@tonic-gate 	 */
265*7c478bd9Sstevel@tonic-gate 
266*7c478bd9Sstevel@tonic-gate 	/* Begin at the beginning, if any */
267*7c478bd9Sstevel@tonic-gate 	if (tok == (char *) NULL) {
268*7c478bd9Sstevel@tonic-gate 	    return ((char *) NULL);
269*7c478bd9Sstevel@tonic-gate 	}
270*7c478bd9Sstevel@tonic-gate 
271*7c478bd9Sstevel@tonic-gate 	/* Find end of the token string */
272*7c478bd9Sstevel@tonic-gate 	tokend = tok + strlen(tok);
273*7c478bd9Sstevel@tonic-gate 
274*7c478bd9Sstevel@tonic-gate 	/* Look for the 1st occurrence of any delimiter */
275*7c478bd9Sstevel@tonic-gate 	for (p = delims ; *p != '\0' ; p++) {
276*7c478bd9Sstevel@tonic-gate 	    for (q = strchr(tok, *p) ; q && (q != tok) && (*(q-1) == '\\') ; q = strchr(q+1, *p)) ;
277*7c478bd9Sstevel@tonic-gate 	    if (q && (q < tokend)) tokend = q;
278*7c478bd9Sstevel@tonic-gate 	}
279*7c478bd9Sstevel@tonic-gate 
280*7c478bd9Sstevel@tonic-gate 	/* Done */
281*7c478bd9Sstevel@tonic-gate 	return(tokend);
282*7c478bd9Sstevel@tonic-gate }
283*7c478bd9Sstevel@tonic-gate 
284*7c478bd9Sstevel@tonic-gate /*
285*7c478bd9Sstevel@tonic-gate  * char *noesc(str)
286*7c478bd9Sstevel@tonic-gate  *
287*7c478bd9Sstevel@tonic-gate  *	This function squeezes out all of the escaped character sequences
288*7c478bd9Sstevel@tonic-gate  *	from the string <str>.  It returns a pointer to that string.
289*7c478bd9Sstevel@tonic-gate  *
290*7c478bd9Sstevel@tonic-gate  *  Arguments:
291*7c478bd9Sstevel@tonic-gate  *	str	char *
292*7c478bd9Sstevel@tonic-gate  *		The string that is to have its escaped characters removed.
293*7c478bd9Sstevel@tonic-gate  *
294*7c478bd9Sstevel@tonic-gate  *  Returns:  char *
295*7c478bd9Sstevel@tonic-gate  *	This function returns its argument <str> always.
296*7c478bd9Sstevel@tonic-gate  *
297*7c478bd9Sstevel@tonic-gate  *  Notes:
298*7c478bd9Sstevel@tonic-gate  *	This function potentially modifies the string it is given.
299*7c478bd9Sstevel@tonic-gate  */
300*7c478bd9Sstevel@tonic-gate 
301*7c478bd9Sstevel@tonic-gate char *
302*7c478bd9Sstevel@tonic-gate noesc(str)
303*7c478bd9Sstevel@tonic-gate 	char   *str;		/* String to remove escaped characters from */
304*7c478bd9Sstevel@tonic-gate {
305*7c478bd9Sstevel@tonic-gate 	char   *p;		/* Temp string pointer */
306*7c478bd9Sstevel@tonic-gate 	char   *q;		/* Temp string pointer */
307*7c478bd9Sstevel@tonic-gate 
308*7c478bd9Sstevel@tonic-gate 	/* Look for an escaped character */
309*7c478bd9Sstevel@tonic-gate 	p = str;
310*7c478bd9Sstevel@tonic-gate 	while (*p && (*p != '\\')) p++;
311*7c478bd9Sstevel@tonic-gate 
312*7c478bd9Sstevel@tonic-gate 
313*7c478bd9Sstevel@tonic-gate 	/*
314*7c478bd9Sstevel@tonic-gate 	 * If there was at least one, squeeze them out
315*7c478bd9Sstevel@tonic-gate 	 * Otherwise, don't touch the argument string
316*7c478bd9Sstevel@tonic-gate 	 */
317*7c478bd9Sstevel@tonic-gate 
318*7c478bd9Sstevel@tonic-gate 	if (*p) {
319*7c478bd9Sstevel@tonic-gate 	    q = p++;
320*7c478bd9Sstevel@tonic-gate 	    while (*q++ = *p++) if (*p == '\\') p++;
321*7c478bd9Sstevel@tonic-gate 	}
322*7c478bd9Sstevel@tonic-gate 
323*7c478bd9Sstevel@tonic-gate 	/* Finished.  Return our argument */
324*7c478bd9Sstevel@tonic-gate 	return(str);
325*7c478bd9Sstevel@tonic-gate }
326*7c478bd9Sstevel@tonic-gate 
327*7c478bd9Sstevel@tonic-gate /*
328*7c478bd9Sstevel@tonic-gate  * struct sevstr *getauxsevs(ptr)
329*7c478bd9Sstevel@tonic-gate  *
330*7c478bd9Sstevel@tonic-gate  *	Parses a string that is in the format of the severity definitions.
331*7c478bd9Sstevel@tonic-gate  *	Returns a pointer to a (malloc'd) structure that contains the
332*7c478bd9Sstevel@tonic-gate  *	definition, or (struct sevstr *) NULL if none was parsed.
333*7c478bd9Sstevel@tonic-gate  *
334*7c478bd9Sstevel@tonic-gate  * Arguments:
335*7c478bd9Sstevel@tonic-gate  *	ptr	char *
336*7c478bd9Sstevel@tonic-gate  *		References the string from which data is to be extracted.
337*7c478bd9Sstevel@tonic-gate  *		If (char *) NULL, continue where we left off.  Otherwise,
338*7c478bd9Sstevel@tonic-gate  *		start with the string referenced by ptr.
339*7c478bd9Sstevel@tonic-gate  *
340*7c478bd9Sstevel@tonic-gate  * Returns: struct sevstr *
341*7c478bd9Sstevel@tonic-gate  *	A pointer to a malloc'd structure containing the severity definition
342*7c478bd9Sstevel@tonic-gate  *	parsed from string, or (struct sevstr *) NULL if none.
343*7c478bd9Sstevel@tonic-gate  *
344*7c478bd9Sstevel@tonic-gate  * Notes:
345*7c478bd9Sstevel@tonic-gate  *    - This function is destructive to the string referenced by its argument.
346*7c478bd9Sstevel@tonic-gate  */
347*7c478bd9Sstevel@tonic-gate 
348*7c478bd9Sstevel@tonic-gate 
349*7c478bd9Sstevel@tonic-gate /* Static data */
350*7c478bd9Sstevel@tonic-gate static	char	       *leftoff = (char *) NULL;
351*7c478bd9Sstevel@tonic-gate 
352*7c478bd9Sstevel@tonic-gate static	struct sevstr *
353*7c478bd9Sstevel@tonic-gate getauxsevs(ptr)
354*7c478bd9Sstevel@tonic-gate 	char   *ptr;
355*7c478bd9Sstevel@tonic-gate {
356*7c478bd9Sstevel@tonic-gate 
357*7c478bd9Sstevel@tonic-gate 	/* Automatic data */
358*7c478bd9Sstevel@tonic-gate 	char	       *current;	/* Ptr to current sev def'n */
359*7c478bd9Sstevel@tonic-gate 	char	       *tokend;		/* Ptr to end of current sev def'n */
360*7c478bd9Sstevel@tonic-gate 	char	       *kywd;		/* Ptr to extracted kywd */
361*7c478bd9Sstevel@tonic-gate 	char	       *valstr;		/* Ptr to extracted sev value */
362*7c478bd9Sstevel@tonic-gate 	char	       *prstr;		/* Ptr to extracted print str */
363*7c478bd9Sstevel@tonic-gate 	char	       *p;		/* Temp pointer */
364*7c478bd9Sstevel@tonic-gate 	int		val;		/* Converted severity value */
365*7c478bd9Sstevel@tonic-gate 	int		done;		/* Flag, sev def'n found and ok? */
366*7c478bd9Sstevel@tonic-gate 	struct sevstr  *rtnval;		/* Value to return */
367*7c478bd9Sstevel@tonic-gate 
368*7c478bd9Sstevel@tonic-gate 
369*7c478bd9Sstevel@tonic-gate 	/* Start anew or start where we left off? */
370*7c478bd9Sstevel@tonic-gate 	current = (ptr == (char *) NULL) ? leftoff : ptr;
371*7c478bd9Sstevel@tonic-gate 
372*7c478bd9Sstevel@tonic-gate 
373*7c478bd9Sstevel@tonic-gate 	/* If nothing to parse, return (char *) NULL */
374*7c478bd9Sstevel@tonic-gate 	if (current == (char *) NULL) {
375*7c478bd9Sstevel@tonic-gate 	    return ((struct sevstr *) NULL);
376*7c478bd9Sstevel@tonic-gate 	}
377*7c478bd9Sstevel@tonic-gate 
378*7c478bd9Sstevel@tonic-gate 
379*7c478bd9Sstevel@tonic-gate 	/*
380*7c478bd9Sstevel@tonic-gate 	 * Look through the string "current" for a token of the form
381*7c478bd9Sstevel@tonic-gate 	 * <kywd>,<sev>,<printstring> delimited by ':' or '\0'
382*7c478bd9Sstevel@tonic-gate 	 */
383*7c478bd9Sstevel@tonic-gate 
384*7c478bd9Sstevel@tonic-gate 	/* Loop initializations */
385*7c478bd9Sstevel@tonic-gate 	done = FALSE;
386*7c478bd9Sstevel@tonic-gate 	rtnval = (struct sevstr *) NULL;
387*7c478bd9Sstevel@tonic-gate 	while (!done) {
388*7c478bd9Sstevel@tonic-gate 
389*7c478bd9Sstevel@tonic-gate 	    /* Eat leading junk */
390*7c478bd9Sstevel@tonic-gate 	    while (*(tokend = exttok(current, ":,")) == ':') {
391*7c478bd9Sstevel@tonic-gate 		current = tokend + 1;
392*7c478bd9Sstevel@tonic-gate 	    }
393*7c478bd9Sstevel@tonic-gate 
394*7c478bd9Sstevel@tonic-gate 	    /* If we've found a <kywd>,... */
395*7c478bd9Sstevel@tonic-gate 	    if (*tokend == ',') {
396*7c478bd9Sstevel@tonic-gate 		kywd = current;
397*7c478bd9Sstevel@tonic-gate 		*tokend = '\0';
398*7c478bd9Sstevel@tonic-gate 
399*7c478bd9Sstevel@tonic-gate 		/* Look for <kywd>,<sev>,... */
400*7c478bd9Sstevel@tonic-gate 		current = tokend + 1;
401*7c478bd9Sstevel@tonic-gate 		if (*(tokend = exttok(current, ":,")) == ',') {
402*7c478bd9Sstevel@tonic-gate 		    valstr = current;
403*7c478bd9Sstevel@tonic-gate 		    *tokend = '\0';
404*7c478bd9Sstevel@tonic-gate 		    current = tokend+1;
405*7c478bd9Sstevel@tonic-gate 		    prstr = current;
406*7c478bd9Sstevel@tonic-gate 
407*7c478bd9Sstevel@tonic-gate 		    /* Make sure <sev> > 4 */
408*7c478bd9Sstevel@tonic-gate 		    val = (int) strtol(noesc(valstr), &p, 0);
409*7c478bd9Sstevel@tonic-gate 		    if ((val > 4) && (p == tokend)) {
410*7c478bd9Sstevel@tonic-gate 
411*7c478bd9Sstevel@tonic-gate 			/*
412*7c478bd9Sstevel@tonic-gate 			 * Found <kywd>,<sev>,<printstring>.
413*7c478bd9Sstevel@tonic-gate 			 * remember where we left off
414*7c478bd9Sstevel@tonic-gate 			 */
415*7c478bd9Sstevel@tonic-gate 
416*7c478bd9Sstevel@tonic-gate 		        if (*(tokend = exttok(current, ":")) == ':') {
417*7c478bd9Sstevel@tonic-gate 			    *tokend = '\0';
418*7c478bd9Sstevel@tonic-gate 			    leftoff = tokend + 1;
419*7c478bd9Sstevel@tonic-gate 			} else leftoff = (char *) NULL;
420*7c478bd9Sstevel@tonic-gate 
421*7c478bd9Sstevel@tonic-gate 			/* Alloc structure to contain severity definition */
422*7c478bd9Sstevel@tonic-gate 			if (rtnval = (struct sevstr *) malloc(sizeof(struct sevstr))) {
423*7c478bd9Sstevel@tonic-gate 
424*7c478bd9Sstevel@tonic-gate 			    /* Fill in structure */
425*7c478bd9Sstevel@tonic-gate 			    rtnval->sevkywd = noesc(kywd);
426*7c478bd9Sstevel@tonic-gate 			    rtnval->sevvalue = val;
427*7c478bd9Sstevel@tonic-gate 			    rtnval->sevprstr = noesc(prstr);
428*7c478bd9Sstevel@tonic-gate 			    rtnval->sevnext = (struct sevstr *) NULL;
429*7c478bd9Sstevel@tonic-gate 			}
430*7c478bd9Sstevel@tonic-gate 
431*7c478bd9Sstevel@tonic-gate 			done = TRUE;
432*7c478bd9Sstevel@tonic-gate 
433*7c478bd9Sstevel@tonic-gate 		    } else {
434*7c478bd9Sstevel@tonic-gate 
435*7c478bd9Sstevel@tonic-gate 			/* Invalid severity value, eat thru end of token */
436*7c478bd9Sstevel@tonic-gate 			current = tokend;
437*7c478bd9Sstevel@tonic-gate 			if (*(tokend = exttok(prstr, ":")) == ':')
438*7c478bd9Sstevel@tonic-gate 			    current++;
439*7c478bd9Sstevel@tonic-gate 		    }
440*7c478bd9Sstevel@tonic-gate 
441*7c478bd9Sstevel@tonic-gate 		} else {
442*7c478bd9Sstevel@tonic-gate 
443*7c478bd9Sstevel@tonic-gate 		    /* Invalid severity definition, eat thru end of token */
444*7c478bd9Sstevel@tonic-gate 		    current = tokend;
445*7c478bd9Sstevel@tonic-gate 		    if (*tokend == ':')
446*7c478bd9Sstevel@tonic-gate 			current++;
447*7c478bd9Sstevel@tonic-gate 		}
448*7c478bd9Sstevel@tonic-gate 
449*7c478bd9Sstevel@tonic-gate 	    } else {
450*7c478bd9Sstevel@tonic-gate 
451*7c478bd9Sstevel@tonic-gate 		/* End of string found */
452*7c478bd9Sstevel@tonic-gate 		done = TRUE;
453*7c478bd9Sstevel@tonic-gate 		leftoff = (char *) NULL;
454*7c478bd9Sstevel@tonic-gate 	    }
455*7c478bd9Sstevel@tonic-gate 
456*7c478bd9Sstevel@tonic-gate 	} /* while (!done) */
457*7c478bd9Sstevel@tonic-gate 
458*7c478bd9Sstevel@tonic-gate 	/* Finished */
459*7c478bd9Sstevel@tonic-gate 	return(rtnval);
460*7c478bd9Sstevel@tonic-gate }
461*7c478bd9Sstevel@tonic-gate 
462*7c478bd9Sstevel@tonic-gate /*
463*7c478bd9Sstevel@tonic-gate  * fmtmsg [-a action] [-c classification] [-l label] [-s severity] [-t tag]
464*7c478bd9Sstevel@tonic-gate  *        [-u subclass[,subclass[,...]]] [text]
465*7c478bd9Sstevel@tonic-gate  *
466*7c478bd9Sstevel@tonic-gate  * Function:
467*7c478bd9Sstevel@tonic-gate  *	Writes a message in the standard format.  Typically used by shell
468*7c478bd9Sstevel@tonic-gate  *	scripts to write error messages to the user.
469*7c478bd9Sstevel@tonic-gate  *
470*7c478bd9Sstevel@tonic-gate  * Arguments:
471*7c478bd9Sstevel@tonic-gate  *	text		String that is the text of the message
472*7c478bd9Sstevel@tonic-gate  *
473*7c478bd9Sstevel@tonic-gate  * Options:
474*7c478bd9Sstevel@tonic-gate  *   -a action		String that describes user action to take to
475*7c478bd9Sstevel@tonic-gate  *			correct the situation
476*7c478bd9Sstevel@tonic-gate  *   -c classification	Keyword that identifies the type of the message
477*7c478bd9Sstevel@tonic-gate  *   -l label		String that identifies the source of the message
478*7c478bd9Sstevel@tonic-gate  *   -s severity	Keyword that identifies the severity of the message
479*7c478bd9Sstevel@tonic-gate  *   -t tag		String that identifies the message (use unclear)
480*7c478bd9Sstevel@tonic-gate  *   -u sub_classes	Comma-list of keywords that refines the type of
481*7c478bd9Sstevel@tonic-gate  *			the message
482*7c478bd9Sstevel@tonic-gate  *
483*7c478bd9Sstevel@tonic-gate  * Environment Variables Used:
484*7c478bd9Sstevel@tonic-gate  *	MSGVERB		Defines the pieces of a message the user expects
485*7c478bd9Sstevel@tonic-gate  *			to see.  It is a list of keywords separated by
486*7c478bd9Sstevel@tonic-gate  *			colons (':').
487*7c478bd9Sstevel@tonic-gate  *	SEV_LEVEL	Defines a list of auxiliary severity keywords, values,
488*7c478bd9Sstevel@tonic-gate  *			and print-strings.  It is a list of fields separated
489*7c478bd9Sstevel@tonic-gate  *			by colons (':').  Each field consists of three
490*7c478bd9Sstevel@tonic-gate  *			elements, keyword, value (in octal, hex, or decimal),
491*7c478bd9Sstevel@tonic-gate  *			and print-string, separated by commas (',').
492*7c478bd9Sstevel@tonic-gate  *
493*7c478bd9Sstevel@tonic-gate  * Needs:
494*7c478bd9Sstevel@tonic-gate  *
495*7c478bd9Sstevel@tonic-gate  * Open Issues:
496*7c478bd9Sstevel@tonic-gate  */
497*7c478bd9Sstevel@tonic-gate 
498*7c478bd9Sstevel@tonic-gate main(argc, argv)
499*7c478bd9Sstevel@tonic-gate 	int	argc;			/* Argument count */
500*7c478bd9Sstevel@tonic-gate 	char   *argv[];			/* Pointers to arguments */
501*7c478bd9Sstevel@tonic-gate {
502*7c478bd9Sstevel@tonic-gate 
503*7c478bd9Sstevel@tonic-gate 	/* Local automatic data */
504*7c478bd9Sstevel@tonic-gate 
505*7c478bd9Sstevel@tonic-gate 	long			class;		/* Classification (built) */
506*7c478bd9Sstevel@tonic-gate 
507*7c478bd9Sstevel@tonic-gate 	int			severity;	/* User specified severity */
508*7c478bd9Sstevel@tonic-gate 	int			msgrtn;		/* Value returned by fmtmsg() */
509*7c478bd9Sstevel@tonic-gate 	int			optchar;	/* Opt char on cmdline */
510*7c478bd9Sstevel@tonic-gate 	int			exitval;	/* Value to return */
511*7c478bd9Sstevel@tonic-gate 
512*7c478bd9Sstevel@tonic-gate 	int			found;		/* FLAG, kywd found yet? */
513*7c478bd9Sstevel@tonic-gate 	int			errflg;		/* FLAG, error seen in cmd */
514*7c478bd9Sstevel@tonic-gate 	int			a_seen;		/* FLAG, -a option seen */
515*7c478bd9Sstevel@tonic-gate 	int			c_seen;		/* FLAG, -c option seen */
516*7c478bd9Sstevel@tonic-gate 	int			l_seen;		/* FLAG, -l option seen */
517*7c478bd9Sstevel@tonic-gate 	int			s_seen;		/* FLAG, -s option seen */
518*7c478bd9Sstevel@tonic-gate 	int			t_seen;		/* FLAG, -t option seen */
519*7c478bd9Sstevel@tonic-gate 	int			u_seen;		/* FLAG, -u option seen */
520*7c478bd9Sstevel@tonic-gate 	int			text_seen;	/* FLAG, text seen */
521*7c478bd9Sstevel@tonic-gate 
522*7c478bd9Sstevel@tonic-gate 	char		       *text;		/* Ptr to user's text */
523*7c478bd9Sstevel@tonic-gate 	char		       *label;		/* Ptr to user's label */
524*7c478bd9Sstevel@tonic-gate 	char		       *tag;		/* Ptr to user's tag */
525*7c478bd9Sstevel@tonic-gate 	char		       *action;		/* Ptr to user's action str */
526*7c478bd9Sstevel@tonic-gate 	char		       *sstr;		/* Ptr to -s (severity) arg */
527*7c478bd9Sstevel@tonic-gate 	char		       *ustr;		/* Ptr to -u (subclass) arg */
528*7c478bd9Sstevel@tonic-gate 	char		       *cstr;		/* Ptr to -c (class) arg */
529*7c478bd9Sstevel@tonic-gate 	char		       *sevstrval;	/* Ptr to SEV_LEVEL argument */
530*7c478bd9Sstevel@tonic-gate 	char		       *sevval;		/* Ptr to temp SEV_LEVEL arg */
531*7c478bd9Sstevel@tonic-gate 	char		       *tokenptr;	/* Ptr to current token */
532*7c478bd9Sstevel@tonic-gate 	char		       *cmdname;	/* Ptr to base command name */
533*7c478bd9Sstevel@tonic-gate 	char		       *p;		/* Multipurpose ptr */
534*7c478bd9Sstevel@tonic-gate 
535*7c478bd9Sstevel@tonic-gate 	struct class_info      *class_info;	/* Ptr to class/subclass info structure */
536*7c478bd9Sstevel@tonic-gate 	struct sev_info	       *sev_info;	/* Ptr to severity info struct */
537*7c478bd9Sstevel@tonic-gate 	struct sevstr	       *penvsev;	/* Ptr to SEV_LEVEL values */
538*7c478bd9Sstevel@tonic-gate 
539*7c478bd9Sstevel@tonic-gate 
540*7c478bd9Sstevel@tonic-gate 
541*7c478bd9Sstevel@tonic-gate 	/*
542*7c478bd9Sstevel@tonic-gate 	 * fmtmsg
543*7c478bd9Sstevel@tonic-gate 	 */
544*7c478bd9Sstevel@tonic-gate 
545*7c478bd9Sstevel@tonic-gate 
546*7c478bd9Sstevel@tonic-gate 	/* Initializations */
547*7c478bd9Sstevel@tonic-gate 
548*7c478bd9Sstevel@tonic-gate 
549*7c478bd9Sstevel@tonic-gate 	/* Extract the base command name from the command */
550*7c478bd9Sstevel@tonic-gate 	if ((p = strrchr(argv[0], '/')) == (char *) NULL)
551*7c478bd9Sstevel@tonic-gate 	    cmdname = argv[0];
552*7c478bd9Sstevel@tonic-gate 	else
553*7c478bd9Sstevel@tonic-gate 	    cmdname = p+1;
554*7c478bd9Sstevel@tonic-gate 
555*7c478bd9Sstevel@tonic-gate 	/* Build the label for messages from "fmtmsg" */
556*7c478bd9Sstevel@tonic-gate 	(void) snprintf(labelbuf, sizeof (labelbuf), "UX:%s", cmdname);
557*7c478bd9Sstevel@tonic-gate 
558*7c478bd9Sstevel@tonic-gate 
559*7c478bd9Sstevel@tonic-gate 	/*
560*7c478bd9Sstevel@tonic-gate 	 * Extract arguments from the command line
561*7c478bd9Sstevel@tonic-gate 	 */
562*7c478bd9Sstevel@tonic-gate 
563*7c478bd9Sstevel@tonic-gate 	/* Initializations */
564*7c478bd9Sstevel@tonic-gate 
565*7c478bd9Sstevel@tonic-gate 	opterr = 0;			/* Disable messages from getopt() */
566*7c478bd9Sstevel@tonic-gate 	errflg = FALSE;			/* No errors seen yet */
567*7c478bd9Sstevel@tonic-gate 
568*7c478bd9Sstevel@tonic-gate 	a_seen = FALSE;			/* No action (-a) text seen yet */
569*7c478bd9Sstevel@tonic-gate 	c_seen = FALSE;			/* No classification (-c) seen yet */
570*7c478bd9Sstevel@tonic-gate 	l_seen = FALSE;			/* No label (-l) seen yet */
571*7c478bd9Sstevel@tonic-gate 	s_seen = FALSE;			/* No severity (-s) seen yet */
572*7c478bd9Sstevel@tonic-gate 	t_seen = FALSE;			/* No tag (-t) seen yet */
573*7c478bd9Sstevel@tonic-gate 	u_seen = FALSE;			/* No subclass (-u) seen yet */
574*7c478bd9Sstevel@tonic-gate 	text_seen = FALSE;		/* No text seen yet */
575*7c478bd9Sstevel@tonic-gate 
576*7c478bd9Sstevel@tonic-gate 
577*7c478bd9Sstevel@tonic-gate 	/*
578*7c478bd9Sstevel@tonic-gate 	 * If only the command name was used, write out a usage string to
579*7c478bd9Sstevel@tonic-gate 	 * the standard output file.
580*7c478bd9Sstevel@tonic-gate 	 */
581*7c478bd9Sstevel@tonic-gate 
582*7c478bd9Sstevel@tonic-gate 	if (argc == 1) {
583*7c478bd9Sstevel@tonic-gate 	    (void) fputs(BIGUSAGE, stderr);
584*7c478bd9Sstevel@tonic-gate 	    exit(0);
585*7c478bd9Sstevel@tonic-gate 	}
586*7c478bd9Sstevel@tonic-gate 
587*7c478bd9Sstevel@tonic-gate 
588*7c478bd9Sstevel@tonic-gate 	/* Parce command line */
589*7c478bd9Sstevel@tonic-gate 	while (((optchar = getopt(argc, argv, "a:c:l:s:t:u:")) != EOF) &&
590*7c478bd9Sstevel@tonic-gate 	       !errflg) {
591*7c478bd9Sstevel@tonic-gate 
592*7c478bd9Sstevel@tonic-gate 	    switch(optchar) {
593*7c478bd9Sstevel@tonic-gate 
594*7c478bd9Sstevel@tonic-gate 	    case 'a':		/* -a actiontext */
595*7c478bd9Sstevel@tonic-gate 		if (!a_seen) {
596*7c478bd9Sstevel@tonic-gate 		    action = optarg;
597*7c478bd9Sstevel@tonic-gate 		    a_seen = TRUE;
598*7c478bd9Sstevel@tonic-gate 		} else errflg = TRUE;
599*7c478bd9Sstevel@tonic-gate 		break;
600*7c478bd9Sstevel@tonic-gate 
601*7c478bd9Sstevel@tonic-gate 	    case 'c':		/* -c classification */
602*7c478bd9Sstevel@tonic-gate 		if (!c_seen) {
603*7c478bd9Sstevel@tonic-gate 		    cstr = optarg;
604*7c478bd9Sstevel@tonic-gate 		    c_seen = TRUE;
605*7c478bd9Sstevel@tonic-gate 		} else errflg = TRUE;
606*7c478bd9Sstevel@tonic-gate 		break;
607*7c478bd9Sstevel@tonic-gate 
608*7c478bd9Sstevel@tonic-gate 	    case 'l':		/* -l label */
609*7c478bd9Sstevel@tonic-gate 		if (!l_seen) {
610*7c478bd9Sstevel@tonic-gate 		    label = optarg;
611*7c478bd9Sstevel@tonic-gate 		    l_seen = TRUE;
612*7c478bd9Sstevel@tonic-gate 		} else errflg = TRUE;
613*7c478bd9Sstevel@tonic-gate 		break;
614*7c478bd9Sstevel@tonic-gate 
615*7c478bd9Sstevel@tonic-gate 	    case 's':		/* -s severity */
616*7c478bd9Sstevel@tonic-gate 		if (!s_seen) {
617*7c478bd9Sstevel@tonic-gate 		    sstr = optarg;
618*7c478bd9Sstevel@tonic-gate 		    s_seen = TRUE;
619*7c478bd9Sstevel@tonic-gate 		} else errflg = TRUE;
620*7c478bd9Sstevel@tonic-gate 		break;
621*7c478bd9Sstevel@tonic-gate 
622*7c478bd9Sstevel@tonic-gate 	    case 't':		/* -t tag */
623*7c478bd9Sstevel@tonic-gate 		if (!t_seen) {
624*7c478bd9Sstevel@tonic-gate 		    tag = optarg;
625*7c478bd9Sstevel@tonic-gate 		    t_seen = TRUE;
626*7c478bd9Sstevel@tonic-gate 		} else errflg = TRUE;
627*7c478bd9Sstevel@tonic-gate 		break;
628*7c478bd9Sstevel@tonic-gate 
629*7c478bd9Sstevel@tonic-gate 	    case 'u':		/* -u subclasslist */
630*7c478bd9Sstevel@tonic-gate 		if (!u_seen) {
631*7c478bd9Sstevel@tonic-gate 		    ustr = optarg;
632*7c478bd9Sstevel@tonic-gate 		    u_seen = TRUE;
633*7c478bd9Sstevel@tonic-gate 		} else errflg = TRUE;
634*7c478bd9Sstevel@tonic-gate 		break;
635*7c478bd9Sstevel@tonic-gate 
636*7c478bd9Sstevel@tonic-gate 	    case '?':		/* -? or unknown option */
637*7c478bd9Sstevel@tonic-gate 	    default:
638*7c478bd9Sstevel@tonic-gate 		errflg = TRUE;
639*7c478bd9Sstevel@tonic-gate 		break;
640*7c478bd9Sstevel@tonic-gate 
641*7c478bd9Sstevel@tonic-gate 	    } /* esac */
642*7c478bd9Sstevel@tonic-gate 	}
643*7c478bd9Sstevel@tonic-gate 
644*7c478bd9Sstevel@tonic-gate 
645*7c478bd9Sstevel@tonic-gate 	/* Get the text */
646*7c478bd9Sstevel@tonic-gate 	if (!errflg) {
647*7c478bd9Sstevel@tonic-gate 	    if (argc == (optind+1)) {
648*7c478bd9Sstevel@tonic-gate 		text = argv[optind];
649*7c478bd9Sstevel@tonic-gate 		text_seen = TRUE;
650*7c478bd9Sstevel@tonic-gate 	    }
651*7c478bd9Sstevel@tonic-gate 	    else if (argc != optind) {
652*7c478bd9Sstevel@tonic-gate 		errflg = TRUE;
653*7c478bd9Sstevel@tonic-gate 	    }
654*7c478bd9Sstevel@tonic-gate 	}
655*7c478bd9Sstevel@tonic-gate 
656*7c478bd9Sstevel@tonic-gate 
657*7c478bd9Sstevel@tonic-gate 	/* Report syntax errors */
658*7c478bd9Sstevel@tonic-gate 	if (errflg) {
659*7c478bd9Sstevel@tonic-gate 	    (void) fputs(BIGUSAGE, stderr);
660*7c478bd9Sstevel@tonic-gate 	    exit(1);
661*7c478bd9Sstevel@tonic-gate 	}
662*7c478bd9Sstevel@tonic-gate 
663*7c478bd9Sstevel@tonic-gate 
664*7c478bd9Sstevel@tonic-gate 	/*
665*7c478bd9Sstevel@tonic-gate 	 * Classification.
666*7c478bd9Sstevel@tonic-gate 	 */
667*7c478bd9Sstevel@tonic-gate 
668*7c478bd9Sstevel@tonic-gate 	class = 0L;
669*7c478bd9Sstevel@tonic-gate 	if (c_seen) {
670*7c478bd9Sstevel@tonic-gate 
671*7c478bd9Sstevel@tonic-gate 	    /* Search for keyword in list */
672*7c478bd9Sstevel@tonic-gate 	    for (class_info = &classes[0] ;
673*7c478bd9Sstevel@tonic-gate 		 (class_info->keyword != (char *) NULL) &&
674*7c478bd9Sstevel@tonic-gate 		 (strcmp(cstr, class_info->keyword)) ;
675*7c478bd9Sstevel@tonic-gate 		 class_info++) ;
676*7c478bd9Sstevel@tonic-gate 
677*7c478bd9Sstevel@tonic-gate 	    /* If invalid (keyword unknown), write a message and exit */
678*7c478bd9Sstevel@tonic-gate 	    if (class_info->keyword == (char *) NULL) {
679*7c478bd9Sstevel@tonic-gate 		(void) snprintf(msgbuf, sizeof (msgbuf),
680*7c478bd9Sstevel@tonic-gate 			"Invalid class: %s", cstr);
681*7c478bd9Sstevel@tonic-gate 		(void) fmtmsg(CLASS, labelbuf, MM_ERROR, msgbuf,
682*7c478bd9Sstevel@tonic-gate 		              MM_NULLACT, MM_NULLTAG);
683*7c478bd9Sstevel@tonic-gate 		exit(1);
684*7c478bd9Sstevel@tonic-gate 	    }
685*7c478bd9Sstevel@tonic-gate 
686*7c478bd9Sstevel@tonic-gate 	    /* Save classification */
687*7c478bd9Sstevel@tonic-gate 	    class = class_info->value;
688*7c478bd9Sstevel@tonic-gate 
689*7c478bd9Sstevel@tonic-gate 	}
690*7c478bd9Sstevel@tonic-gate 
691*7c478bd9Sstevel@tonic-gate 
692*7c478bd9Sstevel@tonic-gate 	/*
693*7c478bd9Sstevel@tonic-gate 	 * Subclassification.
694*7c478bd9Sstevel@tonic-gate 	 */
695*7c478bd9Sstevel@tonic-gate 
696*7c478bd9Sstevel@tonic-gate 	if (u_seen) {
697*7c478bd9Sstevel@tonic-gate 
698*7c478bd9Sstevel@tonic-gate 	    errflg = FALSE;
699*7c478bd9Sstevel@tonic-gate 	    p = strcpy(malloc((unsigned int) strlen(ustr)+1), ustr);
700*7c478bd9Sstevel@tonic-gate 	    if ((tokenptr = strtok(p, ",")) == (char *) NULL) errflg = TRUE;
701*7c478bd9Sstevel@tonic-gate 	    else do {
702*7c478bd9Sstevel@tonic-gate 
703*7c478bd9Sstevel@tonic-gate 		/* Got a keyword.  Look for it in keyword list */
704*7c478bd9Sstevel@tonic-gate 		for (class_info = subclasses ;
705*7c478bd9Sstevel@tonic-gate 		     (class_info->keyword != (char *) NULL) &&
706*7c478bd9Sstevel@tonic-gate 		     (strcmp(tokenptr, class_info->keyword) != 0) ;
707*7c478bd9Sstevel@tonic-gate 		     class_info++) ;
708*7c478bd9Sstevel@tonic-gate 
709*7c478bd9Sstevel@tonic-gate 		/* If found in list and no conflict, remember in class */
710*7c478bd9Sstevel@tonic-gate 		if ((class_info->keyword != (char *) NULL) && ((class & class_info->conflict) == 0L))
711*7c478bd9Sstevel@tonic-gate 		    class |= class_info->value;
712*7c478bd9Sstevel@tonic-gate 		else
713*7c478bd9Sstevel@tonic-gate 		    errflg = TRUE;
714*7c478bd9Sstevel@tonic-gate 
715*7c478bd9Sstevel@tonic-gate 	    } while (!errflg && ((tokenptr = strtok((char *) NULL, ",")) != (char *) NULL)) ;
716*7c478bd9Sstevel@tonic-gate 
717*7c478bd9Sstevel@tonic-gate 	    if (errflg) {
718*7c478bd9Sstevel@tonic-gate 		(void) snprintf(msgbuf, sizeof (msgbuf),
719*7c478bd9Sstevel@tonic-gate 			"Invalid subclass: %s", ustr);
720*7c478bd9Sstevel@tonic-gate 		(void) fmtmsg(CLASS, labelbuf, MM_ERROR, msgbuf,
721*7c478bd9Sstevel@tonic-gate 		              MM_NULLACT, MM_NULLTAG);
722*7c478bd9Sstevel@tonic-gate 		exit(1);
723*7c478bd9Sstevel@tonic-gate 	    }
724*7c478bd9Sstevel@tonic-gate 
725*7c478bd9Sstevel@tonic-gate 	}
726*7c478bd9Sstevel@tonic-gate 
727*7c478bd9Sstevel@tonic-gate 	if (!c_seen & !u_seen) class = MM_NULLMC;
728*7c478bd9Sstevel@tonic-gate 
729*7c478bd9Sstevel@tonic-gate 
730*7c478bd9Sstevel@tonic-gate 
731*7c478bd9Sstevel@tonic-gate 	/*
732*7c478bd9Sstevel@tonic-gate 	 * Severity.
733*7c478bd9Sstevel@tonic-gate 	 */
734*7c478bd9Sstevel@tonic-gate 
735*7c478bd9Sstevel@tonic-gate 	if (s_seen) {
736*7c478bd9Sstevel@tonic-gate 
737*7c478bd9Sstevel@tonic-gate 	    /* If the severity is specified as a number, use that value */
738*7c478bd9Sstevel@tonic-gate 	    severity = strtol(sstr, &p, 10);
739*7c478bd9Sstevel@tonic-gate 	    if (*p || (strlen(sstr) == 0)) {
740*7c478bd9Sstevel@tonic-gate 
741*7c478bd9Sstevel@tonic-gate 		/* Look for the standard severities */
742*7c478bd9Sstevel@tonic-gate 		for (sev_info = severities ;
743*7c478bd9Sstevel@tonic-gate 		     (sev_info->keyword != (char *) NULL) &&
744*7c478bd9Sstevel@tonic-gate 		     (strcmp(sstr, sev_info->keyword)) ;
745*7c478bd9Sstevel@tonic-gate 		     sev_info++) ;
746*7c478bd9Sstevel@tonic-gate 
747*7c478bd9Sstevel@tonic-gate 		/*
748*7c478bd9Sstevel@tonic-gate 		 * If the "severity" argument is one of the standard keywords,
749*7c478bd9Sstevel@tonic-gate 		 * remember it for fmtmsg().  Otherwise, look at the SEV_LEVEL
750*7c478bd9Sstevel@tonic-gate 		 * environment variable for severity extensions.
751*7c478bd9Sstevel@tonic-gate 		 */
752*7c478bd9Sstevel@tonic-gate 
753*7c478bd9Sstevel@tonic-gate 		/* If the keyword is one of the standard ones, save severity */
754*7c478bd9Sstevel@tonic-gate 		if (sev_info->keyword != (char *) NULL) severity = sev_info->value;
755*7c478bd9Sstevel@tonic-gate 
756*7c478bd9Sstevel@tonic-gate 		else {
757*7c478bd9Sstevel@tonic-gate 
758*7c478bd9Sstevel@tonic-gate 		    /*
759*7c478bd9Sstevel@tonic-gate 		     * Severity keyword may be one of the extended set, if any.
760*7c478bd9Sstevel@tonic-gate 		     */
761*7c478bd9Sstevel@tonic-gate 
762*7c478bd9Sstevel@tonic-gate 		    /* Get the value of the SEV_LEVEL environment variable */
763*7c478bd9Sstevel@tonic-gate 		    found = FALSE;
764*7c478bd9Sstevel@tonic-gate 		    if ((sevstrval = getenv(SEV_LEVEL)) != (char *) NULL) {
765*7c478bd9Sstevel@tonic-gate 			sevval = (char *) malloc((unsigned int) strlen(sevstrval)+1);
766*7c478bd9Sstevel@tonic-gate 			penvsev = getauxsevs(strcpy(sevval, sevstrval));
767*7c478bd9Sstevel@tonic-gate 			if (penvsev != (struct sevstr *) NULL) do {
768*7c478bd9Sstevel@tonic-gate 			    if (strcmp(penvsev->sevkywd, sstr) == 0) {
769*7c478bd9Sstevel@tonic-gate 				severity = penvsev->sevvalue;
770*7c478bd9Sstevel@tonic-gate 				found = TRUE;
771*7c478bd9Sstevel@tonic-gate 			    }
772*7c478bd9Sstevel@tonic-gate 			    else {
773*7c478bd9Sstevel@tonic-gate 				free(penvsev);
774*7c478bd9Sstevel@tonic-gate 				penvsev = getauxsevs((char *) NULL);
775*7c478bd9Sstevel@tonic-gate 			    }
776*7c478bd9Sstevel@tonic-gate 			} while (!found && (penvsev != (struct sevstr *) NULL));
777*7c478bd9Sstevel@tonic-gate 
778*7c478bd9Sstevel@tonic-gate 			if (found) free(penvsev);
779*7c478bd9Sstevel@tonic-gate 			free(sevval);
780*7c478bd9Sstevel@tonic-gate 		    }
781*7c478bd9Sstevel@tonic-gate 
782*7c478bd9Sstevel@tonic-gate 		    if (!found) {
783*7c478bd9Sstevel@tonic-gate 			(void) snprintf(msgbuf, sizeof (msgbuf),
784*7c478bd9Sstevel@tonic-gate 				"Invalid severity: %s", sstr);
785*7c478bd9Sstevel@tonic-gate 			(void) fmtmsg(CLASS, labelbuf, MM_ERROR, msgbuf,
786*7c478bd9Sstevel@tonic-gate 				      MM_NULLACT, MM_NULLTAG);
787*7c478bd9Sstevel@tonic-gate 			exit(1);
788*7c478bd9Sstevel@tonic-gate 		    }
789*7c478bd9Sstevel@tonic-gate 
790*7c478bd9Sstevel@tonic-gate 		}  /* <severity> is not one of the standard severities */
791*7c478bd9Sstevel@tonic-gate 
792*7c478bd9Sstevel@tonic-gate 	    }  /* <severity> is not numeric */
793*7c478bd9Sstevel@tonic-gate 
794*7c478bd9Sstevel@tonic-gate 	}  /* if (s_seen) */
795*7c478bd9Sstevel@tonic-gate 
796*7c478bd9Sstevel@tonic-gate 	else severity = MM_NULLSEV;
797*7c478bd9Sstevel@tonic-gate 
798*7c478bd9Sstevel@tonic-gate 
799*7c478bd9Sstevel@tonic-gate 	/*
800*7c478bd9Sstevel@tonic-gate 	 * Other options
801*7c478bd9Sstevel@tonic-gate 	 */
802*7c478bd9Sstevel@tonic-gate 
803*7c478bd9Sstevel@tonic-gate 	if (!a_seen) action = MM_NULLACT;
804*7c478bd9Sstevel@tonic-gate 	if (!l_seen) label = MM_NULLLBL;
805*7c478bd9Sstevel@tonic-gate 	if (!t_seen) tag = MM_NULLTAG;
806*7c478bd9Sstevel@tonic-gate 	if (!text_seen) text = MM_NULLTXT;
807*7c478bd9Sstevel@tonic-gate 
808*7c478bd9Sstevel@tonic-gate 
809*7c478bd9Sstevel@tonic-gate 	/*
810*7c478bd9Sstevel@tonic-gate 	 * Write the message
811*7c478bd9Sstevel@tonic-gate 	 */
812*7c478bd9Sstevel@tonic-gate 
813*7c478bd9Sstevel@tonic-gate 	msgrtn = fmtmsg(class, label, severity, text, action ,tag);
814*7c478bd9Sstevel@tonic-gate 
815*7c478bd9Sstevel@tonic-gate 
816*7c478bd9Sstevel@tonic-gate 	/*
817*7c478bd9Sstevel@tonic-gate 	 * Return appropriate value to the shell (or wherever)
818*7c478bd9Sstevel@tonic-gate 	 */
819*7c478bd9Sstevel@tonic-gate 
820*7c478bd9Sstevel@tonic-gate 	exitval = 0;
821*7c478bd9Sstevel@tonic-gate 	if (msgrtn == MM_NOTOK) exitval = 32;
822*7c478bd9Sstevel@tonic-gate 	else {
823*7c478bd9Sstevel@tonic-gate 	    if (msgrtn & MM_NOMSG) exitval += 2;
824*7c478bd9Sstevel@tonic-gate 	    if (msgrtn & MM_NOCON) exitval += 4;
825*7c478bd9Sstevel@tonic-gate 	}
826*7c478bd9Sstevel@tonic-gate 
827*7c478bd9Sstevel@tonic-gate 	exit(exitval);
828*7c478bd9Sstevel@tonic-gate 	return(exitval);
829*7c478bd9Sstevel@tonic-gate }
830