xref: /titanic_51/usr/src/lib/libast/common/comp/fmtmsglib.c (revision 3e14f97f673e8a630f076077de35afdd43dc1587)
1da2e3ebdSchin /***********************************************************************
2da2e3ebdSchin *                                                                      *
3da2e3ebdSchin *               This software is part of the ast package               *
4*3e14f97fSRoger A. Faulkner *          Copyright (c) 1985-2010 AT&T Intellectual Property          *
5da2e3ebdSchin *                      and is licensed under the                       *
6da2e3ebdSchin *                  Common Public License, Version 1.0                  *
77c2fbfb3SApril Chin *                    by AT&T Intellectual Property                     *
8da2e3ebdSchin *                                                                      *
9da2e3ebdSchin *                A copy of the License is available at                 *
10da2e3ebdSchin *            http://www.opensource.org/licenses/cpl1.0.txt             *
11da2e3ebdSchin *         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
12da2e3ebdSchin *                                                                      *
13da2e3ebdSchin *              Information and Software Systems Research               *
14da2e3ebdSchin *                            AT&T Research                             *
15da2e3ebdSchin *                           Florham Park NJ                            *
16da2e3ebdSchin *                                                                      *
17da2e3ebdSchin *                 Glenn Fowler <gsf@research.att.com>                  *
18da2e3ebdSchin *                  David Korn <dgk@research.att.com>                   *
19da2e3ebdSchin *                   Phong Vo <kpv@research.att.com>                    *
20da2e3ebdSchin *                                                                      *
21da2e3ebdSchin ***********************************************************************/
22da2e3ebdSchin #pragma prototyped
23da2e3ebdSchin /*
24da2e3ebdSchin  * fmtmsg implementation
25da2e3ebdSchin  */
26da2e3ebdSchin 
27da2e3ebdSchin #include <ast.h>
28da2e3ebdSchin 
29da2e3ebdSchin #if _lib_fmtmsg
30da2e3ebdSchin 
31da2e3ebdSchin NoN(fmtmsg)
32da2e3ebdSchin 
33da2e3ebdSchin #else
34da2e3ebdSchin 
35da2e3ebdSchin #define MM_TABLES
36da2e3ebdSchin 
37da2e3ebdSchin #include <fmtmsg.h>
38da2e3ebdSchin 
39da2e3ebdSchin #define INIT_VERB	0x1
40da2e3ebdSchin #define INIT_CONSOLE	0x2
41da2e3ebdSchin 
42da2e3ebdSchin static struct
43da2e3ebdSchin {
44da2e3ebdSchin 	int		console;
45da2e3ebdSchin 	unsigned int	init;
46da2e3ebdSchin 	unsigned int	mask;
47da2e3ebdSchin } mm;
48da2e3ebdSchin 
49da2e3ebdSchin const MM_table_t	mm_class[] =
50da2e3ebdSchin {
51da2e3ebdSchin 	"null",		0,		0,
52da2e3ebdSchin 	"hard",		"HARDWARE",	MM_HARD,
53da2e3ebdSchin 	"soft",		"SOFTWARE",	MM_SOFT,
54da2e3ebdSchin 	"firm",		"FIRMWARE",	MM_FIRM,
55da2e3ebdSchin 	"appl",		"APPLICATION",	MM_APPL,
56da2e3ebdSchin 	"util",		"UTILITY",	MM_UTIL,
57da2e3ebdSchin 	"opsys",	"KERNEL",	MM_OPSYS,
58da2e3ebdSchin 	"print",	0,		MM_PRINT,
59da2e3ebdSchin 	"console",	0,		MM_CONSOLE,
60da2e3ebdSchin 	"recov",	"RECOVERABLE",	MM_RECOVER,
61da2e3ebdSchin 	"nrecov",	"PANIC",	MM_NRECOV,
62da2e3ebdSchin 	0,		0,		0
63da2e3ebdSchin };
64da2e3ebdSchin 
65da2e3ebdSchin static const MM_table_t	mm_severity_init[] =
66da2e3ebdSchin {
67da2e3ebdSchin 	"nosev",	0,		MM_NOSEV,
68da2e3ebdSchin 	"halt",		"HALT",		MM_HALT,
69da2e3ebdSchin 	"error",	"ERROR",	MM_ERROR,
70da2e3ebdSchin 	"warn",		"WARNING",	MM_WARNING,
71da2e3ebdSchin 	"info",		"INFO",		MM_INFO,
72da2e3ebdSchin 	0,		0,		0
73da2e3ebdSchin };
74da2e3ebdSchin 
75da2e3ebdSchin const MM_table_t	mm_verb[] =
76da2e3ebdSchin {
77da2e3ebdSchin 	"all",		0,		MM_all,
78da2e3ebdSchin 	"action",	0,		MM_action,
79da2e3ebdSchin 	"class",	0,		MM_class,
80da2e3ebdSchin 	"default",	0,		MM_default,
81da2e3ebdSchin 	"label",	0,		MM_label,
82da2e3ebdSchin 	"severity",	0,		MM_severity,
83da2e3ebdSchin 	"source",	0,		MM_source,
84da2e3ebdSchin 	"tag",		0,		MM_tag,
85da2e3ebdSchin 	"text",		0,		MM_text,
86da2e3ebdSchin 	0,		0,		0
87da2e3ebdSchin };
88da2e3ebdSchin 
89da2e3ebdSchin const MM_table_t*
90da2e3ebdSchin _mm_severity(void)
91da2e3ebdSchin {
92da2e3ebdSchin 	static MM_table_t*	severity;
93da2e3ebdSchin 
94da2e3ebdSchin 	if (!severity)
95da2e3ebdSchin 	{
96da2e3ebdSchin 		register char*		s;
97da2e3ebdSchin 		register MM_table_t*	p;
98da2e3ebdSchin 		register int		n;
99da2e3ebdSchin 		register int		c;
100da2e3ebdSchin 		char*			e;
101da2e3ebdSchin 		MM_table_t*		q;
102da2e3ebdSchin 
103da2e3ebdSchin 		n = 0;
104da2e3ebdSchin 		if ((s = getenv(MM_SEVERITY_ENV)) && *s)
105da2e3ebdSchin 		{
106da2e3ebdSchin 			e = s;
107da2e3ebdSchin 			c = 0;
108da2e3ebdSchin 			for (;;)
109da2e3ebdSchin 			{
110da2e3ebdSchin 				switch (*s++)
111da2e3ebdSchin 				{
112da2e3ebdSchin 				case 0:
113da2e3ebdSchin 					break;
114da2e3ebdSchin 				case ',':
115da2e3ebdSchin 					if (++c > 2)
116da2e3ebdSchin 					{
117da2e3ebdSchin 						n = 0;
118da2e3ebdSchin 						break;
119da2e3ebdSchin 					}
120da2e3ebdSchin 					continue;
121da2e3ebdSchin 				case ':':
122da2e3ebdSchin 					if (c != 2)
123da2e3ebdSchin 					{
124da2e3ebdSchin 						n = 0;
125da2e3ebdSchin 						break;
126da2e3ebdSchin 					}
127da2e3ebdSchin 					c = 0;
128da2e3ebdSchin 					n++;
129da2e3ebdSchin 					continue;
130da2e3ebdSchin 				default:
131da2e3ebdSchin 					continue;
132da2e3ebdSchin 				}
133da2e3ebdSchin 				break;
134da2e3ebdSchin 			}
135da2e3ebdSchin 			if (c == 2)
136da2e3ebdSchin 				n++;
137da2e3ebdSchin 			else n = 0;
138da2e3ebdSchin 			if (n)
139da2e3ebdSchin 			{
140da2e3ebdSchin 				for (p = (MM_table_t*)mm_severity_init; p->name; p++);
141da2e3ebdSchin 				n += p - (MM_table_t*)mm_severity_init + 1;
142da2e3ebdSchin 				if (severity = newof(0, MM_table_t, n, s - e))
143da2e3ebdSchin 				{
144da2e3ebdSchin 					s = (char*)severity + n * sizeof(MM_table_t);
145da2e3ebdSchin 					strcpy(s, e);
146da2e3ebdSchin 					p = severity;
147da2e3ebdSchin 					for (q = (MM_table_t*)mm_severity_init; q->name; q++)
148da2e3ebdSchin 						*p++ = *q;
149da2e3ebdSchin 					p->name = s;
150da2e3ebdSchin 					c = 0;
151da2e3ebdSchin 					for (;;)
152da2e3ebdSchin 					{
153da2e3ebdSchin 						switch (*s++)
154da2e3ebdSchin 						{
155da2e3ebdSchin 						case 0:
156da2e3ebdSchin 							break;
157da2e3ebdSchin 						case ',':
158da2e3ebdSchin 							switch (c++)
159da2e3ebdSchin 							{
160da2e3ebdSchin 							case 0:
161da2e3ebdSchin 								*(s - 1) = 0;
162da2e3ebdSchin 								p->value = strtol(s, NiL, 0);
163da2e3ebdSchin 								break;
164da2e3ebdSchin 							case 1:
165da2e3ebdSchin 								p->display = s;
166da2e3ebdSchin 								break;
167da2e3ebdSchin 							}
168da2e3ebdSchin 							continue;
169da2e3ebdSchin 						case ':':
170da2e3ebdSchin 							c = 0;
171da2e3ebdSchin 							*(s - 1) = 0;
172da2e3ebdSchin 							(++p)->name = s;
173da2e3ebdSchin 							continue;
174da2e3ebdSchin 						default:
175da2e3ebdSchin 							continue;
176da2e3ebdSchin 						}
177da2e3ebdSchin 						break;
178da2e3ebdSchin 					}
179da2e3ebdSchin 				}
180da2e3ebdSchin 			}
181da2e3ebdSchin 		}
182da2e3ebdSchin 		if (!severity)
183da2e3ebdSchin 			severity = (MM_table_t*)mm_severity_init;
184da2e3ebdSchin 	}
185da2e3ebdSchin 	return (const MM_table_t*)severity;
186da2e3ebdSchin }
187da2e3ebdSchin 
188da2e3ebdSchin static char*
189da2e3ebdSchin display(register const MM_table_t* tab, int value, int mask)
190da2e3ebdSchin {
191da2e3ebdSchin 	while (tab->name)
192da2e3ebdSchin 	{
193da2e3ebdSchin 		if (value == tab->value || mask && (value & tab->value))
194da2e3ebdSchin 			return (char*)tab->display;
195da2e3ebdSchin 		tab++;
196da2e3ebdSchin 	}
197da2e3ebdSchin 	return 0;
198da2e3ebdSchin }
199da2e3ebdSchin 
200da2e3ebdSchin int
201da2e3ebdSchin fmtmsg(long classification, const char* label, int severity, const char* text, const char* action, const char* tag)
202da2e3ebdSchin {
203da2e3ebdSchin 	register int		c;
204da2e3ebdSchin 	register char*		s;
205da2e3ebdSchin 	register char*		t;
206da2e3ebdSchin 	register MM_table_t*	p;
207da2e3ebdSchin 	int			n;
208da2e3ebdSchin 	int			m;
209da2e3ebdSchin 	int			r;
210da2e3ebdSchin 	int			fd;
211da2e3ebdSchin 	unsigned int		mask;
212da2e3ebdSchin 	Sfio_t*			sp;
213da2e3ebdSchin 	char			lab[MM_LABEL_1_MAX + MM_LABEL_2_MAX + 3];
214da2e3ebdSchin 
215da2e3ebdSchin 	if (!mm.init)
216da2e3ebdSchin 	{
217da2e3ebdSchin 		mm.init = INIT_VERB;
218da2e3ebdSchin 		if (!(s = getenv(MM_VERB_ENV)))
219da2e3ebdSchin 			mm.mask = MM_default;
220da2e3ebdSchin 		else for (;;)
221da2e3ebdSchin 		{
222da2e3ebdSchin 			if (t = strchr(s, ':'))
223da2e3ebdSchin 				*t = 0;
224da2e3ebdSchin 			if (!(p = (MM_table_t*)strlook(mm_verb, sizeof(MM_table_t), s)))
225da2e3ebdSchin 			{
226da2e3ebdSchin 				mm.mask = MM_default;
227da2e3ebdSchin 				if (t)
228da2e3ebdSchin 					*t = ':';
229da2e3ebdSchin 				break;
230da2e3ebdSchin 			}
231da2e3ebdSchin 			mm.mask |= p->value;
232da2e3ebdSchin 			if (!t)
233da2e3ebdSchin 				break;
234da2e3ebdSchin 			*t++ = ':';
235da2e3ebdSchin 			s = t;
236da2e3ebdSchin 		}
237da2e3ebdSchin 	}
238da2e3ebdSchin 	if (!(classification & (MM_CONSOLE|MM_PRINT)))
239da2e3ebdSchin 		return 0;
240da2e3ebdSchin 	if (!(sp = sfstropen()))
241da2e3ebdSchin 		return MM_NOTOK;
242da2e3ebdSchin 	r = 0;
243da2e3ebdSchin 	if (s = (char*)label)
244da2e3ebdSchin 	{
245da2e3ebdSchin 		if (t = strchr(s, ':'))
246da2e3ebdSchin 		{
247da2e3ebdSchin 			if ((n = t - s) > MM_LABEL_1_MAX)
248da2e3ebdSchin 				n = MM_LABEL_1_MAX;
249da2e3ebdSchin 			sfprintf(sp, "%*.*s:", n, n, s);
250da2e3ebdSchin 			s = ++t;
251da2e3ebdSchin 			if ((n = strlen(t)) > MM_LABEL_2_MAX)
252da2e3ebdSchin 				n = MM_LABEL_2_MAX;
253da2e3ebdSchin 			sfprintf(sp, "%*.*s", n, n, s);
254da2e3ebdSchin 		}
255da2e3ebdSchin 		else
256da2e3ebdSchin 		{
257da2e3ebdSchin 			if ((n = strlen(t)) > MM_LABEL_1_MAX)
258da2e3ebdSchin 				n = MM_LABEL_1_MAX;
259da2e3ebdSchin 			sfprintf(sp, "%*.*s", n, n, s);
260da2e3ebdSchin 		}
261da2e3ebdSchin 		if (!(s = sfstruse(sp)))
262da2e3ebdSchin 		{
263da2e3ebdSchin 			sfstrclose(sp);
264da2e3ebdSchin 			return MM_NOTOK;
265da2e3ebdSchin 		}
266da2e3ebdSchin 		strcpy(lab, s);
267da2e3ebdSchin 	}
268da2e3ebdSchin 	for (;;)
269da2e3ebdSchin 	{
270da2e3ebdSchin 		if (classification & MM_CONSOLE)
271da2e3ebdSchin 		{
272da2e3ebdSchin 			classification &= ~MM_CONSOLE;
273da2e3ebdSchin 			if (!(mm.init & INIT_CONSOLE))
274da2e3ebdSchin 				mm.console = open("/dev/console", O_WRONLY|O_APPEND|O_NOCTTY);
275da2e3ebdSchin 			if (mm.console < 0)
276da2e3ebdSchin 			{
277da2e3ebdSchin 				r |= MM_NOCON;
278da2e3ebdSchin 				continue;
279da2e3ebdSchin 			}
280da2e3ebdSchin 			c = MM_NOCON;
281da2e3ebdSchin 			fd = mm.console;
282da2e3ebdSchin 			mask = MM_all;
283da2e3ebdSchin 		}
284da2e3ebdSchin 		else if (classification & MM_PRINT)
285da2e3ebdSchin 		{
286da2e3ebdSchin 			classification &= ~MM_PRINT;
287da2e3ebdSchin 			c = MM_NOMSG;
288da2e3ebdSchin 			fd = 2;
289da2e3ebdSchin 			mask = mm.mask;
290da2e3ebdSchin 		}
291da2e3ebdSchin 		else break;
292da2e3ebdSchin 		if ((mask & MM_label) && label)
293da2e3ebdSchin 			sfprintf(sp, "%s: ", lab);
294da2e3ebdSchin 		if ((mask & MM_severity) && (s = display(mm_severity, severity, 0)))
295da2e3ebdSchin 			sfprintf(sp, "%s: ", s);
296da2e3ebdSchin 		n = sfstrtell(sp);
297da2e3ebdSchin 		if ((mask & MM_text) && text)
298da2e3ebdSchin 			sfprintf(sp, "%s\n", text);
299da2e3ebdSchin 		else sfputc(sp, '\n');
300da2e3ebdSchin 		if ((mask & MM_action) && action || (mask & MM_tag) && (label || tag))
301da2e3ebdSchin 		{
302da2e3ebdSchin 			if (fd != mm.console && (n -= 8) > 0)
303da2e3ebdSchin 				sfprintf(sp, "%*.*s", n, n, "");
304da2e3ebdSchin 			sfprintf(sp, "TO FIX:");
305da2e3ebdSchin 			if ((mask & MM_action) && action)
306da2e3ebdSchin 				sfprintf(sp, " %s", action);
307da2e3ebdSchin 			if ((mask & MM_tag) && (label || tag))
308da2e3ebdSchin 			{
309da2e3ebdSchin 				sfprintf(sp, "  ");
310da2e3ebdSchin 				if (!tag || label && !strchr(tag, ':'))
311da2e3ebdSchin 					sfprintf(sp, "%s%s", lab, tag ? ":" : "");
312da2e3ebdSchin 				if (tag)
313da2e3ebdSchin 					sfprintf(sp, "%s", tag);
314da2e3ebdSchin 			}
315da2e3ebdSchin 			if (mask & (MM_class|MM_source|MM_status))
316da2e3ebdSchin 			{
317da2e3ebdSchin 				sfputc(sp, ' ');
318da2e3ebdSchin 				if ((mask & MM_source) && (m = classification & (MM_APPL|MM_UTIL|MM_OPSYS)) && (s = display(mm_class, m, 1)))
319da2e3ebdSchin 					sfprintf(sp, " %s", s);
320da2e3ebdSchin 				if ((mask & MM_class) && (m = classification & (MM_HARD|MM_SOFT|MM_FIRM)) && (s = display(mm_class, m, 1)))
321da2e3ebdSchin 					sfprintf(sp, " %s", s);
322da2e3ebdSchin 				if ((mask & MM_status) && (m = classification & (MM_RECOVER|MM_NRECOV)) && (s = display(mm_class, m, 1)))
323da2e3ebdSchin 					sfprintf(sp, " %s", s);
324da2e3ebdSchin 			}
325da2e3ebdSchin 			sfputc(sp, '\n');
326da2e3ebdSchin 		}
327da2e3ebdSchin 		n = sfstrtell(sp);
328da2e3ebdSchin 		if (!(s = sfstruse(sp)) || write(fd, s, n) != n)
329da2e3ebdSchin 			r |= c;
330da2e3ebdSchin 	}
331da2e3ebdSchin 	sfstrclose(sp);
332da2e3ebdSchin 	return r;
333da2e3ebdSchin }
334da2e3ebdSchin 
335da2e3ebdSchin #endif
336