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.8 2011/08/31 16:24:59 plunky 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
42extern int do_monitor;
43extern int accepted;
44extern FILE *logfp;
45
46static void check_reg(char *logstring);
47
48struct logtab {
49	const char *text;
50	int pri;
51};
52
53/*---------------------------------------------------------------------------*
54 * 	table for converting internal log levels into syslog levels
55 *---------------------------------------------------------------------------*/
56static 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 *---------------------------------------------------------------------------*/
69void
70init_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, 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 *---------------------------------------------------------------------------*/
124void
125finish_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 *---------------------------------------------------------------------------*/
141void
142logit(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 *---------------------------------------------------------------------------*/
218char *
219getlogdatetime()
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 *---------------------------------------------------------------------------*/
234static void
235check_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			const 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