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 int 49823f68a2SMike Barcroft fmtmsg(long class, const char *label, int sev, const char *text, 50823f68a2SMike Barcroft const char *action, const char *tag) 51823f68a2SMike Barcroft { 52823f68a2SMike Barcroft FILE *fp; 53823f68a2SMike Barcroft char *env, *msgverb, *output; 54823f68a2SMike Barcroft 55823f68a2SMike Barcroft if (class & MM_PRINT) { 56823f68a2SMike Barcroft if ((env = getenv("MSGVERB")) != NULL && *env != '\0' && 57823f68a2SMike Barcroft strlen(env) <= strlen(DFLT_MSGVERB)) { 58823f68a2SMike Barcroft if ((msgverb = strdup(env)) == NULL) 59823f68a2SMike Barcroft return (MM_NOTOK); 600f1bfcd2SMike Barcroft else if (validmsgverb(msgverb) == 0) { 610f1bfcd2SMike Barcroft free(msgverb); 62823f68a2SMike Barcroft goto def; 630f1bfcd2SMike Barcroft } 64823f68a2SMike Barcroft } else { 65823f68a2SMike Barcroft def: 66823f68a2SMike Barcroft if ((msgverb = strdup(DFLT_MSGVERB)) == NULL) 67823f68a2SMike Barcroft return (MM_NOTOK); 68823f68a2SMike Barcroft } 69823f68a2SMike Barcroft output = printfmt(msgverb, class, label, sev, text, action, 70823f68a2SMike Barcroft tag); 71800563c5SMike Barcroft if (output == NULL) { 72800563c5SMike Barcroft free(msgverb); 73823f68a2SMike Barcroft return (MM_NOTOK); 74800563c5SMike Barcroft } 75823f68a2SMike Barcroft if (*output != '\0') 76823f68a2SMike Barcroft fprintf(stderr, "%s", output); 77823f68a2SMike Barcroft free(msgverb); 78823f68a2SMike Barcroft free(output); 79823f68a2SMike Barcroft } 80823f68a2SMike Barcroft if (class & MM_CONSOLE) { 81823f68a2SMike Barcroft output = printfmt(DFLT_MSGVERB, class, label, sev, text, 82823f68a2SMike Barcroft action, tag); 83823f68a2SMike Barcroft if (output == NULL) 84823f68a2SMike Barcroft return (MM_NOCON); 85823f68a2SMike Barcroft if (*output != '\0') { 86*1084b38bSJilles Tjoelker if ((fp = fopen("/dev/console", "ae")) == NULL) { 87823f68a2SMike Barcroft free(output); 88823f68a2SMike Barcroft return (MM_NOCON); 89823f68a2SMike Barcroft } 90823f68a2SMike Barcroft fprintf(fp, "%s", output); 91823f68a2SMike Barcroft fclose(fp); 92823f68a2SMike Barcroft } 93823f68a2SMike Barcroft free(output); 94823f68a2SMike Barcroft } 95823f68a2SMike Barcroft return (MM_OK); 96823f68a2SMike Barcroft } 97823f68a2SMike Barcroft 98823f68a2SMike Barcroft #define INSERT_COLON \ 99823f68a2SMike Barcroft if (*output != '\0') \ 100d0509082SJacques Vidrine strlcat(output, ": ", size) 101823f68a2SMike Barcroft #define INSERT_NEWLINE \ 102823f68a2SMike Barcroft if (*output != '\0') \ 103d0509082SJacques Vidrine strlcat(output, "\n", size) 104823f68a2SMike Barcroft #define INSERT_SPACE \ 105823f68a2SMike Barcroft if (*output != '\0') \ 106d0509082SJacques Vidrine strlcat(output, " ", size) 107823f68a2SMike Barcroft 108823f68a2SMike Barcroft /* 109823f68a2SMike Barcroft * Returns NULL on memory allocation failure, otherwise returns a pointer to 110823f68a2SMike Barcroft * a newly malloc()'d output buffer. 111823f68a2SMike Barcroft */ 112823f68a2SMike Barcroft static char * 113823f68a2SMike Barcroft printfmt(char *msgverb, long class, const char *label, int sev, 114823f68a2SMike Barcroft const char *text, const char *act, const char *tag) 115823f68a2SMike Barcroft { 116823f68a2SMike Barcroft size_t size; 117823f68a2SMike Barcroft char *comp, *output; 118823f68a2SMike Barcroft const char *sevname; 119823f68a2SMike Barcroft 120823f68a2SMike Barcroft size = 32; 121823f68a2SMike Barcroft if (label != MM_NULLLBL) 122823f68a2SMike Barcroft size += strlen(label); 123823f68a2SMike Barcroft if ((sevname = sevinfo(sev)) != NULL) 124823f68a2SMike Barcroft size += strlen(sevname); 125823f68a2SMike Barcroft if (text != MM_NULLTXT) 126823f68a2SMike Barcroft size += strlen(text); 12736ba9f40SChristian Brueffer if (act != MM_NULLACT) 128823f68a2SMike Barcroft size += strlen(act); 129823f68a2SMike Barcroft if (tag != MM_NULLTAG) 130823f68a2SMike Barcroft size += strlen(tag); 131823f68a2SMike Barcroft 132823f68a2SMike Barcroft if ((output = malloc(size)) == NULL) 133823f68a2SMike Barcroft return (NULL); 134823f68a2SMike Barcroft *output = '\0'; 135823f68a2SMike Barcroft while ((comp = nextcomp(msgverb)) != NULL) { 136823f68a2SMike Barcroft if (strcmp(comp, "label") == 0 && label != MM_NULLLBL) { 137823f68a2SMike Barcroft INSERT_COLON; 138d0509082SJacques Vidrine strlcat(output, label, size); 139823f68a2SMike Barcroft } else if (strcmp(comp, "severity") == 0 && sevname != NULL) { 140823f68a2SMike Barcroft INSERT_COLON; 141d0509082SJacques Vidrine strlcat(output, sevinfo(sev), size); 142823f68a2SMike Barcroft } else if (strcmp(comp, "text") == 0 && text != MM_NULLTXT) { 143823f68a2SMike Barcroft INSERT_COLON; 144d0509082SJacques Vidrine strlcat(output, text, size); 145823f68a2SMike Barcroft } else if (strcmp(comp, "action") == 0 && act != MM_NULLACT) { 146823f68a2SMike Barcroft INSERT_NEWLINE; 147d0509082SJacques Vidrine strlcat(output, "TO FIX: ", size); 148d0509082SJacques Vidrine strlcat(output, act, size); 149823f68a2SMike Barcroft } else if (strcmp(comp, "tag") == 0 && tag != MM_NULLTAG) { 150823f68a2SMike Barcroft INSERT_SPACE; 151d0509082SJacques Vidrine strlcat(output, tag, size); 152823f68a2SMike Barcroft } 153823f68a2SMike Barcroft } 154823f68a2SMike Barcroft INSERT_NEWLINE; 155823f68a2SMike Barcroft return (output); 156823f68a2SMike Barcroft } 157823f68a2SMike Barcroft 1580f1bfcd2SMike Barcroft /* 1590f1bfcd2SMike Barcroft * Returns a component of a colon delimited string. NULL is returned to 1600f1bfcd2SMike Barcroft * indicate that there are no remaining components. This function must be 1610f1bfcd2SMike Barcroft * called until it returns NULL in order for the local state to be cleared. 1620f1bfcd2SMike Barcroft */ 163823f68a2SMike Barcroft static char * 164823f68a2SMike Barcroft nextcomp(const char *msgverb) 165823f68a2SMike Barcroft { 166823f68a2SMike Barcroft static char lmsgverb[MAX_MSGVERB], *state; 167823f68a2SMike Barcroft char *retval; 168823f68a2SMike Barcroft 169823f68a2SMike Barcroft if (*lmsgverb == '\0') { 170d0509082SJacques Vidrine strlcpy(lmsgverb, msgverb, sizeof(lmsgverb)); 171823f68a2SMike Barcroft retval = strtok_r(lmsgverb, ":", &state); 172823f68a2SMike Barcroft } else { 173823f68a2SMike Barcroft retval = strtok_r(NULL, ":", &state); 174823f68a2SMike Barcroft } 175823f68a2SMike Barcroft if (retval == NULL) 176823f68a2SMike Barcroft *lmsgverb = '\0'; 177823f68a2SMike Barcroft return (retval); 178823f68a2SMike Barcroft } 179823f68a2SMike Barcroft 180823f68a2SMike Barcroft static const char * 181823f68a2SMike Barcroft sevinfo(int sev) 182823f68a2SMike Barcroft { 183823f68a2SMike Barcroft 184823f68a2SMike Barcroft switch (sev) { 185823f68a2SMike Barcroft case MM_HALT: 186823f68a2SMike Barcroft return ("HALT"); 187823f68a2SMike Barcroft case MM_ERROR: 188823f68a2SMike Barcroft return ("ERROR"); 189823f68a2SMike Barcroft case MM_WARNING: 190823f68a2SMike Barcroft return ("WARNING"); 191823f68a2SMike Barcroft case MM_INFO: 192823f68a2SMike Barcroft return ("INFO"); 193823f68a2SMike Barcroft default: 194823f68a2SMike Barcroft return (NULL); 195823f68a2SMike Barcroft } 196823f68a2SMike Barcroft } 197823f68a2SMike Barcroft 198823f68a2SMike Barcroft /* 199823f68a2SMike Barcroft * Returns 1 if the msgverb list is valid, otherwise 0. 200823f68a2SMike Barcroft */ 201823f68a2SMike Barcroft static int 202823f68a2SMike Barcroft validmsgverb(const char *msgverb) 203823f68a2SMike Barcroft { 2048b34578dSJilles Tjoelker const char *validlist = "label\0severity\0text\0action\0tag\0"; 205823f68a2SMike Barcroft char *msgcomp; 2068b34578dSJilles Tjoelker size_t len1, len2; 2078b34578dSJilles Tjoelker const char *p; 2088b34578dSJilles Tjoelker int equality; 209823f68a2SMike Barcroft 2100f1bfcd2SMike Barcroft equality = 0; 211823f68a2SMike Barcroft while ((msgcomp = nextcomp(msgverb)) != NULL) { 2120f1bfcd2SMike Barcroft equality--; 2138b34578dSJilles Tjoelker len1 = strlen(msgcomp); 2148b34578dSJilles Tjoelker for (p = validlist; (len2 = strlen(p)) != 0; p += len2 + 1) { 2158b34578dSJilles Tjoelker if (len1 == len2 && memcmp(msgcomp, p, len1) == 0) 2160f1bfcd2SMike Barcroft equality++; 217823f68a2SMike Barcroft } 218823f68a2SMike Barcroft } 2190f1bfcd2SMike Barcroft return (!equality); 220823f68a2SMike Barcroft } 221