1 /* $NetBSD: fmtmsg.c,v 1.5 2012/03/20 16:36:05 matt Exp $ */
4 * Copyright (c) 1999 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
32 #include <sys/cdefs.h>
33 #if defined(LIBC_SCCS) && !defined(lint)
34 __RCSID("$NetBSD: fmtmsg.c,v 1.5 2012/03/20 16:36:05 matt Exp $");
35 #endif /* LIBC_SCCS and not lint */
43 static unsigned int msgverb(const char *);
44 static const char * severity2str(int);
45 static int writeit(FILE *, unsigned int, const char *,
46 const char *, const char *, const char *,
49 #define MM_VERBLABEL 0x01U
50 #define MM_VERBSEVERITY 0x02U
51 #define MM_VERBTEXT 0x04U
52 #define MM_VERBACTION 0x08U
53 #define MM_VERBTAG 0x10U
55 (MM_VERBLABEL | MM_VERBSEVERITY | MM_VERBTEXT | MM_VERBACTION | \
58 static const struct keyword
{
59 size_t len
; /* strlen(keyword) */
60 const char * const keyword
;
62 { 5, "label" }, /* log2(MM_VERBLABEL) */
63 { 8, "severity" }, /* ... */
66 { 3, "tag" } /* log2(MM_VERBTAG) */
69 static const size_t nkeywords
= sizeof (keywords
) / sizeof (keywords
[0]);
72 * Convert a colon-separated list of known keywords to a set of MM_VERB*
73 * flags, defaulting to `all' if not set, empty, or in presence of unknown
77 msgverb(const char *str
)
86 while (*str
!= '\0') {
87 for (i
= 0; i
< nkeywords
; i
++) {
88 if (memcmp(str
, keywords
[i
].keyword
, keywords
[i
].len
)
90 (*(str
+ keywords
[i
].len
) == ':' ||
91 *(str
+ keywords
[i
].len
) == '\0'))
100 if (*(str
+= keywords
[i
].len
) == ':')
109 static const char severities
[][8] = {
117 static const size_t nseverities
= sizeof (severities
) / sizeof (severities
[0]);
120 * Returns the string representation associated with the numerical severity
121 * value, defaulting to NULL for an unknown value.
124 severity2str(int severity
)
129 (u_int
) severity
< nseverities
)
130 result
= severities
[severity
];
138 * Format and write the message to the given stream, selecting those
139 * components displayed from msgverb, returning the number of characters
140 * written, or a negative value in case of an error.
143 writeit(FILE *stream
, unsigned int which
, const char *label
,
144 const char *sevstr
, const char *text
, const char *action
,
149 nwritten
= fprintf(stream
, "%s%s%s%s%s%s%s%s%s%s%s",
150 ((which
& MM_VERBLABEL
) && label
!= MM_NULLLBL
) ?
152 ((which
& MM_VERBLABEL
) && label
!= MM_NULLLBL
) ?
154 (which
& MM_VERBSEVERITY
) ?
156 (which
& MM_VERBSEVERITY
) ?
158 ((which
& MM_VERBTEXT
) && text
!= MM_NULLTXT
) ?
160 ((which
& MM_VERBLABEL
) && label
!= MM_NULLLBL
) ||
161 ((which
& MM_VERBSEVERITY
)) ||
162 ((which
& MM_VERBTEXT
) && text
!= MM_NULLTXT
) ?
164 ((which
& MM_VERBACTION
) && action
!= MM_NULLACT
) ?
166 ((which
& MM_VERBACTION
) && action
!= MM_NULLACT
) ?
168 ((which
& MM_VERBACTION
) && label
!= MM_NULLACT
) ?
170 ((which
& MM_VERBTAG
) && tag
!= MM_NULLTAG
) ?
172 ((which
& MM_VERBACTION
) && action
!= MM_NULLACT
) ||
173 ((which
& MM_VERBTAG
) && tag
!= MM_NULLTAG
) ?
180 fmtmsg(long classification
, const char *label
, int severity
,
181 const char *text
, const char *action
, const char *tag
)
184 const char *p
, *sevstr
;
187 /* Validate label constraints, if not null. */
188 if (label
!= MM_NULLLBL
) {
190 * Two fields, separated by a colon. The first field is up to
191 * 10 bytes, the second is up to 14 bytes.
193 p
= strchr(label
, ':');
194 if (p
== NULL
|| p
- label
> 10 || strlen(p
+ 1) > 14)
197 /* Validate severity argument. */
198 if ((sevstr
= severity2str(severity
)) == NULL
)
202 * Fact in search for a better place: XSH5 does not define any
203 * functionality for `classification' bits other than the display
209 if (classification
& MM_PRINT
) {
210 if (writeit(stderr
, msgverb(getenv("MSGVERB")),
211 label
, sevstr
, text
, action
, tag
) < 0)
214 /* Similar to MM_PRINT but ignoring $MSGVERB. */
215 if (classification
& MM_CONSOLE
) {
216 if ((console
= fopen(_PATH_CONSOLE
, "w")) != NULL
) {
217 if (writeit(console
, MM_VERBALL
,
218 label
, sevstr
, text
, action
, tag
) < 0)
221 * Ignore result: does not constitute ``generate a
224 (void)fclose(console
);
230 if (result
== (MM_NOMSG
| MM_NOCON
))
233 return (result
== 0 ? MM_OK
: result
);