There are no available options for this view.

Parent Directory Parent Directory | Revision <a href="/cvs/aolserver/aolserver/nsd/log.c#A_Log">Log</a> Revision <a href="/cvs/aolserver/aolserver/nsd/log.c#A_Log">Log</a>

Revision 1.17 - (show annotations) (download) (as text)
Thu Sep 9 12:14:23 2010 UTC (20 months, 2 weeks ago) by gneumann
Branch: MAIN
CVS Tags: HEAD
Branch point for: aolserver_v45_r2
Changes since 1.16: +8 -1 lines
File MIME type: text/x-chdr
remove escape characters from log file
1 /*
2 * The contents of this file are subject to the AOLserver Public License
3 * Version 1.1 (the "License"); you may not use this file except in
4 * compliance with the License. You may obtain a copy of the License at
5 * http://aolserver.com/.
6 *
7 * Software distributed under the License is distributed on an "AS IS"
8 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
9 * the License for the specific language governing rights and limitations
10 * under the License.
11 *
12 * The Original Code is AOLserver Code and related documentation
13 * distributed by AOL.
14 *
15 * The Initial Developer of the Original Code is America Online,
16 * Inc. Portions created by AOL are Copyright (C) 1999 America Online,
17 * Inc. All Rights Reserved.
18 *
19 * Alternatively, the contents of this file may be used under the terms
20 * of the GNU General Public License (the "GPL"), in which case the
21 * provisions of GPL are applicable instead of those above. If you wish
22 * to allow use of your version of this file only under the terms of the
23 * GPL and not to allow others to use your version of this file under the
24 * License, indicate your decision by deleting the provisions above and
25 * replace them with the notice and other provisions required by the GPL.
26 * If you do not delete the provisions above, a recipient may use your
27 * version of this file under either the License or the GPL.
28 */
29
30
31 /*
32 * nslog.c --
33 *
34 * This file implements the access log using NCSA Common <a href="/cvs/aolserver/aolserver/nsd/log.c#A_Log">Log</a> format.
35 */
36
37 static const char *RCSID = "@(#) $Header: /cvsroot-fuse/aolserver/aolserver/nslog/nslog.c,v 1.17 2010/09/09 12:14:23 gneumann Exp $, compiled: " __DATE__ " " __TIME__;
38
39 #include "ns.h"
40 #include <sys/stat.h> /* mkdir */
41 #include <ctype.h> /* isspace */
42
43 #define LOG_COMBINED 1
44 #define LOG_FMTTIME 2
45 #define LOG_REQTIME 4
46
47 typedef struct {
48 char *module;
49 Ns_Mutex lock;
50 int fd;
51 char *file;
52 char *rollfmt;
53 int flags;
54 int maxbackup;
55 int maxlines;
56 int curlines;
57 int suppressquery;
58 Ns_DString buffer;
59 char **extheaders;
60 } <a href="/cvs/aolserver/aolserver/nsd/log.c#A_Log">Log</a>;
61
62
63 /*
64 * Local functions defined in this file
65 */
66 static Ns_Callback <a href="/cvs/aolserver/aolserver/nslog/nslog.c#A_LogRollCallback">LogRollCallback</a>;
67 static Ns_Callback <a href="/cvs/aolserver/aolserver/nslog/nslog.c#A_LogCloseCallback">LogCloseCallback</a>;
68 static Ns_TraceProc <a href="/cvs/aolserver/aolserver/nslog/nslog.c#A_LogTrace">LogTrace</a>;
69 static int <a href="/cvs/aolserver/aolserver/nslog/nslog.c#A_LogFlush">LogFlush</a>(<a href="/cvs/aolserver/aolserver/nsd/log.c#A_Log">Log</a> *logPtr, Ns_DString *dsPtr);
70 static int <a href="/cvs/aolserver/aolserver/nslog/nslog.c#A_LogOpen">LogOpen</a>(<a href="/cvs/aolserver/aolserver/nsd/log.c#A_Log">Log</a> *logPtr);
71 static int <a href="/cvs/aolserver/aolserver/nslog/nslog.c#A_LogRoll">LogRoll</a>(<a href="/cvs/aolserver/aolserver/nsd/log.c#A_Log">Log</a> *logPtr);
72 static int <a href="/cvs/aolserver/aolserver/nslog/nslog.c#A_LogClose">LogClose</a>(<a href="/cvs/aolserver/aolserver/nsd/log.c#A_Log">Log</a> *logPtr);
73 static void <a href="/cvs/aolserver/aolserver/nslog/nslog.c#A_LogConfigExtHeaders">LogConfigExtHeaders</a>(<a href="/cvs/aolserver/aolserver/nsd/log.c#A_Log">Log</a> *logPtr, char *path);
74 static Ns_ArgProc <a href="/cvs/aolserver/aolserver/nslog/nslog.c#A_LogArg">LogArg</a>;
75 static Tcl_CmdProc <a href="/cvs/aolserver/aolserver/nslog/nslog.c#A_LogCmd">LogCmd</a>;
76 static Ns_TclInterpInitProc <a href="/cvs/aolserver/nsopenssl/tclcmds.c#A_AddCmds">AddCmds</a>;
77
78
79 /*
80 *----------------------------------------------------------------------
81 *
82 * <a href="/cvs/aolserver/aolserver/nslog/nslog.c#A_NsLog_ModInit">NsLog_ModInit</a> --
83 *
84 * Module initialization routine.
85 *
86 * Results:
87 * NS_OK.
88 *
89 * Side effects:
90 * <a href="/cvs/aolserver/aolserver/nsd/log.c#A_Log">Log</a> file is opened, trace routine is registered, and, if
91 * configured, log file roll signal and scheduled procedures
92 * are registered.
93 *
94 *----------------------------------------------------------------------
95 */
96
97 int
98 <a href="/cvs/aolserver/aolserver/nslog/nslog.c#A_NsLog_ModInit">NsLog_ModInit</a>(char *server, char *module)
99 {
100 char *path;
101 int opt, hour;
102 <a href="/cvs/aolserver/aolserver/nsd/log.c#A_Log">Log</a> *logPtr;
103 static int first = 1;
104
105 /*
106 * Register the info callbacks just once.
107 */
108
109 if (first) {
110 <a href="/cvs/aolserver/aolserver/nsd/proc.c#A_Ns_RegisterProcInfo">Ns_RegisterProcInfo</a>((void *)<a href="/cvs/aolserver/aolserver/nslog/nslog.c#A_LogRollCallback">LogRollCallback</a>, "logroll", <a href="/cvs/aolserver/aolserver/nslog/nslog.c#A_LogArg">LogArg</a>);
111 <a href="/cvs/aolserver/aolserver/nsd/proc.c#A_Ns_RegisterProcInfo">Ns_RegisterProcInfo</a>((void *)<a href="/cvs/aolserver/aolserver/nslog/nslog.c#A_LogCloseCallback">LogCloseCallback</a>, "logclose", <a href="/cvs/aolserver/aolserver/nslog/nslog.c#A_LogArg">LogArg</a>);
112 first = 0;
113 }
114
115 /*
116 * Initialize the log buffer.
117 */
118
119 logPtr = ns_calloc(1, sizeof(<a href="/cvs/aolserver/aolserver/nsd/log.c#A_Log">Log</a>));
120 logPtr->fd = -1;
121 logPtr->module = module;
122 Ns_MutexInit(&logPtr->lock);
123 Ns_MutexSetName2(&logPtr->lock, "nslog", server);
124 <a href="/cvs/aolserver/aolserver/nsd/dstring.c#A_Ns_DStringInit">Ns_DStringInit</a>(&logPtr->buffer);
125
126 /*
127 * Determine the log file name which, if not
128 * absolute, is expected to exist in the module
129 * specific directory. The module directory is
130 * created if necessary.
131 */
132
133 path = <a href="/cvs/aolserver/aolserver/nsd/config.c#A_Ns_ConfigGetPath">Ns_ConfigGetPath</a>(server, module, NULL);
134 logPtr->file = <a href="/cvs/aolserver/aolserver/nsd/config.c#A_Ns_ConfigGetValue">Ns_ConfigGetValue</a>(path, "file");
135 if (logPtr->file == NULL) {
136 logPtr->file = "access.log";
137 }
138 if (<a href="/cvs/aolserver/aolserver/nsd/pathname.c#A_Ns_PathIsAbsolute">Ns_PathIsAbsolute</a>(logPtr->file) == NS_FALSE) {
139 Ns_DString ds;
140
141 <a href="/cvs/aolserver/aolserver/nsd/dstring.c#A_Ns_DStringInit">Ns_DStringInit</a>(&ds);
142 <a href="/cvs/aolserver/aolserver/nsd/pathname.c#A_Ns_ModulePath">Ns_ModulePath</a>(&ds, server, module, NULL, NULL);
143 if (mkdir(ds.string, 0755) != 0 && errno != EEXIST
144 && errno != EISDIR) {
145 <a href="/cvs/aolserver/aolserver/nsd/log.c#A_Ns_Log">Ns_Log</a>(Error, "nslog: mkdir(%s) failed: %s",
146 ds.string, strerror(errno));
147 <a href="/cvs/aolserver/aolserver/nsd/dstring.c#A_Ns_DStringFree">Ns_DStringFree</a>(&ds);
148 return NS_ERROR;
149 }
150 <a href="/cvs/aolserver/aolserver/nsd/dstring.c#A_Ns_DStringTrunc">Ns_DStringTrunc</a>(&ds, 0);
151 <a href="/cvs/aolserver/aolserver/nsd/pathname.c#A_Ns_ModulePath">Ns_ModulePath</a>(&ds, server, module, logPtr->file, NULL);
152 logPtr->file = <a href="/cvs/aolserver/aolserver/nsd/dstring.c#A_Ns_DStringExport">Ns_DStringExport</a>(&ds);
153 }
154
155 /*
156 * Get parameters from configuration file
157 */
158
159 logPtr->rollfmt = <a href="/cvs/aolserver/aolserver/nsd/config.c#A_Ns_ConfigGetValue">Ns_ConfigGetValue</a>(path, "rollfmt");
160 if (!<a href="/cvs/aolserver/aolserver/nsd/config.c#A_Ns_ConfigGetInt">Ns_ConfigGetInt</a>(path, "maxbuffer", &logPtr->maxlines)) {
161 logPtr->maxlines = 0;
162 }
163 if (!<a href="/cvs/aolserver/aolserver/nsd/config.c#A_Ns_ConfigGetInt">Ns_ConfigGetInt</a>(path, "maxbackup", &logPtr->maxbackup) || logPtr->maxbackup < 1) {
164 logPtr->maxbackup = 100;
165 }
166 if (!<a href="/cvs/aolserver/aolserver/nsd/config.c#A_Ns_ConfigGetBool">Ns_ConfigGetBool</a>(path, "formattedTime", &opt)) {
167 opt = 1;
168 }
169 if (opt) {
170 logPtr->flags |= LOG_FMTTIME;
171 }
172 if (!<a href="/cvs/aolserver/aolserver/nsd/config.c#A_Ns_ConfigGetBool">Ns_ConfigGetBool</a>(path, "logcombined", &opt)) {
173 opt = 1;
174 }
175 if (opt) {
176 logPtr->flags |= LOG_COMBINED;
177 }
178 if (!<a href="/cvs/aolserver/aolserver/nsd/config.c#A_Ns_ConfigGetBool">Ns_ConfigGetBool</a>(path, "logreqtime", &opt)) {
179 opt = 0;
180 }
181 if (opt) {
182 logPtr->flags |= LOG_REQTIME;
183 }
184
185
186 if (!<a href="/cvs/aolserver/aolserver/nsd/config.c#A_Ns_ConfigGetBool">Ns_ConfigGetBool</a>(path, "suppressquery", &logPtr->suppressquery)) {
187 logPtr->suppressquery = 0;
188 }
189
190 /*
191 * Schedule various log roll and shutdown options.
192 */
193
194 if (!<a href="/cvs/aolserver/aolserver/nsd/config.c#A_Ns_ConfigGetInt">Ns_ConfigGetInt</a>(path, "rollhour", &hour) ||
195 hour < 0 || hour > 23) {
196 hour = 0;
197 }
198 if (!<a href="/cvs/aolserver/aolserver/nsd/config.c#A_Ns_ConfigGetBool">Ns_ConfigGetBool</a>(path, "rolllog", &opt)) {
199 opt = 1;
200 }
201 if (opt) {
202 <a href="/cvs/aolserver/aolserver/nsd/sched.c#A_Ns_ScheduleDaily">Ns_ScheduleDaily</a>((Ns_SchedProc *) <a href="/cvs/aolserver/aolserver/nslog/nslog.c#A_LogRollCallback">LogRollCallback</a>, logPtr, 0, hour, 0, NULL);
203 }
204 if (!<a href="/cvs/aolserver/aolserver/nsd/config.c#A_Ns_ConfigGetBool">Ns_ConfigGetBool</a>(path, "rollonsignal", &opt)) {
205 opt = 0;;
206 }
207 if (opt) {
208 <a href="/cvs/aolserver/aolserver/nsd/callbacks.c#A_Ns_RegisterAtSignal">Ns_RegisterAtSignal</a>(<a href="/cvs/aolserver/aolserver/nslog/nslog.c#A_LogRollCallback">LogRollCallback</a>, logPtr);
209 }
210
211 <a href="/cvs/aolserver/aolserver/nslog/nslog.c#A_LogConfigExtHeaders">LogConfigExtHeaders</a>(logPtr, path);
212
213 /*
214 * Open the log and register the trace.
215 */
216
217 if (<a href="/cvs/aolserver/aolserver/nslog/nslog.c#A_LogOpen">LogOpen</a>(logPtr) != NS_OK) {
218 return NS_ERROR;
219 }
220 <a href="/cvs/aolserver/aolserver/nsd/filter.c#A_Ns_RegisterServerTrace">Ns_RegisterServerTrace</a>(server, <a href="/cvs/aolserver/aolserver/nslog/nslog.c#A_LogTrace">LogTrace</a>, logPtr);
221 <a href="/cvs/aolserver/aolserver/nsd/callbacks.c#A_Ns_RegisterAtShutdown">Ns_RegisterAtShutdown</a>(<a href="/cvs/aolserver/aolserver/nslog/nslog.c#A_LogCloseCallback">LogCloseCallback</a>, logPtr);
222 <a href="/cvs/aolserver/aolserver/nsd/tclinit.c#A_Ns_TclInitInterps">Ns_TclInitInterps</a>(server, <a href="/cvs/aolserver/nsopenssl/tclcmds.c#A_AddCmds">AddCmds</a>, logPtr);
223 return NS_OK;
224 }
225
226
227 /*
228 *----------------------------------------------------------------------
229 *
230 * <a href="/cvs/aolserver/aolserver/nslog/nslog.c#A_LogTrace">LogTrace</a> --
231 *
232 * Trace routine for appending the log with the current connection
233 * results.
234 *
235 * Results:
236 * None.
237 *
238 * Side effects:
239 * Entry is appended to the open log.
240 *
241 *----------------------------------------------------------------------
242 */
243
244 static void
245 <a href="/cvs/aolserver/aolserver/nslog/nslog.c#A_LogTrace">LogTrace</a>(void *arg, Ns_Conn *conn)
246 {
247 Ns_DString ds;
248 register char *p;
249 int quote, n, status, i;
250 char buf[100];
251 <a href="/cvs/aolserver/aolserver/nsd/log.c#A_Log">Log</a> *logPtr = arg;
252
253 Ns_Time now, diff;
254
255 /*
256 * Compute the request's elapsed time.
257 */
258
259 if (logPtr->flags & LOG_REQTIME) {
260
261 Ns_GetTime(&now);
262 Ns_DiffTime(&now, <a href="/cvs/aolserver/aolserver/nsd/conn.c#A_Ns_ConnStartTime">Ns_ConnStartTime</a>(conn), &diff);
263 }
264
265 <a href="/cvs/aolserver/aolserver/nsd/dstring.c#A_Ns_DStringInit">Ns_DStringInit</a>(&ds);
266
267 /*
268 * Append the peer address and auth user (if any).
269 * Watch for users comming from proxy servers.
270 */
271
272 if (conn->headers && (p = <a href="/cvs/aolserver/aolserver/nsd/set.c#A_Ns_SetIGet">Ns_SetIGet</a>(conn->headers, "X-Forwarded-For"))) {
273 <a href="/cvs/aolserver/aolserver/nsd/dstring.c#A_Ns_DStringAppend">Ns_DStringAppend</a>(&ds, p);
274 } else {
275 <a href="/cvs/aolserver/aolserver/nsd/dstring.c#A_Ns_DStringAppend">Ns_DStringAppend</a>(&ds, <a href="/cvs/aolserver/aolserver/nsd/conn.c#A_Ns_ConnPeer">Ns_ConnPeer</a>(conn));
276 }
277 if (conn->authUser == NULL) {
278 <a href="/cvs/aolserver/aolserver/nsd/dstring.c#A_Ns_DStringAppend">Ns_DStringAppend</a>(&ds, " - - ");
279 } else {
280 p = conn->authUser;
281 quote = 0;
282 while (*p != '\0') {
283 if (isspace((unsigned char) *p)) {
284 quote = 1;
285 break;
286 }
287 ++p;
288 }
289 if (quote) {
290 <a href="/cvs/aolserver/aolserver/nsd/dstring.c#A_Ns_DStringVarAppend">Ns_DStringVarAppend</a>(&ds, " - \"", conn->authUser, "\" ", NULL);
291 } else {
292 <a href="/cvs/aolserver/aolserver/nsd/dstring.c#A_Ns_DStringVarAppend">Ns_DStringVarAppend</a>(&ds, " - ", conn->authUser, " ", NULL);
293 }
294 }
295
296 /*
297 * Append a common log format time stamp including GMT offset.
298 */
299
300 if (!(logPtr->flags & LOG_FMTTIME)) {
301 sprintf(buf, "[%ld]", (long) time(NULL));
302 } else {
303 <a href="/cvs/aolserver/aolserver/nsd/log.c#A_Ns_LogTime">Ns_LogTime</a>(buf);
304 }
305 <a href="/cvs/aolserver/aolserver/nsd/dstring.c#A_Ns_DStringAppend">Ns_DStringAppend</a>(&ds, buf);
306
307 /*
308 * Append the request line.
309 */
310
311 if (conn->request && conn->request->line) {
312
313 if (logPtr->suppressquery) {
314 /*
315 * Don't display query data.
316 * NB: Side-effect is that the real URI is returned, so places
317 * where trailing slash returns "index.html" logs as "index.html".
318 */
319 <a href="/cvs/aolserver/aolserver/nsd/dstring.c#A_Ns_DStringVarAppend">Ns_DStringVarAppend</a>(&ds, " \"", conn->request->url, "\" ", NULL);
320 } else {
321 <a href="/cvs/aolserver/aolserver/nsd/dstring.c#A_Ns_DStringVarAppend">Ns_DStringVarAppend</a>(&ds, " \"", conn->request->line, "\" ", NULL);
322 }
323 } else {
324 <a href="/cvs/aolserver/aolserver/nsd/dstring.c#A_Ns_DStringAppend">Ns_DStringAppend</a>(&ds, " \"\" ");
325 }
326
327 /*
328 * Construct and append the HTTP status code and bytes sent.
329 */
330
331 n = <a href="/cvs/aolserver/aolserver/nsd/conn.c#A_Ns_ConnResponseStatus">Ns_ConnResponseStatus</a>(conn);
332 sprintf(buf, "%d %u ", n ? n : 200, <a href="/cvs/aolserver/aolserver/nsd/conn.c#A_Ns_ConnContentSent">Ns_ConnContentSent</a>(conn));
333 <a href="/cvs/aolserver/aolserver/nsd/dstring.c#A_Ns_DStringAppend">Ns_DStringAppend</a>(&ds, buf);
334
335 if ((logPtr->flags & LOG_COMBINED)) {
336
337 /*
338 * Append the referer and user-agent headers (if any).
339 */
340
341 <a href="/cvs/aolserver/aolserver/nsd/dstring.c#A_Ns_DStringAppend">Ns_DStringAppend</a>(&ds, "\"");
342 if ((p = <a href="/cvs/aolserver/aolserver/nsd/set.c#A_Ns_SetIGet">Ns_SetIGet</a>(conn->headers, "referer"))) {
343 <a href="/cvs/aolserver/aolserver/nsd/dstring.c#A_Ns_DStringAppend">Ns_DStringAppend</a>(&ds, p);
344 }
345 <a href="/cvs/aolserver/aolserver/nsd/dstring.c#A_Ns_DStringAppend">Ns_DStringAppend</a>(&ds, "\" \"");
346 if ((p = <a href="/cvs/aolserver/aolserver/nsd/set.c#A_Ns_SetIGet">Ns_SetIGet</a>(conn->headers, "user-agent"))) {
347 <a href="/cvs/aolserver/aolserver/nsd/dstring.c#A_Ns_DStringAppend">Ns_DStringAppend</a>(&ds, p);
348 }
349 <a href="/cvs/aolserver/aolserver/nsd/dstring.c#A_Ns_DStringAppend">Ns_DStringAppend</a>(&ds, "\"");
350
351 }
352
353 /*
354 * Append the request's elapsed time (if enabled).
355 */
356
357 if (logPtr->flags & LOG_REQTIME) {
358
359 sprintf(buf, " %d.%06ld", (int)diff.sec, diff.usec);
360 <a href="/cvs/aolserver/aolserver/nsd/dstring.c#A_Ns_DStringAppend">Ns_DStringAppend</a>(&ds, buf);
361 }
362
363
364 /*
365 * Append the extended headers (if any).
366 */
367 for (i=0; logPtr->extheaders[i] != NULL; i++) {
368 if ((p = <a href="/cvs/aolserver/aolserver/nsd/set.c#A_Ns_SetIGet">Ns_SetIGet</a>(conn->headers, logPtr->extheaders[i]))) {
369 <a href="/cvs/aolserver/aolserver/nsd/dstring.c#A_Ns_DStringAppend">Ns_DStringAppend</a>(&ds, " \"");
370 <a href="/cvs/aolserver/aolserver/nsd/dstring.c#A_Ns_DStringAppend">Ns_DStringAppend</a>(&ds, p);
371 <a href="/cvs/aolserver/aolserver/nsd/dstring.c#A_Ns_DStringAppend">Ns_DStringAppend</a>(&ds, "\"");
372 } else {
373 <a href="/cvs/aolserver/aolserver/nsd/dstring.c#A_Ns_DStringAppend">Ns_DStringAppend</a>(&ds, " -");
374 }
375 }
376
377 for (i=0; i<ds.length; i++) {
378 /* don't allow terminal escape characters in the log file */
379 if (ds.string[i] == 0x1b) {
380 ds.string[i] = 7; /* bell */
381 }
382 }
383
384 /*
385 * Append the trailing newline and buffer and/or flush the line.
386 */
387
388 status = NS_OK;
389 <a href="/cvs/aolserver/aolserver/nsd/dstring.c#A_Ns_DStringAppend">Ns_DStringAppend</a>(&ds, "\n");
390 Ns_MutexLock(&logPtr->lock);
391 if (logPtr->maxlines <= 0) {
392 status = <a href="/cvs/aolserver/aolserver/nslog/nslog.c#A_LogFlush">LogFlush</a>(logPtr, &ds);
393 } else {
394 <a href="/cvs/aolserver/aolserver/nsd/dstring.c#A_Ns_DStringNAppend">Ns_DStringNAppend</a>(&logPtr->buffer, ds.string, ds.length);
395 if (++logPtr->curlines > logPtr->maxlines) {
396 status = <a href="/cvs/aolserver/aolserver/nslog/nslog.c#A_LogFlush">LogFlush</a>(logPtr, &logPtr->buffer);
397 logPtr->curlines = 0;
398 }
399 }
400 Ns_MutexUnlock(&logPtr->lock);
401 <a href="/cvs/aolserver/aolserver/nsd/dstring.c#A_Ns_DStringFree">Ns_DStringFree</a>(&ds);
402 if (status != NS_OK) {
403 <a href="/cvs/aolserver/aolserver/nsd/log.c#A_Ns_Log">Ns_Log</a>(Error, "nslog: failed to flush log: %s", strerror(errno));
404 }
405 }
406
407
408 /*
409 *----------------------------------------------------------------------
410 *
411 * <a href="/cvs/aolserver/aolserver/nslog/nslog.c#A_LogCmd">LogCmd</a> --
412 *
413 * Implement the ns_accesslog command.
414 *
415 * Results:
416 * Standard Tcl result.
417 *
418 * Side effects:
419 * Depends on command.
420 *
421 *----------------------------------------------------------------------
422 */
423
424 static int
425 <a href="/cvs/aolserver/nsopenssl/tclcmds.c#A_AddCmds">AddCmds</a>(Tcl_Interp *interp, void *arg)
426 {
427 Tcl_CreateCommand(interp, "ns_accesslog", <a href="/cvs/aolserver/aolserver/nslog/nslog.c#A_LogCmd">LogCmd</a>, arg, NULL);
428 return TCL_OK;
429 }
430
431 static int
432 <a href="/cvs/aolserver/aolserver/nslog/nslog.c#A_LogCmd">LogCmd</a>(ClientData arg, Tcl_Interp *interp, int argc, CONST char **argv)
433 {
434 char *rollfile;
435 int status;
436 <a href="/cvs/aolserver/aolserver/nsd/log.c#A_Log">Log</a> *logPtr = arg;
437
438 if (argc < 2) {
439 Tcl_AppendResult(interp, "wrong # args: should be: \"",
440 argv[0], " command ?arg?\"", NULL);
441 return TCL_ERROR;
442 }
443 if (STREQ(argv[1], "file")) {
444 Tcl_SetResult(interp, logPtr->file, TCL_STATIC);
445 } else if (STREQ(argv[1], "roll")) {
446 if (argc != 2 && argc != 3) {
447 Tcl_AppendResult(interp, "wrong # args: should be: \"",
448 argv[0], " ", argv[1], " ?file?\"", NULL);
449 return TCL_ERROR;
450 }
451 Ns_MutexLock(&logPtr->lock);
452 if (argc == 2) {
453 status = <a href="/cvs/aolserver/aolserver/nslog/nslog.c#A_LogRoll">LogRoll</a>(logPtr);
454 } else {
455 rollfile = (char*)argv[2];
456 status = NS_OK;
457 if (access(rollfile, F_OK) == 0) {
458 status = <a href="/cvs/aolserver/aolserver/nsd/rollfile.c#A_Ns_RollFile">Ns_RollFile</a>(rollfile, logPtr->maxbackup);
459 }
460 if (status == NS_OK) {
461 if (rename(logPtr->file, rollfile) != 0) {
462 status = NS_ERROR;
463 } else {
464 <a href="/cvs/aolserver/aolserver/nslog/nslog.c#A_LogFlush">LogFlush</a>(logPtr, &logPtr->buffer);
465 status = <a href="/cvs/aolserver/aolserver/nslog/nslog.c#A_LogOpen">LogOpen</a>(logPtr);
466 }
467 }
468 }
469 Ns_MutexUnlock(&logPtr->lock);
470 if (status != NS_OK) {
471 Tcl_AppendResult(interp, "could not roll \"", logPtr->file,
472 "\": ", Tcl_PosixError(interp), NULL);
473 return TCL_ERROR;
474 }
475 } else {
476 Tcl_AppendResult(interp, "unknown command \"", argv[1],
477 "\": should be file or roll", NULL);
478 return TCL_ERROR;
479 }
480 return TCL_OK;
481 }
482
483
484 /*
485 *----------------------------------------------------------------------
486 *
487 * <a href="/cvs/aolserver/aolserver/nslog/nslog.c#A_LogArg">LogArg</a> --
488 *
489 * Copy log file as argument for callback query.
490 *
491 * Results:
492 * None.
493 *
494 * Side effects:
495 * None.
496 *
497 *----------------------------------------------------------------------
498 */
499
500 static void
501 <a href="/cvs/aolserver/aolserver/nslog/nslog.c#A_LogArg">LogArg</a>(Tcl_DString *dsPtr, void *arg)
502 {
503 <a href="/cvs/aolserver/aolserver/nsd/log.c#A_Log">Log</a> *logPtr = arg;
504
505 Tcl_DStringAppendElement(dsPtr, logPtr->file);
506 }
507
508
509 /*
510 *----------------------------------------------------------------------
511 *
512 * <a href="/cvs/aolserver/aolserver/nslog/nslog.c#A_LogOpen">LogOpen</a> --
513 *
514 * Open the access log, closing previous log if opeopen
515 *
516 * Results:
517 * NS_OK or NS_ERROR.
518 *
519 * Side effects:
520 * <a href="/cvs/aolserver/aolserver/nsd/log.c#A_Log">Log</a> re-opened.
521 *
522 *----------------------------------------------------------------------
523 */
524
525 static int
526 <a href="/cvs/aolserver/aolserver/nslog/nslog.c#A_LogOpen">LogOpen</a>(<a href="/cvs/aolserver/aolserver/nsd/log.c#A_Log">Log</a> *logPtr)
527 {
528 int fd;
529
530 fd = open(logPtr->file, O_APPEND|O_WRONLY|O_CREAT, 0644);
531 if (fd < 0) {
532 <a href="/cvs/aolserver/aolserver/nsd/log.c#A_Ns_Log">Ns_Log</a>(Error, "nslog: error '%s' opening '%s'",
533 strerror(errno),logPtr->file);
534 return NS_ERROR;
535 }
536 if (logPtr->fd >= 0) {
537 close(logPtr->fd);
538 }
539 logPtr->fd = fd;
540 <a href="/cvs/aolserver/aolserver/nsd/log.c#A_Ns_Log">Ns_Log</a>(Notice, "nslog: opened '%s'", logPtr->file);
541 return NS_OK;
542 }
543
544
545 /*
546 *----------------------------------------------------------------------
547 *
548 * <a href="/cvs/aolserver/aolserver/nslog/nslog.c#A_LogClose">LogClose</a> --
549 *
550 * Flush and/or close the log.
551 *
552 * Results:
553 * NS_TRUE or NS_FALSE if log was closed.
554 *
555 * Side effects:
556 * Buffer entries, if any, are flushed.
557 *
558 *----------------------------------------------------------------------
559 */
560
561 static int
562 <a href="/cvs/aolserver/aolserver/nslog/nslog.c#A_LogClose">LogClose</a>(<a href="/cvs/aolserver/aolserver/nsd/log.c#A_Log">Log</a> *logPtr)
563 {
564 int status;
565
566 status = NS_OK;
567 if (logPtr->fd >= 0) {
568 <a href="/cvs/aolserver/aolserver/nsd/log.c#A_Ns_Log">Ns_Log</a>(Notice, "nslog: closing '%s'", logPtr->file);
569 status = <a href="/cvs/aolserver/aolserver/nslog/nslog.c#A_LogFlush">LogFlush</a>(logPtr, &logPtr->buffer);
570 close(logPtr->fd);
571 logPtr->fd = -1;
572 <a href="/cvs/aolserver/aolserver/nsd/dstring.c#A_Ns_DStringFree">Ns_DStringFree</a>(&logPtr->buffer);
573 }
574 return status;
575 }
576
577
578 /*
579 *----------------------------------------------------------------------
580 *
581 * <a href="/cvs/aolserver/aolserver/nslog/nslog.c#A_LogFlush">LogFlush</a> --
582 *
583 * Flush a log buffer to the open log file. Note: The mutex
584 * is assumed held during call.
585 *
586 * Results:
587 * None.
588 *
589 * Side effects:
590 * Will disable the log on error.
591 *
592 *----------------------------------------------------------------------
593 */
594
595 static int
596 <a href="/cvs/aolserver/aolserver/nslog/nslog.c#A_LogFlush">LogFlush</a>(<a href="/cvs/aolserver/aolserver/nsd/log.c#A_Log">Log</a> *logPtr, Ns_DString *dsPtr)
597 {
598 if (dsPtr->length > 0) {
599 if (logPtr->fd >= 0 &&
600 write(logPtr->fd, dsPtr->string, (size_t)dsPtr->length) != dsPtr->length) {
601 <a href="/cvs/aolserver/aolserver/nsd/log.c#A_Ns_Log">Ns_Log</a>(Error, "nslog: "
602 "logging disabled: write() failed: '%s'", strerror(errno));
603 close(logPtr->fd);
604 logPtr->fd = -1;
605 }
606 <a href="/cvs/aolserver/aolserver/nsd/dstring.c#A_Ns_DStringTrunc">Ns_DStringTrunc</a>(dsPtr, 0);
607 }
608 if (logPtr->fd < 0) {
609 return NS_ERROR;
610 }
611 return NS_OK;
612 }
613
614
615 /*
616 *----------------------------------------------------------------------
617 *
618 * <a href="/cvs/aolserver/aolserver/nslog/nslog.c#A_LogRoll">LogRoll</a> --
619 *
620 * Roll and re-open the access log. This procedure is scheduled
621 * and/or registered at signal catching.
622 *
623 * Results:
624 * None.
625 *
626 * Side effects:
627 * Files are rolled to new names.
628 *
629 *----------------------------------------------------------------------
630 */
631
632 static int
633 <a href="/cvs/aolserver/aolserver/nslog/nslog.c#A_LogRoll">LogRoll</a>(<a href="/cvs/aolserver/aolserver/nsd/log.c#A_Log">Log</a> *logPtr)
634 {
635 int status;
636
637 status = NS_OK;
638 (void) <a href="/cvs/aolserver/aolserver/nslog/nslog.c#A_LogClose">LogClose</a>(logPtr);
639 if (access(logPtr->file, F_OK) == 0) {
640 if (logPtr->rollfmt == NULL) {
641 status = <a href="/cvs/aolserver/aolserver/nsd/rollfile.c#A_Ns_RollFile">Ns_RollFile</a>(logPtr->file, logPtr->maxbackup);
642 } else {
643 Ns_DString ds;
644 time_t now;
645 struct tm *ptm;
646 char timeBuf[512];
647
648 now = time(NULL);
649 ptm = ns_localtime(&now);
650 strftime(timeBuf, 512, logPtr->rollfmt, ptm);
651 <a href="/cvs/aolserver/aolserver/nsd/dstring.c#A_Ns_DStringInit">Ns_DStringInit</a>(&ds);
652 <a href="/cvs/aolserver/aolserver/nsd/dstring.c#A_Ns_DStringVarAppend">Ns_DStringVarAppend</a>(&ds, logPtr->file, ".", timeBuf, NULL);
653 if (access(ds.string, F_OK) == 0) {
654 status = <a href="/cvs/aolserver/aolserver/nsd/rollfile.c#A_Ns_RollFile">Ns_RollFile</a>(ds.string, logPtr->maxbackup);
655 } else if (errno != ENOENT) {
656 <a href="/cvs/aolserver/aolserver/nsd/log.c#A_Ns_Log">Ns_Log</a>(Error, "nslog: access(%s, F_OK) failed: '%s'",
657 ds.string, strerror(errno));
658 status = NS_ERROR;
659 }
660 if (status == NS_OK && rename(logPtr->file, ds.string) != 0) {
661 <a href="/cvs/aolserver/aolserver/nsd/log.c#A_Ns_Log">Ns_Log</a>(Error, "nslog: rename(%s, %s) failed: '%s'",
662 logPtr->file, ds.string, strerror(errno));
663 status = NS_ERROR;
664 }
665 <a href="/cvs/aolserver/aolserver/nsd/dstring.c#A_Ns_DStringFree">Ns_DStringFree</a>(&ds);
666 if (status == NS_OK) {
667 status = <a href="/cvs/aolserver/aolserver/nsd/rollfile.c#A_Ns_PurgeFiles">Ns_PurgeFiles</a>(logPtr->file, logPtr->maxbackup);
668 }
669 }
670 }
671 status = <a href="/cvs/aolserver/aolserver/nslog/nslog.c#A_LogOpen">LogOpen</a>(logPtr);
672 return status;
673 }
674
675
676 /*
677 *----------------------------------------------------------------------
678 *
679 * <a href="/cvs/aolserver/aolserver/nslog/nslog.c#A_LogCloseCallback">LogCloseCallback</a>, <a href="/cvs/aolserver/aolserver/nslog/nslog.c#A_LogRollCallback">LogRollCallback</a> -
680 *
681 * Close or roll the log.
682 *
683 * Results:
684 * None.
685 *
686 * Side effects:
687 * See <a href="/cvs/aolserver/aolserver/nslog/nslog.c#A_LogClose">LogClose</a> and <a href="/cvs/aolserver/aolserver/nslog/nslog.c#A_LogRoll">LogRoll</a>.
688 *
689 *----------------------------------------------------------------------
690 */
691
692 static void
693 <a href="/cvs/aolserver/aolserver/nslog/nslog.c#A_LogCallback">LogCallback</a>(int (proc)(<a href="/cvs/aolserver/aolserver/nsd/log.c#A_Log">Log</a> *), void *arg, char *desc)
694 {
695 int status;
696 <a href="/cvs/aolserver/aolserver/nsd/log.c#A_Log">Log</a> *logPtr = arg;
697
698 Ns_MutexLock(&logPtr->lock);
699 status = (*proc)(logPtr);
700 Ns_MutexUnlock(&logPtr->lock);
701 if (status != NS_OK) {
702 <a href="/cvs/aolserver/aolserver/nsd/log.c#A_Ns_Log">Ns_Log</a>(Error, "nslog: failed: %s '%s': '%s'",
703 desc, logPtr->file, strerror(errno));
704 }
705 }
706
707 static void
708 <a href="/cvs/aolserver/aolserver/nslog/nslog.c#A_LogCloseCallback">LogCloseCallback</a>(void *arg)
709 {
710 <a href="/cvs/aolserver/aolserver/nslog/nslog.c#A_LogCallback">LogCallback</a>(<a href="/cvs/aolserver/aolserver/nslog/nslog.c#A_LogClose">LogClose</a>, arg, "close");
711 }
712
713 static void
714 <a href="/cvs/aolserver/aolserver/nslog/nslog.c#A_LogRollCallback">LogRollCallback</a>(void *arg)
715 {
716 <a href="/cvs/aolserver/aolserver/nslog/nslog.c#A_LogCallback">LogCallback</a>(<a href="/cvs/aolserver/aolserver/nslog/nslog.c#A_LogRoll">LogRoll</a>, arg, "roll");
717 }
718
719
720 /*
721 *----------------------------------------------------------------------
722 *
723 * <a href="/cvs/aolserver/aolserver/nslog/nslog.c#A_LogConfigExtHeaders">LogConfigExtHeaders</a>
724 *
725 * <a href="/cvs/aolserver/aolserver/nsd/adpparse.c#A_Parse">Parse</a> the ExtendedHeaders configuration.
726 *
727 * Results:
728 * None.
729 *
730 * Side effects:
731 * Sets logPtr->extheaders.
732 *
733 *----------------------------------------------------------------------
734 */
735
736 static void
737 <a href="/cvs/aolserver/aolserver/nslog/nslog.c#A_LogConfigExtHeaders">LogConfigExtHeaders</a>(<a href="/cvs/aolserver/aolserver/nsd/log.c#A_Log">Log</a> *logPtr, char *path)
738 {
739 char *config = <a href="/cvs/aolserver/aolserver/nsd/config.c#A_Ns_ConfigGetValue">Ns_ConfigGetValue</a>(path, "extendedheaders");
740 char *p;
741 int i;
742
743 if (config == NULL) {
744 logPtr->extheaders = ns_calloc(1, sizeof *logPtr->extheaders);
745 logPtr->extheaders[0] = NULL;
746 return;
747 }
748
749 config = ns_strdup(config);
750
751 /* Figure out how many extended headers there are. */
752
753 for (i = 1, p = config; *p; p++) {
754 if (*p == ',') {
755 i++;
756 }
757 }
758
759 /* Initialize the extended header pointers. */
760
761 logPtr->extheaders = ns_calloc((size_t)(i + 1), sizeof *logPtr->extheaders);
762
763 logPtr->extheaders[0] = config;
764
765 for (i = 1, p = config; *p; p++) {
766 if (*p == ',') {
767 *p = '\000';
768 logPtr->extheaders[i++] = p + 1;
769 }
770 }
771
772 logPtr->extheaders[i] = NULL;
773
774 }
775