fmtmsglib.c revision 7c2fbfb345896881c631598ee3852ce9ce33fb07
/***********************************************************************
* *
* This software is part of the ast package *
* Copyright (c) 1985-2008 AT&T Intellectual Property *
* and is licensed under the *
* Common Public License, Version 1.0 *
* by AT&T Intellectual Property *
* *
* A copy of the License is available at *
* http://www.opensource.org/licenses/cpl1.0.txt *
* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
* *
* Information and Software Systems Research *
* AT&T Research *
* Florham Park NJ *
* *
* Glenn Fowler <gsf@research.att.com> *
* David Korn <dgk@research.att.com> *
* Phong Vo <kpv@research.att.com> *
* *
***********************************************************************/
#pragma prototyped
/*
* fmtmsg implementation
*/
#include <ast.h>
#if _lib_fmtmsg
NoN(fmtmsg)
#else
#define MM_TABLES
#include <fmtmsg.h>
#define INIT_VERB 0x1
#define INIT_CONSOLE 0x2
static struct
{
int console;
unsigned int init;
unsigned int mask;
} mm;
const MM_table_t mm_class[] =
{
"null", 0, 0,
"hard", "HARDWARE", MM_HARD,
"soft", "SOFTWARE", MM_SOFT,
"firm", "FIRMWARE", MM_FIRM,
"appl", "APPLICATION", MM_APPL,
"util", "UTILITY", MM_UTIL,
"opsys", "KERNEL", MM_OPSYS,
"print", 0, MM_PRINT,
"console", 0, MM_CONSOLE,
"recov", "RECOVERABLE", MM_RECOVER,
"nrecov", "PANIC", MM_NRECOV,
0, 0, 0
};
static const MM_table_t mm_severity_init[] =
{
"nosev", 0, MM_NOSEV,
"halt", "HALT", MM_HALT,
"error", "ERROR", MM_ERROR,
"warn", "WARNING", MM_WARNING,
"info", "INFO", MM_INFO,
0, 0, 0
};
const MM_table_t mm_verb[] =
{
"all", 0, MM_all,
"action", 0, MM_action,
"class", 0, MM_class,
"default", 0, MM_default,
"label", 0, MM_label,
"severity", 0, MM_severity,
"source", 0, MM_source,
"tag", 0, MM_tag,
"text", 0, MM_text,
0, 0, 0
};
const MM_table_t*
_mm_severity(void)
{
static MM_table_t* severity;
if (!severity)
{
register char* s;
register MM_table_t* p;
register int n;
register int c;
char* e;
MM_table_t* q;
n = 0;
if ((s = getenv(MM_SEVERITY_ENV)) && *s)
{
e = s;
c = 0;
for (;;)
{
switch (*s++)
{
case 0:
break;
case ',':
if (++c > 2)
{
n = 0;
break;
}
continue;
case ':':
if (c != 2)
{
n = 0;
break;
}
c = 0;
n++;
continue;
default:
continue;
}
break;
}
if (c == 2)
n++;
else n = 0;
if (n)
{
for (p = (MM_table_t*)mm_severity_init; p->name; p++);
n += p - (MM_table_t*)mm_severity_init + 1;
if (severity = newof(0, MM_table_t, n, s - e))
{
s = (char*)severity + n * sizeof(MM_table_t);
strcpy(s, e);
p = severity;
for (q = (MM_table_t*)mm_severity_init; q->name; q++)
*p++ = *q;
p->name = s;
c = 0;
for (;;)
{
switch (*s++)
{
case 0:
break;
case ',':
switch (c++)
{
case 0:
*(s - 1) = 0;
p->value = strtol(s, NiL, 0);
break;
case 1:
p->display = s;
break;
}
continue;
case ':':
c = 0;
*(s - 1) = 0;
(++p)->name = s;
continue;
default:
continue;
}
break;
}
}
}
}
if (!severity)
severity = (MM_table_t*)mm_severity_init;
}
return (const MM_table_t*)severity;
}
static char*
display(register const MM_table_t* tab, int value, int mask)
{
while (tab->name)
{
if (value == tab->value || mask && (value & tab->value))
return (char*)tab->display;
tab++;
}
return 0;
}
int
fmtmsg(long classification, const char* label, int severity, const char* text, const char* action, const char* tag)
{
register int c;
register char* s;
register char* t;
register MM_table_t* p;
int n;
int m;
int r;
int fd;
unsigned int mask;
Sfio_t* sp;
char lab[MM_LABEL_1_MAX + MM_LABEL_2_MAX + 3];
if (!mm.init)
{
mm.init = INIT_VERB;
if (!(s = getenv(MM_VERB_ENV)))
mm.mask = MM_default;
else for (;;)
{
if (t = strchr(s, ':'))
*t = 0;
if (!(p = (MM_table_t*)strlook(mm_verb, sizeof(MM_table_t), s)))
{
mm.mask = MM_default;
if (t)
*t = ':';
break;
}
mm.mask |= p->value;
if (!t)
break;
*t++ = ':';
s = t;
}
}
if (!(classification & (MM_CONSOLE|MM_PRINT)))
return 0;
if (!(sp = sfstropen()))
return MM_NOTOK;
r = 0;
if (s = (char*)label)
{
if (t = strchr(s, ':'))
{
if ((n = t - s) > MM_LABEL_1_MAX)
n = MM_LABEL_1_MAX;
sfprintf(sp, "%*.*s:", n, n, s);
s = ++t;
if ((n = strlen(t)) > MM_LABEL_2_MAX)
n = MM_LABEL_2_MAX;
sfprintf(sp, "%*.*s", n, n, s);
}
else
{
if ((n = strlen(t)) > MM_LABEL_1_MAX)
n = MM_LABEL_1_MAX;
sfprintf(sp, "%*.*s", n, n, s);
}
if (!(s = sfstruse(sp)))
{
sfstrclose(sp);
return MM_NOTOK;
}
strcpy(lab, s);
}
for (;;)
{
if (classification & MM_CONSOLE)
{
classification &= ~MM_CONSOLE;
if (!(mm.init & INIT_CONSOLE))
mm.console = open("/dev/console", O_WRONLY|O_APPEND|O_NOCTTY);
if (mm.console < 0)
{
r |= MM_NOCON;
continue;
}
c = MM_NOCON;
fd = mm.console;
mask = MM_all;
}
else if (classification & MM_PRINT)
{
classification &= ~MM_PRINT;
c = MM_NOMSG;
fd = 2;
mask = mm.mask;
}
else break;
if ((mask & MM_label) && label)
sfprintf(sp, "%s: ", lab);
if ((mask & MM_severity) && (s = display(mm_severity, severity, 0)))
sfprintf(sp, "%s: ", s);
n = sfstrtell(sp);
if ((mask & MM_text) && text)
sfprintf(sp, "%s\n", text);
else sfputc(sp, '\n');
if ((mask & MM_action) && action || (mask & MM_tag) && (label || tag))
{
if (fd != mm.console && (n -= 8) > 0)
sfprintf(sp, "%*.*s", n, n, "");
sfprintf(sp, "TO FIX:");
if ((mask & MM_action) && action)
sfprintf(sp, " %s", action);
if ((mask & MM_tag) && (label || tag))
{
sfprintf(sp, " ");
if (!tag || label && !strchr(tag, ':'))
sfprintf(sp, "%s%s", lab, tag ? ":" : "");
if (tag)
sfprintf(sp, "%s", tag);
}
if (mask & (MM_class|MM_source|MM_status))
{
sfputc(sp, ' ');
if ((mask & MM_source) && (m = classification & (MM_APPL|MM_UTIL|MM_OPSYS)) && (s = display(mm_class, m, 1)))
sfprintf(sp, " %s", s);
if ((mask & MM_class) && (m = classification & (MM_HARD|MM_SOFT|MM_FIRM)) && (s = display(mm_class, m, 1)))
sfprintf(sp, " %s", s);
if ((mask & MM_status) && (m = classification & (MM_RECOVER|MM_NRECOV)) && (s = display(mm_class, m, 1)))
sfprintf(sp, " %s", s);
}
sfputc(sp, '\n');
}
n = sfstrtell(sp);
if (!(s = sfstruse(sp)) || write(fd, s, n) != n)
r |= c;
}
sfstrclose(sp);
return r;
}
#endif