1 /*----------------------------------------------------------------------------*/
2 /* Xymon monitor library.                                                     */
3 /*                                                                            */
4 /* This is a library module, part of libxymon.                                */
5 /* It contains routines for error- and debug-message display.                 */
6 /*                                                                            */
7 /* Copyright (C) 2002-2011 Henrik Storner <henrik@storner.dk>                 */
8 /*                                                                            */
9 /* This program is released under the GNU General Public License (GPL),       */
10 /* version 2. See the file "COPYING" for details.                             */
11 /*                                                                            */
12 /*----------------------------------------------------------------------------*/
13 
14 static char rcsid[] = "$Id: errormsg.c 8069 2019-07-23 15:29:06Z jccleaver $";
15 
16 #include <sys/types.h>
17 #include <string.h>
18 #include <sys/time.h>
19 #include <time.h>
20 #include <stdarg.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <unistd.h>
24 #include <limits.h>
25 #include <errno.h>
26 
27 #include "libxymon.h"
28 
29 SBUF_DEFINE(errbuf);
30 static char msg[4096];
31 static char timestr[20];
32 static size_t timesize = sizeof(timestr);
33 static struct timeval now;
34 static time_t then = 0;
35 int save_errbuf = 1;
36 static char *errappname = NULL;
37 
38 int debug = 0;
39 static FILE *tracefd = NULL;
40 static FILE *debugfd = NULL;
41 
errprintf(const char * fmt,...)42 void errprintf(const char *fmt, ...)
43 {
44 	va_list args;
45 	gettimeofday(&now, NULL);
46 
47 	if (now.tv_sec != then) {
48 		strftime(timestr, timesize, "%Y-%m-%d %H:%M:%S", localtime(&now.tv_sec));
49 		then = now.tv_sec;
50 	}
51 	fprintf(stderr, "%s.%06d ", timestr, (int) now.tv_usec);
52 	if (errappname) fprintf(stderr, "%s ", errappname);
53 
54 	va_start(args, fmt);
55 	vsnprintf(msg, sizeof(msg), fmt, args);
56 	va_end(args);
57 
58 	fprintf(stderr, "%s", msg);
59 	fflush(stderr);
60 
61 	if (save_errbuf) {
62 		if (errbuf == NULL) {
63 			SBUF_MALLOC(errbuf, 8192);
64 			*errbuf = '\0';
65 		}
66 		else if ((strlen(errbuf) + strlen(msg)) > errbuf_buflen) {
67 			SBUF_REALLOC(errbuf, errbuf_buflen+8192);
68 		}
69 
70 		strncat(errbuf, msg, (errbuf_buflen - strlen(errbuf)));
71 	}
72 }
73 
74 
real_dbgprintf(const char * fmt,...)75 void real_dbgprintf(const char *fmt, ...)
76 {
77 	va_list args;
78 	gettimeofday(&now, NULL);
79 
80 	if (!debugfd) debugfd = stdout;
81 	if (now.tv_sec != then) {
82 		strftime(timestr, timesize, "%Y-%m-%d %H:%M:%S", localtime(&now.tv_sec));
83 		then = now.tv_sec;
84 	}
85 
86 	fprintf(debugfd, "%lu %s.%06d ", (unsigned long)getpid(), timestr, (int) now.tv_usec);
87 
88 	va_start(args, fmt);
89 	vfprintf(debugfd, fmt, args);
90 	va_end(args);
91 	fflush(debugfd);
92 }
93 
flush_errbuf(void)94 void flush_errbuf(void)
95 {
96 	if (errbuf) xfree(errbuf);
97 	errbuf = NULL;
98 }
99 
100 
set_debugfile(char * fn,int appendtofile)101 void set_debugfile(char *fn, int appendtofile)
102 {
103 	/* Always close and reopen when re-setting */
104 	if (debugfd && (debugfd != stdout) && (debugfd != stderr)) fclose(debugfd);
105 
106 	if (fn) {
107 		if (strcasecmp(fn, "stderr") == 0) debugfd = stderr;
108 		else if (strcasecmp(fn, "stdout") == 0) debugfd = stdout;
109 		else {
110 			debugfd = fopen(fn, (appendtofile ? "a" : "w"));
111 			if (debugfd == NULL) errprintf("Cannot open debug log '%s': %s\n", fn, strerror(errno));
112 		}
113 	}
114 
115 	if (!debugfd) debugfd = stdout;
116 }
117 
118 
starttrace(const char * fn)119 void starttrace(const char *fn)
120 {
121 	if (tracefd) fclose(tracefd);
122 	if (fn) {
123 		tracefd = fopen(fn, "a");
124 		if (tracefd == NULL) errprintf("Cannot open tracefile %s\n", fn);
125 	}
126 	else tracefd = stdout;
127 }
128 
stoptrace(void)129 void stoptrace(void)
130 {
131 	if (tracefd) fclose(tracefd);
132 	tracefd = NULL;
133 }
134 
traceprintf(const char * fmt,...)135 void traceprintf(const char *fmt, ...)
136 {
137 	va_list args;
138 
139 	if (tracefd) {
140 		char timestr[40];
141 		time_t now = getcurrenttime(NULL);
142 
143 		MEMDEFINE(timestr);
144 
145 		strftime(timestr, sizeof(timestr), "%Y-%m-%d %H:%M:%S", localtime(&now));
146 		fprintf(tracefd, "%08lu %s ", (unsigned long)getpid(), timestr);
147 
148 		va_start(args, fmt);
149 		vfprintf(tracefd, fmt, args);
150 		va_end(args);
151 		fflush(tracefd);
152 
153 		MEMUNDEFINE(timestr);
154 	}
155 }
156 
reopen_file(char * fn,char * mode,FILE * fd)157 void reopen_file(char *fn, char *mode, FILE *fd)
158 {
159 	FILE *testfd;
160 
161 	testfd = fopen(fn, mode);
162 	if (!testfd) {
163 		fprintf(stderr, "reopen_file: Cannot open new file: %s\n", strerror(errno));
164 		return;
165 	}
166 	fclose(testfd);
167 
168 	if (freopen(fn, mode, fd) == NULL) {
169 		/* Ugh ... lost the filedescriptor :-(( */
170 	}
171 }
172 
redirect_cgilog(char * cginame)173 void redirect_cgilog(char *cginame)
174 {
175 	char logfn[PATH_MAX];
176 	char *cgilogdir;
177 	FILE *fd;
178 
179 	cgilogdir = getenv("XYMONCGILOGDIR");
180 	if (!cgilogdir) return;
181 
182 	if (cginame) errappname = strdup(cginame);
183 	snprintf(logfn, sizeof(logfn), "%s/cgierror.log", cgilogdir);
184 	reopen_file(logfn, "a", stderr);
185 
186 	/* If debugging, setup the debug logfile */
187 	if (debug) {
188 		snprintf(logfn, sizeof(logfn), "%s/%s.dbg", cgilogdir, (errappname ? errappname : "cgi"));
189 		set_debugfile(logfn, 1);
190 	}
191 }
192 
193 
194