1 /* ====================================================================
2 * The Kannel Software License, Version 1.0
3 *
4 * Copyright (c) 2001-2014 Kannel Group
5 * Copyright (c) 1998-2001 WapIT Ltd.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 *
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in
17 * the documentation and/or other materials provided with the
18 * distribution.
19 *
20 * 3. The end-user documentation included with the redistribution,
21 * if any, must include the following acknowledgment:
22 * "This product includes software developed by the
23 * Kannel Group (http://www.kannel.org/)."
24 * Alternately, this acknowledgment may appear in the software itself,
25 * if and wherever such third-party acknowledgments normally appear.
26 *
27 * 4. The names "Kannel" and "Kannel Group" must not be used to
28 * endorse or promote products derived from this software without
29 * prior written permission. For written permission, please
30 * contact org@kannel.org.
31 *
32 * 5. Products derived from this software may not be called "Kannel",
33 * nor may "Kannel" appear in their name, without prior written
34 * permission of the Kannel Group.
35 *
36 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39 * DISCLAIMED. IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS
40 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
41 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
42 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
43 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
44 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
45 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
46 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
47 * ====================================================================
48 *
49 * This software consists of voluntary contributions made by many
50 * individuals on behalf of the Kannel Group. For more information on
51 * the Kannel Group, please see <http://www.kannel.org/>.
52 *
53 * Portions of this software are based upon software originally written at
54 * WapIT Ltd., Helsinki, Finland for the Kannel project.
55 */
56
57 /*
58 * accesslog.c - implement access logging functions
59 *
60 * see accesslog.h.
61 *
62 * Kalle Marjola 2000 for Project Kannel
63 */
64
65
66 #include <stdio.h>
67 #include <stdlib.h>
68 #include <errno.h>
69 #include <time.h>
70 #include <stdarg.h>
71 #include <string.h>
72
73 #include "gwlib.h"
74
75 static FILE *file = NULL;
76 static char filename[FILENAME_MAX + 1]; /* to allow re-open */
77 static int use_localtime;
78 static int markers = 1; /* can be turned-off by 'access-log-clean = yes' */
79
80 /*
81 * Reopen/rotate lock.
82 */
83 static List *writers = NULL;
84
alog_reopen(void)85 void alog_reopen(void)
86 {
87 if (file == NULL)
88 return;
89
90 if (markers)
91 alog("Log ends");
92
93 gwlist_lock(writers);
94 /* wait for writers to complete */
95 gwlist_consume(writers);
96
97 fclose(file);
98 file = fopen(filename, "a");
99
100 gwlist_unlock(writers);
101
102 if (file == NULL) {
103 error(errno, "Couldn't re-open access logfile `%s'.", filename);
104 }
105 else if (markers) {
106 alog("Log begins");
107 }
108 }
109
110
alog_close(void)111 void alog_close(void)
112 {
113
114 if (file != NULL) {
115 if (markers)
116 alog("Log ends");
117 gwlist_lock(writers);
118 /* wait for writers to complete */
119 gwlist_consume(writers);
120 fclose(file);
121 file = NULL;
122 gwlist_unlock(writers);
123 gwlist_destroy(writers, NULL);
124 writers = NULL;
125 }
126 }
127
128
alog_open(char * fname,int use_localtm,int use_markers)129 void alog_open(char *fname, int use_localtm, int use_markers)
130 {
131 FILE *f;
132
133 use_localtime = use_localtm;
134 markers = use_markers;
135
136 if (file != NULL) {
137 warning(0, "Opening an already opened access log");
138 alog_close();
139 }
140 if (strlen(fname) > FILENAME_MAX) {
141 error(0, "Access Log filename too long: `%s', cannot open.", fname);
142 return;
143 }
144
145 if (writers == NULL)
146 writers = gwlist_create();
147
148 f = fopen(fname, "a");
149 if (f == NULL) {
150 error(errno, "Couldn't open logfile `%s'.", fname);
151 return;
152 }
153 file = f;
154 strcpy(filename, fname);
155 info(0, "Started access logfile `%s'.", filename);
156 if (markers)
157 alog("Log begins");
158 }
159
160
alog_use_localtime(void)161 void alog_use_localtime(void)
162 {
163 use_localtime = 1;
164 }
165
166
alog_use_gmtime(void)167 void alog_use_gmtime(void)
168 {
169 use_localtime = 0;
170 }
171
172
173 #define FORMAT_SIZE (10*1024)
format(char * buf,const char * fmt)174 static void format(char *buf, const char *fmt)
175 {
176 time_t t;
177 struct tm tm;
178 char *p, prefix[1024];
179
180 p = prefix;
181
182 if (markers) {
183 time(&t);
184 if (use_localtime)
185 tm = gw_localtime(t);
186 else
187 tm = gw_gmtime(t);
188
189 sprintf(p, "%04d-%02d-%02d %02d:%02d:%02d ",
190 tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
191 tm.tm_hour, tm.tm_min, tm.tm_sec);
192 } else {
193 *p = '\0';
194 }
195
196 if (strlen(prefix) + strlen(fmt) > FORMAT_SIZE / 2) {
197 sprintf(buf, "%s <OUTPUT message too long>\n", prefix);
198 return;
199 }
200 sprintf(buf, "%s%s\n", prefix, fmt);
201 }
202
203
204 /* XXX should we also log automatically into main log, too? */
205
alog(const char * fmt,...)206 void alog(const char *fmt, ...)
207 {
208 char buf[FORMAT_SIZE + 1];
209 va_list args;
210
211 if (file == NULL)
212 return;
213
214 format(buf, fmt);
215 va_start(args, fmt);
216
217 gwlist_lock(writers);
218 gwlist_add_producer(writers);
219 gwlist_unlock(writers);
220
221 vfprintf(file, buf, args);
222 fflush(file);
223
224 gwlist_remove_producer(writers);
225
226 va_end(args);
227 }
228
229