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