1c6ddf9d0SSascha Wildner /*-
2c6ddf9d0SSascha Wildner * Copyright (c) 2002 Mike Barcroft <mike@FreeBSD.org>
3c6ddf9d0SSascha Wildner * All rights reserved.
4c6ddf9d0SSascha Wildner *
5c6ddf9d0SSascha Wildner * Redistribution and use in source and binary forms, with or without
6c6ddf9d0SSascha Wildner * modification, are permitted provided that the following conditions
7c6ddf9d0SSascha Wildner * are met:
8c6ddf9d0SSascha Wildner * 1. Redistributions of source code must retain the above copyright
9c6ddf9d0SSascha Wildner * notice, this list of conditions and the following disclaimer.
10c6ddf9d0SSascha Wildner * 2. Redistributions in binary form must reproduce the above copyright
11c6ddf9d0SSascha Wildner * notice, this list of conditions and the following disclaimer in the
12c6ddf9d0SSascha Wildner * documentation and/or other materials provided with the distribution.
13c6ddf9d0SSascha Wildner *
14c6ddf9d0SSascha Wildner * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15c6ddf9d0SSascha Wildner * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16c6ddf9d0SSascha Wildner * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17c6ddf9d0SSascha Wildner * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18c6ddf9d0SSascha Wildner * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19c6ddf9d0SSascha Wildner * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20c6ddf9d0SSascha Wildner * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21c6ddf9d0SSascha Wildner * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22c6ddf9d0SSascha Wildner * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23c6ddf9d0SSascha Wildner * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24c6ddf9d0SSascha Wildner * SUCH DAMAGE.
25c6ddf9d0SSascha Wildner *
26*992f890cSSascha Wildner * $FreeBSD: src/lib/libc/gen/fmtmsg.c,v 1.6 2009/11/08 14:02:54 brueffer Exp $
27c6ddf9d0SSascha Wildner */
28c6ddf9d0SSascha Wildner
29c6ddf9d0SSascha Wildner #include <fmtmsg.h>
30c6ddf9d0SSascha Wildner #include <stdio.h>
31c6ddf9d0SSascha Wildner #include <stdlib.h>
32c6ddf9d0SSascha Wildner #include <string.h>
33c6ddf9d0SSascha Wildner
34c6ddf9d0SSascha Wildner /* Default value for MSGVERB. */
35c6ddf9d0SSascha Wildner #define DFLT_MSGVERB "label:severity:text:action:tag"
36c6ddf9d0SSascha Wildner
37c6ddf9d0SSascha Wildner /* Maximum valid size for a MSGVERB. */
38c6ddf9d0SSascha Wildner #define MAX_MSGVERB sizeof(DFLT_MSGVERB)
39c6ddf9d0SSascha Wildner
40c6ddf9d0SSascha Wildner static char *printfmt(char *, long, const char *, int, const char *,
41c6ddf9d0SSascha Wildner const char *, const char *);
42c6ddf9d0SSascha Wildner static char *nextcomp(const char *);
43c6ddf9d0SSascha Wildner static const char
44c6ddf9d0SSascha Wildner *sevinfo(int);
45c6ddf9d0SSascha Wildner static int validmsgverb(const char *);
46c6ddf9d0SSascha Wildner
47c6ddf9d0SSascha Wildner static const char *validlist[] = {
48c6ddf9d0SSascha Wildner "label", "severity", "text", "action", "tag", NULL
49c6ddf9d0SSascha Wildner };
50c6ddf9d0SSascha Wildner
51c6ddf9d0SSascha Wildner int
fmtmsg(long class,const char * label,int sev,const char * text,const char * action,const char * tag)52c6ddf9d0SSascha Wildner fmtmsg(long class, const char *label, int sev, const char *text,
53c6ddf9d0SSascha Wildner const char *action, const char *tag)
54c6ddf9d0SSascha Wildner {
55c6ddf9d0SSascha Wildner FILE *fp;
56c6ddf9d0SSascha Wildner char *env, *msgverb, *output;
57c6ddf9d0SSascha Wildner
58c6ddf9d0SSascha Wildner if (class & MM_PRINT) {
59c6ddf9d0SSascha Wildner if ((env = getenv("MSGVERB")) != NULL && *env != '\0' &&
60c6ddf9d0SSascha Wildner strlen(env) <= strlen(DFLT_MSGVERB)) {
61c6ddf9d0SSascha Wildner if ((msgverb = strdup(env)) == NULL)
62c6ddf9d0SSascha Wildner return (MM_NOTOK);
63c6ddf9d0SSascha Wildner else if (validmsgverb(msgverb) == 0) {
64c6ddf9d0SSascha Wildner free(msgverb);
65c6ddf9d0SSascha Wildner goto def;
66c6ddf9d0SSascha Wildner }
67c6ddf9d0SSascha Wildner } else {
68c6ddf9d0SSascha Wildner def:
69c6ddf9d0SSascha Wildner if ((msgverb = strdup(DFLT_MSGVERB)) == NULL)
70c6ddf9d0SSascha Wildner return (MM_NOTOK);
71c6ddf9d0SSascha Wildner }
72c6ddf9d0SSascha Wildner output = printfmt(msgverb, class, label, sev, text, action,
73c6ddf9d0SSascha Wildner tag);
74c6ddf9d0SSascha Wildner if (output == NULL) {
75c6ddf9d0SSascha Wildner free(msgverb);
76c6ddf9d0SSascha Wildner return (MM_NOTOK);
77c6ddf9d0SSascha Wildner }
78c6ddf9d0SSascha Wildner if (*output != '\0')
79c6ddf9d0SSascha Wildner fprintf(stderr, "%s", output);
80c6ddf9d0SSascha Wildner free(msgverb);
81c6ddf9d0SSascha Wildner free(output);
82c6ddf9d0SSascha Wildner }
83c6ddf9d0SSascha Wildner if (class & MM_CONSOLE) {
84c6ddf9d0SSascha Wildner output = printfmt(DFLT_MSGVERB, class, label, sev, text,
85c6ddf9d0SSascha Wildner action, tag);
86c6ddf9d0SSascha Wildner if (output == NULL)
87c6ddf9d0SSascha Wildner return (MM_NOCON);
88c6ddf9d0SSascha Wildner if (*output != '\0') {
89c6ddf9d0SSascha Wildner if ((fp = fopen("/dev/console", "a")) == NULL) {
90c6ddf9d0SSascha Wildner free(output);
91c6ddf9d0SSascha Wildner return (MM_NOCON);
92c6ddf9d0SSascha Wildner }
93c6ddf9d0SSascha Wildner fprintf(fp, "%s", output);
94c6ddf9d0SSascha Wildner fclose(fp);
95c6ddf9d0SSascha Wildner }
96c6ddf9d0SSascha Wildner free(output);
97c6ddf9d0SSascha Wildner }
98c6ddf9d0SSascha Wildner return (MM_OK);
99c6ddf9d0SSascha Wildner }
100c6ddf9d0SSascha Wildner
101c6ddf9d0SSascha Wildner #define INSERT_COLON \
102c6ddf9d0SSascha Wildner if (*output != '\0') \
103c6ddf9d0SSascha Wildner strlcat(output, ": ", size)
104c6ddf9d0SSascha Wildner #define INSERT_NEWLINE \
105c6ddf9d0SSascha Wildner if (*output != '\0') \
106c6ddf9d0SSascha Wildner strlcat(output, "\n", size)
107c6ddf9d0SSascha Wildner #define INSERT_SPACE \
108c6ddf9d0SSascha Wildner if (*output != '\0') \
109c6ddf9d0SSascha Wildner strlcat(output, " ", size)
110c6ddf9d0SSascha Wildner
111c6ddf9d0SSascha Wildner /*
112c6ddf9d0SSascha Wildner * Returns NULL on memory allocation failure, otherwise returns a pointer to
113c6ddf9d0SSascha Wildner * a newly malloc()'d output buffer.
114c6ddf9d0SSascha Wildner */
115c6ddf9d0SSascha Wildner static char *
printfmt(char * msgverb,long class __unused,const char * label,int sev,const char * text,const char * act,const char * tag)1166d7019e6SSascha Wildner printfmt(char *msgverb, long class __unused, const char *label, int sev,
117c6ddf9d0SSascha Wildner const char *text, const char *act, const char *tag)
118c6ddf9d0SSascha Wildner {
119c6ddf9d0SSascha Wildner size_t size;
120c6ddf9d0SSascha Wildner char *comp, *output;
121c6ddf9d0SSascha Wildner const char *sevname;
122c6ddf9d0SSascha Wildner
123c6ddf9d0SSascha Wildner size = 32;
124c6ddf9d0SSascha Wildner if (label != MM_NULLLBL)
125c6ddf9d0SSascha Wildner size += strlen(label);
126c6ddf9d0SSascha Wildner if ((sevname = sevinfo(sev)) != NULL)
127c6ddf9d0SSascha Wildner size += strlen(sevname);
128c6ddf9d0SSascha Wildner if (text != MM_NULLTXT)
129c6ddf9d0SSascha Wildner size += strlen(text);
130*992f890cSSascha Wildner if (act != MM_NULLACT)
131c6ddf9d0SSascha Wildner size += strlen(act);
132c6ddf9d0SSascha Wildner if (tag != MM_NULLTAG)
133c6ddf9d0SSascha Wildner size += strlen(tag);
134c6ddf9d0SSascha Wildner
135c6ddf9d0SSascha Wildner if ((output = malloc(size)) == NULL)
136c6ddf9d0SSascha Wildner return (NULL);
137c6ddf9d0SSascha Wildner *output = '\0';
138c6ddf9d0SSascha Wildner while ((comp = nextcomp(msgverb)) != NULL) {
139c6ddf9d0SSascha Wildner if (strcmp(comp, "label") == 0 && label != MM_NULLLBL) {
140c6ddf9d0SSascha Wildner INSERT_COLON;
141c6ddf9d0SSascha Wildner strlcat(output, label, size);
142c6ddf9d0SSascha Wildner } else if (strcmp(comp, "severity") == 0 && sevname != NULL) {
143c6ddf9d0SSascha Wildner INSERT_COLON;
144c6ddf9d0SSascha Wildner strlcat(output, sevinfo(sev), size);
145c6ddf9d0SSascha Wildner } else if (strcmp(comp, "text") == 0 && text != MM_NULLTXT) {
146c6ddf9d0SSascha Wildner INSERT_COLON;
147c6ddf9d0SSascha Wildner strlcat(output, text, size);
148c6ddf9d0SSascha Wildner } else if (strcmp(comp, "action") == 0 && act != MM_NULLACT) {
149c6ddf9d0SSascha Wildner INSERT_NEWLINE;
150c6ddf9d0SSascha Wildner strlcat(output, "TO FIX: ", size);
151c6ddf9d0SSascha Wildner strlcat(output, act, size);
152c6ddf9d0SSascha Wildner } else if (strcmp(comp, "tag") == 0 && tag != MM_NULLTAG) {
153c6ddf9d0SSascha Wildner INSERT_SPACE;
154c6ddf9d0SSascha Wildner strlcat(output, tag, size);
155c6ddf9d0SSascha Wildner }
156c6ddf9d0SSascha Wildner }
157c6ddf9d0SSascha Wildner INSERT_NEWLINE;
158c6ddf9d0SSascha Wildner return (output);
159c6ddf9d0SSascha Wildner }
160c6ddf9d0SSascha Wildner
161c6ddf9d0SSascha Wildner /*
162c6ddf9d0SSascha Wildner * Returns a component of a colon delimited string. NULL is returned to
163c6ddf9d0SSascha Wildner * indicate that there are no remaining components. This function must be
164c6ddf9d0SSascha Wildner * called until it returns NULL in order for the local state to be cleared.
165c6ddf9d0SSascha Wildner */
166c6ddf9d0SSascha Wildner static char *
nextcomp(const char * msgverb)167c6ddf9d0SSascha Wildner nextcomp(const char *msgverb)
168c6ddf9d0SSascha Wildner {
169c6ddf9d0SSascha Wildner static char lmsgverb[MAX_MSGVERB], *state;
170c6ddf9d0SSascha Wildner char *retval;
171c6ddf9d0SSascha Wildner
172c6ddf9d0SSascha Wildner if (*lmsgverb == '\0') {
173c6ddf9d0SSascha Wildner strlcpy(lmsgverb, msgverb, sizeof(lmsgverb));
174c6ddf9d0SSascha Wildner retval = strtok_r(lmsgverb, ":", &state);
175c6ddf9d0SSascha Wildner } else {
176c6ddf9d0SSascha Wildner retval = strtok_r(NULL, ":", &state);
177c6ddf9d0SSascha Wildner }
178c6ddf9d0SSascha Wildner if (retval == NULL)
179c6ddf9d0SSascha Wildner *lmsgverb = '\0';
180c6ddf9d0SSascha Wildner return (retval);
181c6ddf9d0SSascha Wildner }
182c6ddf9d0SSascha Wildner
183c6ddf9d0SSascha Wildner static const char *
sevinfo(int sev)184c6ddf9d0SSascha Wildner sevinfo(int sev)
185c6ddf9d0SSascha Wildner {
186c6ddf9d0SSascha Wildner
187c6ddf9d0SSascha Wildner switch (sev) {
188c6ddf9d0SSascha Wildner case MM_HALT:
189c6ddf9d0SSascha Wildner return ("HALT");
190c6ddf9d0SSascha Wildner case MM_ERROR:
191c6ddf9d0SSascha Wildner return ("ERROR");
192c6ddf9d0SSascha Wildner case MM_WARNING:
193c6ddf9d0SSascha Wildner return ("WARNING");
194c6ddf9d0SSascha Wildner case MM_INFO:
195c6ddf9d0SSascha Wildner return ("INFO");
196c6ddf9d0SSascha Wildner default:
197c6ddf9d0SSascha Wildner return (NULL);
198c6ddf9d0SSascha Wildner }
199c6ddf9d0SSascha Wildner }
200c6ddf9d0SSascha Wildner
201c6ddf9d0SSascha Wildner /*
202c6ddf9d0SSascha Wildner * Returns 1 if the msgverb list is valid, otherwise 0.
203c6ddf9d0SSascha Wildner */
204c6ddf9d0SSascha Wildner static int
validmsgverb(const char * msgverb)205c6ddf9d0SSascha Wildner validmsgverb(const char *msgverb)
206c6ddf9d0SSascha Wildner {
207c6ddf9d0SSascha Wildner char *msgcomp;
208c6ddf9d0SSascha Wildner int i, equality;
209c6ddf9d0SSascha Wildner
210c6ddf9d0SSascha Wildner equality = 0;
211c6ddf9d0SSascha Wildner while ((msgcomp = nextcomp(msgverb)) != NULL) {
212c6ddf9d0SSascha Wildner equality--;
213c6ddf9d0SSascha Wildner for (i = 0; validlist[i] != NULL; i++) {
214c6ddf9d0SSascha Wildner if (strcmp(msgcomp, validlist[i]) == 0)
215c6ddf9d0SSascha Wildner equality++;
216c6ddf9d0SSascha Wildner }
217c6ddf9d0SSascha Wildner }
218c6ddf9d0SSascha Wildner return (!equality);
219c6ddf9d0SSascha Wildner }
220