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