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