]>
git.saurik.com Git - apple/libc.git/blob - gen/fmtmsg-fbsd.c
2 * Copyright (c) 2002 Mike Barcroft <mike@FreeBSD.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD: src/lib/libc/gen/fmtmsg.c,v 1.5 2003/05/01 19:03:13 nectar Exp $");
34 #include <sys/types.h>
37 /* Default value for MSGVERB. */
38 #define DFLT_MSGVERB "label:severity:text:action:tag"
40 /* Maximum valid size for a MSGVERB. */
41 #define MAX_MSGVERB sizeof(DFLT_MSGVERB)
43 static char *printfmt(char *, long, const char *, int, const char *,
44 const char *, const char *);
45 static char *nextcomp(const char *);
48 static int validmsgverb(const char *);
50 static const char *validlist
[] = {
51 "label", "severity", "text", "action", "tag", NULL
55 fmtmsg(long class, const char *label
, int sev
, const char *text
,
56 const char *action
, const char *tag
)
59 char *env
, *msgverb
, *output
;
62 if (action
== NULL
) action
= "";
64 if (class & MM_PRINT
) {
65 if ((env
= getenv("MSGVERB")) != NULL
&& *env
!= '\0' &&
66 strlen(env
) <= strlen(DFLT_MSGVERB
)) {
67 if ((msgverb
= strdup(env
)) == NULL
)
69 else if (validmsgverb(msgverb
) == 0) {
75 if ((msgverb
= strdup(DFLT_MSGVERB
)) == NULL
)
78 output
= printfmt(msgverb
, class, label
, sev
, text
, action
,
84 if (*output
!= '\0') {
85 int out_len
= fprintf(stderr
, "%s", output
);
93 if (class & MM_CONSOLE
) {
94 output
= printfmt(DFLT_MSGVERB
, class, label
, sev
, text
,
98 if (*output
!= '\0') {
118 // DO NOT INTEGRATE THIS CHANGE
120 // Integrating it means DEATH.
121 // (see Revelation 6:8 for full details)
123 XXX this is a *huge* kludge to pass the SuSv3 tests,
124 I don't think of it as cheating because they are
125 looking in the wrong place (/realdev/console) to do
126 their testing, but they can't look in the "right"
127 place for various reasons */
128 char *cpath
= "/dev/console";
130 int rc
= stat("/realdev/console", &sb
);
131 if (rc
== 0 && (sb
.st_mode
& S_IFDIR
)) {
132 cpath
= "/realdev/console";
134 /* XXX thus ends the kludge - changes after
135 this point may be safely integrated */
137 if ((fp
= fopen(cpath
, "a")) == NULL
) {
144 fprintf(fp
, "%s", output
);
153 #define INSERT_COLON \
154 if (*output != '\0') \
155 strlcat(output, ": ", size)
156 #define INSERT_NEWLINE \
157 if (*output != '\0') \
158 strlcat(output, "\n", size)
159 #define INSERT_SPACE \
160 if (*output != '\0') \
161 strlcat(output, " ", size)
164 * Returns NULL on memory allocation failure, otherwise returns a pointer to
165 * a newly malloc()'d output buffer.
168 printfmt(char *msgverb
, long class, const char *label
, int sev
,
169 const char *text
, const char *act
, const char *tag
)
176 if (label
!= MM_NULLLBL
)
177 size
+= strlen(label
);
178 if ((sevname
= sevinfo(sev
)) != NULL
)
179 size
+= strlen(sevname
);
180 if (text
!= MM_NULLTXT
)
181 size
+= strlen(text
);
182 if (text
!= MM_NULLACT
)
184 if (tag
!= MM_NULLTAG
)
187 if ((output
= malloc(size
)) == NULL
)
190 while ((comp
= nextcomp(msgverb
)) != NULL
) {
191 if (strcmp(comp
, "label") == 0 && label
!= MM_NULLLBL
) {
193 strlcat(output
, label
, size
);
194 } else if (strcmp(comp
, "severity") == 0 && sevname
!= NULL
) {
196 strlcat(output
, sevinfo(sev
), size
);
197 } else if (strcmp(comp
, "text") == 0 && text
!= MM_NULLTXT
) {
199 strlcat(output
, text
, size
);
200 } else if (strcmp(comp
, "action") == 0 && act
!= MM_NULLACT
) {
202 strlcat(output
, "TO FIX: ", size
);
203 strlcat(output
, act
, size
);
204 } else if (strcmp(comp
, "tag") == 0 && tag
!= MM_NULLTAG
) {
206 strlcat(output
, tag
, size
);
214 * Returns a component of a colon delimited string. NULL is returned to
215 * indicate that there are no remaining components. This function must be
216 * called until it returns NULL in order for the local state to be cleared.
219 nextcomp(const char *msgverb
)
221 static char lmsgverb
[MAX_MSGVERB
], *state
;
224 if (*lmsgverb
== '\0') {
225 strlcpy(lmsgverb
, msgverb
, sizeof(lmsgverb
));
226 retval
= strtok_r(lmsgverb
, ":", &state
);
228 retval
= strtok_r(NULL
, ":", &state
);
254 * Returns 1 if the msgverb list is valid, otherwise 0.
257 validmsgverb(const char *msgverb
)
263 while ((msgcomp
= nextcomp(msgverb
)) != NULL
) {
265 for (i
= 0; validlist
[i
] != NULL
; i
++) {
266 if (strcmp(msgcomp
, validlist
[i
]) == 0)