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