1/* Public domain fmtmsg() 2 * Written by Isaac Dunham, 2014 3 */ 4#include <fmtmsg.h> 5#include <fcntl.h> 6#include <unistd.h> 7#include <stdio.h> 8#include <string.h> 9#include <stdlib.h> 10#include <pthread.h> 11 12/* 13 * If lstr is the first part of bstr, check that the next char in bstr 14 * is either \0 or : 15 */ 16static int _strcolcmp(const char *lstr, const char *bstr) 17{ 18 size_t i = 0; 19 while (lstr[i] && bstr[i] && (bstr[i] == lstr[i])) i++; 20 if ( lstr[i] || (bstr[i] && bstr[i] != ':')) return 1; 21 return 0; 22} 23 24int fmtmsg(long classification, const char *label, int severity, 25 const char *text, const char *action, const char *tag) 26{ 27 int ret = 0, i, consolefd, verb = 0; 28 char *errstring = MM_NULLSEV, *cmsg = getenv("MSGVERB"); 29 char *const msgs[] = { 30 "label", "severity", "text", "action", "tag", NULL 31 }; 32 int cs; 33 34 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs); 35 36 if (severity == MM_HALT) errstring = "HALT: "; 37 else if (severity == MM_ERROR) errstring = "ERROR: "; 38 else if (severity == MM_WARNING) errstring = "WARNING: "; 39 else if (severity == MM_INFO) errstring = "INFO: "; 40 41 if (classification & MM_CONSOLE) { 42 consolefd = open("/dev/console", O_WRONLY); 43 if (consolefd < 0) { 44 ret = MM_NOCON; 45 } else { 46 if (dprintf(consolefd, "%s%s%s%s%s%s%s%s\n", 47 label?label:"", label?": ":"", 48 severity?errstring:"", text?text:"", 49 action?"\nTO FIX: ":"", 50 action?action:"", action?" ":"", 51 tag?tag:"" )<1) 52 ret = MM_NOCON; 53 close(consolefd); 54 } 55 } 56 57 if (classification & MM_PRINT) { 58 while (cmsg && cmsg[0]) { 59 for(i=0; msgs[i]; i++) { 60 if (!_strcolcmp(msgs[i], cmsg)) break; 61 } 62 if (msgs[i] == NULL) { 63 //ignore MSGVERB-unrecognized component 64 verb = 0xFF; 65 break; 66 } else { 67 verb |= (1 << i); 68 cmsg = strchr(cmsg, ':'); 69 if (cmsg) cmsg++; 70 } 71 } 72 if (!verb) verb = 0xFF; 73 if (dprintf(2, "%s%s%s%s%s%s%s%s\n", 74 (verb&1 && label) ? label : "", 75 (verb&1 && label) ? ": " : "", 76 (verb&2 && severity) ? errstring : "", 77 (verb&4 && text) ? text : "", 78 (verb&8 && action) ? "\nTO FIX: " : "", 79 (verb&8 && action) ? action : "", 80 (verb&8 && action) ? " " : "", 81 (verb&16 && tag) ? tag : "" ) < 1) 82 ret |= MM_NOMSG; 83 } 84 if ((ret & (MM_NOCON|MM_NOMSG)) == (MM_NOCON|MM_NOMSG)) 85 ret = MM_NOTOK; 86 87 pthread_setcancelstate(cs, 0); 88 89 return ret; 90} 91