1823f68a2SMike Barcroft /*- 2823f68a2SMike Barcroft * Copyright (c) 2002 Mike Barcroft <mike@FreeBSD.org> 3823f68a2SMike Barcroft * All rights reserved. 4823f68a2SMike Barcroft * 5823f68a2SMike Barcroft * Redistribution and use in source and binary forms, with or without 6823f68a2SMike Barcroft * modification, are permitted provided that the following conditions 7823f68a2SMike Barcroft * are met: 8823f68a2SMike Barcroft * 1. Redistributions of source code must retain the above copyright 9823f68a2SMike Barcroft * notice, this list of conditions and the following disclaimer. 10823f68a2SMike Barcroft * 2. Redistributions in binary form must reproduce the above copyright 11823f68a2SMike Barcroft * notice, this list of conditions and the following disclaimer in the 12823f68a2SMike Barcroft * documentation and/or other materials provided with the distribution. 13823f68a2SMike Barcroft * 14823f68a2SMike Barcroft * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15823f68a2SMike Barcroft * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16823f68a2SMike Barcroft * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17823f68a2SMike Barcroft * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18823f68a2SMike Barcroft * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19823f68a2SMike Barcroft * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20823f68a2SMike Barcroft * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21823f68a2SMike Barcroft * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22823f68a2SMike Barcroft * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23823f68a2SMike Barcroft * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24823f68a2SMike Barcroft * SUCH DAMAGE. 25823f68a2SMike Barcroft */ 26823f68a2SMike Barcroft 27823f68a2SMike Barcroft #include <sys/cdefs.h> 28823f68a2SMike Barcroft __FBSDID("$FreeBSD$"); 29823f68a2SMike Barcroft 30823f68a2SMike Barcroft #include <fmtmsg.h> 31823f68a2SMike Barcroft #include <stdio.h> 32823f68a2SMike Barcroft #include <stdlib.h> 33823f68a2SMike Barcroft #include <string.h> 34823f68a2SMike Barcroft 35823f68a2SMike Barcroft /* Default value for MSGVERB. */ 36823f68a2SMike Barcroft #define DFLT_MSGVERB "label:severity:text:action:tag" 37823f68a2SMike Barcroft 38823f68a2SMike Barcroft /* Maximum valid size for a MSGVERB. */ 39823f68a2SMike Barcroft #define MAX_MSGVERB sizeof(DFLT_MSGVERB) 40823f68a2SMike Barcroft 41823f68a2SMike Barcroft static char *printfmt(char *, long, const char *, int, const char *, 42823f68a2SMike Barcroft const char *, const char *); 43823f68a2SMike Barcroft static char *nextcomp(const char *); 44823f68a2SMike Barcroft static const char 45823f68a2SMike Barcroft *sevinfo(int); 46823f68a2SMike Barcroft static int validmsgverb(const char *); 47823f68a2SMike Barcroft 48823f68a2SMike Barcroft static const char *validlist[] = { 49823f68a2SMike Barcroft "label", "severity", "text", "action", "tag", NULL 50823f68a2SMike Barcroft }; 51823f68a2SMike Barcroft 52823f68a2SMike Barcroft int 53823f68a2SMike Barcroft fmtmsg(long class, const char *label, int sev, const char *text, 54823f68a2SMike Barcroft const char *action, const char *tag) 55823f68a2SMike Barcroft { 56823f68a2SMike Barcroft FILE *fp; 57823f68a2SMike Barcroft char *env, *msgverb, *output; 58823f68a2SMike Barcroft 59823f68a2SMike Barcroft if (class & MM_PRINT) { 60823f68a2SMike Barcroft if ((env = getenv("MSGVERB")) != NULL && *env != '\0' && 61823f68a2SMike Barcroft strlen(env) <= strlen(DFLT_MSGVERB)) { 62823f68a2SMike Barcroft if ((msgverb = strdup(env)) == NULL) 63823f68a2SMike Barcroft return (MM_NOTOK); 640f1bfcd2SMike Barcroft else if (validmsgverb(msgverb) == 0) { 650f1bfcd2SMike Barcroft free(msgverb); 66823f68a2SMike Barcroft goto def; 670f1bfcd2SMike Barcroft } 68823f68a2SMike Barcroft } else { 69823f68a2SMike Barcroft def: 70823f68a2SMike Barcroft if ((msgverb = strdup(DFLT_MSGVERB)) == NULL) 71823f68a2SMike Barcroft return (MM_NOTOK); 72823f68a2SMike Barcroft } 73823f68a2SMike Barcroft output = printfmt(msgverb, class, label, sev, text, action, 74823f68a2SMike Barcroft tag); 75800563c5SMike Barcroft if (output == NULL) { 76800563c5SMike Barcroft free(msgverb); 77823f68a2SMike Barcroft return (MM_NOTOK); 78800563c5SMike Barcroft } 79823f68a2SMike Barcroft if (*output != '\0') 80823f68a2SMike Barcroft fprintf(stderr, "%s", output); 81823f68a2SMike Barcroft free(msgverb); 82823f68a2SMike Barcroft free(output); 83823f68a2SMike Barcroft } 84823f68a2SMike Barcroft if (class & MM_CONSOLE) { 85823f68a2SMike Barcroft output = printfmt(DFLT_MSGVERB, class, label, sev, text, 86823f68a2SMike Barcroft action, tag); 87823f68a2SMike Barcroft if (output == NULL) 88823f68a2SMike Barcroft return (MM_NOCON); 89823f68a2SMike Barcroft if (*output != '\0') { 90823f68a2SMike Barcroft if ((fp = fopen("/dev/console", "a")) == NULL) { 91823f68a2SMike Barcroft free(output); 92823f68a2SMike Barcroft return (MM_NOCON); 93823f68a2SMike Barcroft } 94823f68a2SMike Barcroft fprintf(fp, "%s", output); 95823f68a2SMike Barcroft fclose(fp); 96823f68a2SMike Barcroft } 97823f68a2SMike Barcroft free(output); 98823f68a2SMike Barcroft } 99823f68a2SMike Barcroft return (MM_OK); 100823f68a2SMike Barcroft } 101823f68a2SMike Barcroft 102823f68a2SMike Barcroft #define INSERT_COLON \ 103823f68a2SMike Barcroft if (*output != '\0') \ 104d0509082SJacques Vidrine strlcat(output, ": ", size) 105823f68a2SMike Barcroft #define INSERT_NEWLINE \ 106823f68a2SMike Barcroft if (*output != '\0') \ 107d0509082SJacques Vidrine strlcat(output, "\n", size) 108823f68a2SMike Barcroft #define INSERT_SPACE \ 109823f68a2SMike Barcroft if (*output != '\0') \ 110d0509082SJacques Vidrine strlcat(output, " ", size) 111823f68a2SMike Barcroft 112823f68a2SMike Barcroft /* 113823f68a2SMike Barcroft * Returns NULL on memory allocation failure, otherwise returns a pointer to 114823f68a2SMike Barcroft * a newly malloc()'d output buffer. 115823f68a2SMike Barcroft */ 116823f68a2SMike Barcroft static char * 117823f68a2SMike Barcroft printfmt(char *msgverb, long class, const char *label, int sev, 118823f68a2SMike Barcroft const char *text, const char *act, const char *tag) 119823f68a2SMike Barcroft { 120823f68a2SMike Barcroft size_t size; 121823f68a2SMike Barcroft char *comp, *output; 122823f68a2SMike Barcroft const char *sevname; 123823f68a2SMike Barcroft 124823f68a2SMike Barcroft size = 32; 125823f68a2SMike Barcroft if (label != MM_NULLLBL) 126823f68a2SMike Barcroft size += strlen(label); 127823f68a2SMike Barcroft if ((sevname = sevinfo(sev)) != NULL) 128823f68a2SMike Barcroft size += strlen(sevname); 129823f68a2SMike Barcroft if (text != MM_NULLTXT) 130823f68a2SMike Barcroft size += strlen(text); 13136ba9f40SChristian Brueffer if (act != MM_NULLACT) 132823f68a2SMike Barcroft size += strlen(act); 133823f68a2SMike Barcroft if (tag != MM_NULLTAG) 134823f68a2SMike Barcroft size += strlen(tag); 135823f68a2SMike Barcroft 136823f68a2SMike Barcroft if ((output = malloc(size)) == NULL) 137823f68a2SMike Barcroft return (NULL); 138823f68a2SMike Barcroft *output = '\0'; 139823f68a2SMike Barcroft while ((comp = nextcomp(msgverb)) != NULL) { 140823f68a2SMike Barcroft if (strcmp(comp, "label") == 0 && label != MM_NULLLBL) { 141823f68a2SMike Barcroft INSERT_COLON; 142d0509082SJacques Vidrine strlcat(output, label, size); 143823f68a2SMike Barcroft } else if (strcmp(comp, "severity") == 0 && sevname != NULL) { 144823f68a2SMike Barcroft INSERT_COLON; 145d0509082SJacques Vidrine strlcat(output, sevinfo(sev), size); 146823f68a2SMike Barcroft } else if (strcmp(comp, "text") == 0 && text != MM_NULLTXT) { 147823f68a2SMike Barcroft INSERT_COLON; 148d0509082SJacques Vidrine strlcat(output, text, size); 149823f68a2SMike Barcroft } else if (strcmp(comp, "action") == 0 && act != MM_NULLACT) { 150823f68a2SMike Barcroft INSERT_NEWLINE; 151d0509082SJacques Vidrine strlcat(output, "TO FIX: ", size); 152d0509082SJacques Vidrine strlcat(output, act, size); 153823f68a2SMike Barcroft } else if (strcmp(comp, "tag") == 0 && tag != MM_NULLTAG) { 154823f68a2SMike Barcroft INSERT_SPACE; 155d0509082SJacques Vidrine strlcat(output, tag, size); 156823f68a2SMike Barcroft } 157823f68a2SMike Barcroft } 158823f68a2SMike Barcroft INSERT_NEWLINE; 159823f68a2SMike Barcroft return (output); 160823f68a2SMike Barcroft } 161823f68a2SMike Barcroft 1620f1bfcd2SMike Barcroft /* 1630f1bfcd2SMike Barcroft * Returns a component of a colon delimited string. NULL is returned to 1640f1bfcd2SMike Barcroft * indicate that there are no remaining components. This function must be 1650f1bfcd2SMike Barcroft * called until it returns NULL in order for the local state to be cleared. 1660f1bfcd2SMike Barcroft */ 167823f68a2SMike Barcroft static char * 168823f68a2SMike Barcroft nextcomp(const char *msgverb) 169823f68a2SMike Barcroft { 170823f68a2SMike Barcroft static char lmsgverb[MAX_MSGVERB], *state; 171823f68a2SMike Barcroft char *retval; 172823f68a2SMike Barcroft 173823f68a2SMike Barcroft if (*lmsgverb == '\0') { 174d0509082SJacques Vidrine strlcpy(lmsgverb, msgverb, sizeof(lmsgverb)); 175823f68a2SMike Barcroft retval = strtok_r(lmsgverb, ":", &state); 176823f68a2SMike Barcroft } else { 177823f68a2SMike Barcroft retval = strtok_r(NULL, ":", &state); 178823f68a2SMike Barcroft } 179823f68a2SMike Barcroft if (retval == NULL) 180823f68a2SMike Barcroft *lmsgverb = '\0'; 181823f68a2SMike Barcroft return (retval); 182823f68a2SMike Barcroft } 183823f68a2SMike Barcroft 184823f68a2SMike Barcroft static const char * 185823f68a2SMike Barcroft sevinfo(int sev) 186823f68a2SMike Barcroft { 187823f68a2SMike Barcroft 188823f68a2SMike Barcroft switch (sev) { 189823f68a2SMike Barcroft case MM_HALT: 190823f68a2SMike Barcroft return ("HALT"); 191823f68a2SMike Barcroft case MM_ERROR: 192823f68a2SMike Barcroft return ("ERROR"); 193823f68a2SMike Barcroft case MM_WARNING: 194823f68a2SMike Barcroft return ("WARNING"); 195823f68a2SMike Barcroft case MM_INFO: 196823f68a2SMike Barcroft return ("INFO"); 197823f68a2SMike Barcroft default: 198823f68a2SMike Barcroft return (NULL); 199823f68a2SMike Barcroft } 200823f68a2SMike Barcroft } 201823f68a2SMike Barcroft 202823f68a2SMike Barcroft /* 203823f68a2SMike Barcroft * Returns 1 if the msgverb list is valid, otherwise 0. 204823f68a2SMike Barcroft */ 205823f68a2SMike Barcroft static int 206823f68a2SMike Barcroft validmsgverb(const char *msgverb) 207823f68a2SMike Barcroft { 208823f68a2SMike Barcroft char *msgcomp; 2090f1bfcd2SMike Barcroft int i, equality; 210823f68a2SMike Barcroft 2110f1bfcd2SMike Barcroft equality = 0; 212823f68a2SMike Barcroft while ((msgcomp = nextcomp(msgverb)) != NULL) { 2130f1bfcd2SMike Barcroft equality--; 2140f1bfcd2SMike Barcroft for (i = 0; validlist[i] != NULL; i++) { 2150f1bfcd2SMike Barcroft if (strcmp(msgcomp, validlist[i]) == 0) 2160f1bfcd2SMike Barcroft equality++; 217823f68a2SMike Barcroft } 218823f68a2SMike Barcroft } 2190f1bfcd2SMike Barcroft return (!equality); 220823f68a2SMike Barcroft } 221