1 /*
2  * Copyright (c) 1997, 1999 Hellmuth Michaelis. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23  * SUCH DAMAGE.
24  *
25  *---------------------------------------------------------------------------
26  *
27  *	i4b daemon - logging routines
28  *	-----------------------------
29  *
30  *	$Id: log.c,v 1.6 2003/10/06 09:43:27 itojun Exp $
31  *
32  * $FreeBSD$
33  *
34  *      last edit-date: [Mon Jan  8 08:09:36 2001]
35  *
36  *---------------------------------------------------------------------------*/
37 
38 #include "isdnd.h"
39 
40 #define LOGBUFLEN 256
41 
42 extern int do_monitor;
43 extern int accepted;
44 extern FILE *logfp;
45 
46 static void check_reg(char *logstring);
47 
48 struct logtab {
49 	char *text;
50 	int pri;
51 };
52 
53 /*---------------------------------------------------------------------------*
54  * 	table for converting internal log levels into syslog levels
55  *---------------------------------------------------------------------------*/
56 static struct logtab logtab[] = {
57 	{"ERR", LOG_ERR},	/* error conditions			*/
58 	{"WRN", LOG_WARNING},   /* warning conditions, nonfatal		*/
59 	{"DMN", LOG_NOTICE},	/* significant conditions of the daemon	*/
60 	{"CHD", LOG_INFO},	/* informational, call handling		*/
61 	{"DBG", LOG_DEBUG},	/* debug messages 			*/
62 	{"MER", LOG_ERR},	/* monitor error conditions		*/
63 	{"PKT", LOG_INFO}	/* packet logging 			*/
64 };
65 
66 /*---------------------------------------------------------------------------*
67  *	initialize logging
68  *---------------------------------------------------------------------------*/
69 void
init_log(void)70 init_log(void)
71 {
72 	int i;
73 
74 	if (uselogfile)
75 	{
76 		if ((logfp = fopen(logfile, "a")) == NULL)
77 		{
78 			fprintf(stderr, "ERROR, cannot open logfile %s: %s\n",
79 				logfile, strerror(errno));
80 			exit(1);
81 		}
82 
83 		/* set unbuffered operation */
84 
85 		setvbuf(logfp, (char *)NULL, _IONBF, 0);
86 	}
87 	else
88 	{
89 #if DEBUG
90 		if (do_debug && do_fork == 0 && do_fullscreen == 0)
91 			(void)openlog("isdnd",
92 				LOG_PID|LOG_NDELAY|LOG_PERROR,
93 				logfacility);
94 		else
95 #endif
96 		(void)openlog("isdnd", LOG_PID|LOG_NDELAY,
97 				logfacility);
98 	}
99 
100 	/* initialize the regexp array */
101 
102 	for (i = 0; i < MAX_RE; i++)
103 	{
104 		char *p;
105 		char buf[64];
106 
107 		snprintf(buf, sizeof(buf), "%s%d", REGPROG_DEF, i);
108 
109 		rarr[i].re_flg = 0;
110 
111 		if ((p = strdup(buf)) == NULL)
112 		{
113 			logit(LL_DBG, "init_log: malloc failed: %s", strerror(errno));
114 			do_exit(1);
115 		}
116 
117 		rarr[i].re_prog = p;
118 	}
119 }
120 
121 /*---------------------------------------------------------------------------*
122  *	finish logging
123  *---------------------------------------------------------------------------*/
124 void
finish_log(void)125 finish_log(void)
126 {
127 	if (uselogfile)
128 	{
129 		fflush(logfp);
130 		fclose(logfp);
131 	}
132 	else
133 	{
134 		(void)closelog();
135 	}
136 }
137 
138 /*---------------------------------------------------------------------------*
139  *	place entry into logfile
140  *---------------------------------------------------------------------------*/
141 void
logit(int what,const char * fmt,...)142 logit(int what, const char *fmt, ...)
143 {
144 	char buffer[LOGBUFLEN];
145 	register char *dp;
146 	va_list ap;
147 
148 	va_start(ap, fmt);
149 	vsnprintf(buffer, LOGBUFLEN-1, fmt, ap);
150 	va_end(ap);
151 
152 	dp = getlogdatetime();	/* get time string ptr */
153 
154 	/* put some messages on stderr to, important if in early startup
155 	   phase and not yet daemonized */
156 	if (what == LL_ERR)
157 		if (!do_fullscreen || !curses_ready)
158 			fprintf(stderr, "isdnd: %s\n", buffer);
159 
160 #ifdef USE_CURSES
161 
162 	/* put log on screen ? */
163 
164 	if ((do_fullscreen && curses_ready) &&
165 	   ((!debug_noscreen) || (debug_noscreen && (what != LL_DBG))))
166 	{
167 		wprintw(lower_w, "%s %s %-.*s\n", dp, logtab[what].text,
168 
169 /*
170  * FreeBSD-current integrated ncurses. Since then it is no longer possible
171  * to write to the last column in the logfilewindow without causing an
172  * automatic newline to occur resulting in a blank line in that window.
173  */
174 #ifdef __FreeBSD__
175 #include <osreldate.h>
176 #endif
177 #if defined(__FreeBSD_version) && __FreeBSD_version >= 400009
178 #warning "FreeBSD ncurses is buggy: write to last column = auto newline!"
179 		     COLS-((strlen(dp))+(strlen(logtab[what].text))+3), buffer);
180 #else
181 		     (int)(COLS-((strlen(dp))+(strlen(logtab[what].text))+2)), buffer);
182 #endif
183 		wrefresh(lower_w);
184 	}
185 #endif
186 
187 #ifdef I4B_EXTERNAL_MONITOR
188 	if (what != LL_MER) /* don't send monitor errs, endless loop !!! */
189 		monitor_evnt_log(logtab[what].pri, logtab[what].text, buffer);
190 #endif
191 
192 	if (uselogfile)
193 	{
194 		fprintf(logfp, "%s %s %s\n", dp, logtab[what].text, buffer);
195 	}
196 	else
197 	{
198 		register char *s = buffer;
199 
200 		/* strip leading spaces from syslog output */
201 
202 		while(*s && (*s == ' '))
203 			s++;
204 
205 		syslog(logtab[what].pri, "%s %s", logtab[what].text, s);
206 	}
207 
208 
209 #if DEBUG
210 	if (what != LL_DBG) /* don't check debug logs, endless loop !!! */
211 #endif
212 		check_reg(buffer);
213 }
214 
215 /*---------------------------------------------------------------------------*
216  *	return ptr to static area containing date/time
217  *---------------------------------------------------------------------------*/
218 char *
getlogdatetime()219 getlogdatetime()
220 {
221 	static char logdatetime[41];
222 	time_t tim;
223 	register struct tm *tp;
224 
225 	tim = time(NULL);
226 	tp = localtime(&tim);
227 	strftime(logdatetime,40,I4B_TIME_FORMAT,tp);
228 	return(logdatetime);
229 }
230 
231 /*---------------------------------------------------------------------------*
232  *	check for a match in the regexp array
233  *---------------------------------------------------------------------------*/
234 static void
check_reg(char * logstring)235 check_reg(char *logstring)
236 {
237 	register int i;
238 
239 	for (i = 0; i < MAX_RE; i++)
240 	{
241 		if (rarr[i].re_flg && (!regexec(&(rarr[i].re), logstring, (size_t) 0, NULL, 0)))
242 		{
243 			char* argv[3];
244 			argv[0] = rarr[i].re_prog;
245 			argv[1] = logstring;
246 			argv[2] = NULL;
247 
248 			exec_prog(rarr[i].re_prog, argv);
249 			break;
250 		}
251 	}
252 }
253 
254 /* EOF */
255