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