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