1 /* $NetBSD: fmtmsg.c,v 1.3 2002/11/11 06:31:14 thorpej 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.3 2002/11/11 06:31:14 thorpej Exp $");
35 #endif /* LIBC_SCCS and not lint */
43 static unsigned int msgverb
__P((const char *));
44 static const char * severity2str
__P((int));
45 static int writeit
__P((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
87 while (*str
!= '\0') {
88 for (i
= 0; i
< nkeywords
; i
++) {
89 if (memcmp(str
, keywords
[i
].keyword
, keywords
[i
].len
)
91 (*(str
+ keywords
[i
].len
) == ':' ||
92 *(str
+ keywords
[i
].len
) == '\0'))
101 if (*(str
+= keywords
[i
].len
) == ':')
110 static const char * const severities
[] = {
118 static const size_t nseverities
= sizeof (severities
) / sizeof (severities
[0]);
121 * Returns the string representation associated with the numerical severity
122 * value, defaulting to NULL for an unknown value.
125 severity2str(severity
)
131 (u_int
) severity
< nseverities
)
132 result
= severities
[severity
];
140 * Format and write the message to the given stream, selecting those
141 * components displayed from msgverb, returning the number of characters
142 * written, or a negative value in case of an error.
145 writeit(stream
, which
, label
, sevstr
, text
, action
, tag
)
156 nwritten
= fprintf(stream
, "%s%s%s%s%s%s%s%s%s%s%s",
157 ((which
& MM_VERBLABEL
) && label
!= MM_NULLLBL
) ?
159 ((which
& MM_VERBLABEL
) && label
!= MM_NULLLBL
) ?
161 (which
& MM_VERBSEVERITY
) ?
163 (which
& MM_VERBSEVERITY
) ?
165 ((which
& MM_VERBTEXT
) && text
!= MM_NULLTXT
) ?
167 ((which
& MM_VERBLABEL
) && label
!= MM_NULLLBL
) ||
168 ((which
& MM_VERBSEVERITY
)) ||
169 ((which
& MM_VERBTEXT
) && text
!= MM_NULLTXT
) ?
171 ((which
& MM_VERBACTION
) && action
!= MM_NULLACT
) ?
173 ((which
& MM_VERBACTION
) && action
!= MM_NULLACT
) ?
175 ((which
& MM_VERBACTION
) && label
!= MM_NULLACT
) ?
177 ((which
& MM_VERBTAG
) && tag
!= MM_NULLTAG
) ?
179 ((which
& MM_VERBACTION
) && action
!= MM_NULLACT
) ||
180 ((which
& MM_VERBTAG
) && tag
!= MM_NULLTAG
) ?
187 fmtmsg(classification
, label
, severity
, text
, action
, tag
)
196 const char *p
, *sevstr
;
199 /* Validate label constraints, if not null. */
200 if (label
!= MM_NULLLBL
) {
202 * Two fields, separated by a colon. The first field is up to
203 * 10 bytes, the second is up to 14 bytes.
205 p
= strchr(label
, ':');
206 if (p
== NULL
|| p
- label
> 10 || strlen(p
+ 1) > 14)
209 /* Validate severity argument. */
210 if ((sevstr
= severity2str(severity
)) == NULL
)
214 * Fact in search for a better place: XSH5 does not define any
215 * functionality for `classification' bits other than the display
221 if (classification
& MM_PRINT
) {
222 if (writeit(stderr
, msgverb(getenv("MSGVERB")),
223 label
, sevstr
, text
, action
, tag
) < 0)
226 /* Similar to MM_PRINT but ignoring $MSGVERB. */
227 if (classification
& MM_CONSOLE
) {
228 if ((console
= fopen(_PATH_CONSOLE
, "w")) != NULL
) {
229 if (writeit(console
, MM_VERBALL
,
230 label
, sevstr
, text
, action
, tag
) < 0)
233 * Ignore result: does not constitute ``generate a
236 (void)fclose(console
);
242 if (result
== (MM_NOMSG
| MM_NOCON
))
245 return (result
== 0 ? MM_OK
: result
);