1 /*
2  * log.h --- the logging module of websh3
3  * nca-073-9
4  *
5  * Copyright (c) 1996-2000 by Netcetera AG.
6  * Copyright (c) 2001 by Apache Software Foundation.
7  * All rights reserved.
8  *
9  * See the file "license.terms" for information on usage and
10  * redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
11  *
12  * @(#) $Id: log.h 788707 2009-06-26 14:04:40Z ronnie $
13  *
14  */
15 
16 /* ----------------------------------------------------------------------------
17  * metaphor -- let me explain the methaphor I am using for the logging module:
18  *
19  * it looks to me like a snail mail handling process -- you write an
20  * address onto your letter and drop it in the box (web::log address
21  * letter). The post office decides whether the address makes sense by
22  * searching through the list of known addresses, and rejects the
23  * letter if it does not pass this filter (manage the list of known
24  * addresses with web::loglevel). If the letter is accepted, it goes
25  * through the distribution system where there are different bags,
26  * labeled with "USA", "Zurich" etc. The distributer will put your
27  * letter into the correct bag which then will be handled by the
28  * respective post office (manage the list of bags with web::logdest).
29  * In our case, once the letter is dropped into one of those bags, it
30  * will be delivered right away.
31  * ------------------------------------------------------------------------- */
32 
33 #include "args.h"
34 #include "hashutl.h"
35 #include "macros.h"
36 #include "tcl.h"
37 #include "webutl.h"
38 #include "request.h"
39 
40 
41 #ifndef WEBLOG_H
42 #define WEBLOG_H
43 
44 /* --------------------------------------------------------------------------
45  * Log levels
46  * ------------------------------------------------------------------------*/
47 
48 #define WEBLOG_DEBUG   "websh.debug"
49 #define WEBLOG_INFO    "websh.info"
50 #define WEBLOG_WARNING "websh.warning"
51 #define WEBLOG_ERROR   "websh.error"
52 
53 
54 #define WEB_LOG_DEFAULTFORMAT "%x %X [$p] $f.$l: $m\n"
55 
56 /* --------------------------------------------------------------------------
57  * Commands
58  * ------------------------------------------------------------------------*/
59 
60 /* ----------------------------------------------------------------------------
61  * SubCommands
62  * ------------------------------------------------------------------------- */
63 #define WEB_LOG_SUBCMD_ADD    "add"
64 #define WEB_LOG_SUBCMD_DELETE "delete"
65 #define WEB_LOG_SUBCMD_NAMES  "names"
66 #define WEB_LOG_SUBCMD_LEVELS "levels"
67 
68 /* ----------------------------------------------------------------------------
69  * Parameters (like "web::cmdurl -cmd aCommand", where there is an argument
70  * ------------------------------------------------------------------------- */
71 #define WEB_LOG_PARAM_FORMAT "-format"
72 #define WEB_LOG_PARAM_MAXCHAR "-maxchar"
73 
74 /* --------------------------------------------------------------------------
75  * Registered Data
76  * ------------------------------------------------------------------------*/
77 #define WEB_LOG_ASSOC_DATA "web::logData"
78 
79 /* --------------------------------------------------------------------------
80  * messages
81  * ------------------------------------------------------------------------*/
82 #define WEB_LOG_USAGE_LOGDEST_ADD \
83   "add ?options? level type ?type-specific-arguments ...?"
84 
85 /* --------------------------------------------------------------------------
86  * other
87  * ------------------------------------------------------------------------*/
88 #define LOG_LIST_INITIAL_SIZE 10
89 #define LOG_FILTER_PREFIX "loglevel"
90 #define LOG_DEST_PREFIX "logdest"
91 #define LOG_SUBSTDEFAULT 0
92 #define LOG_SAFEDEFAULT 1
93 
94 /* ----------------------------------------------------------------------------
95  * list of possible categories
96  * ------------------------------------------------------------------------- */
97 typedef enum Severity
98 {
99     none, alert, error, warning, info, debug, invalid = -1
100 }
101 Severity;
102 
103 /* ----------------------------------------------------------------------------
104  * the log level, as attached to a log message and as used for filtering
105  * ------------------------------------------------------------------------- */
106 typedef struct LogLevel
107 {
108     int keep;
109     char *facility;
110     Severity minSeverity;
111     Severity maxSeverity;	/* only used for filter */
112 }
113 LogLevel;
114 
115 LogLevel *createLogLevel();
116 int destroyLogLevel(void *level, void *dum);
117 
118 /* ----------------------------------------------------------------------------
119  * plug-in interface
120  * ------------------------------------------------------------------------- */
121 typedef ClientData(LogPlugInConstructor) (Tcl_Interp * interp,
122 					  ClientData clientData,
123 					  int objc, Tcl_Obj * CONST objv[]);
124 typedef int (LogPlugInDestructor) (Tcl_Interp * interp,
125 				   ClientData clientData);
126 typedef int (LogPlugInHandler) (Tcl_Interp * interp,
127 				ClientData clientData, char *msg);
128 
129 typedef struct LogPlugIn
130 {
131     LogPlugInConstructor *constructor;
132     LogPlugInDestructor *destructor;
133     LogPlugInHandler *handler;
134 }
135 LogPlugIn;
136 LogPlugIn DLLEXPORT *createLogPlugIn();
137 int destroyLogPlugIn(void *plugIn, void *dum);
138 int DLLEXPORT registerLogPlugIn(Tcl_Interp * interp, char *type, LogPlugIn * plugIn);
139 
140 
141 /* ----------------------------------------------------------------------------
142  * log destination (like stderr, file, channel, ...)
143  * ------------------------------------------------------------------------- */
144 typedef struct LogDest
145 {
146     int keep;
147     LogLevel *filter;
148     char *format;
149     long maxCharInMsg;
150     LogPlugIn *plugIn;
151     ClientData plugInData;
152 }
153 LogDest;
154 LogDest *createLogDest();
155 int destroyLogDest(void *dest, void *env);
156 char *createLogDestName(char *prefix, int cnt);
157 
158 
159 
160 
161 /* ----------------------------------------------------------------------------
162  * log data structure
163  * ------------------------------------------------------------------------- */
164 typedef struct LogData
165 {
166   LogLevel **listOfFilters;
167   int filterSize; /* size of filter list */
168   LogDest **listOfDests;
169   int destSize; /* site of destination list */
170   Tcl_HashTable *listOfPlugIns;
171   int logSubst;	/* 1: subst log message, 0: don't (default 0) */
172   int safeLog;	/* 1: web::log never fails, 0: can throw I/O error (default 1) */
173   int keep;  /* flag for log config to keep during initializer code */
174   /* needed so that global settings can be accessed */
175   RequestData * requestData;
176 }
177 LogData;
178 
179 LogData *createLogData();
180 void destroyLogData(ClientData clientData, Tcl_Interp * interp);
181 
182 
183 /* ----------------------------------------------------------------------------
184  * Tcl interface and commands
185  * ------------------------------------------------------------------------- */
186 int DLLEXPORT log_Init(Tcl_Interp * interp);
187 
188 int Web_Log(ClientData clientData,
189 	    Tcl_Interp * interp, int objc, Tcl_Obj * CONST objv[]);
190 
191 int Web_LogDest(ClientData clientData,
192 		Tcl_Interp * interp, int objc, Tcl_Obj * CONST objv[]);
193 
194 int Web_LogFilter(ClientData clientData,
195 		  Tcl_Interp * interp, int objc, Tcl_Obj * CONST objv[]);
196 
197 
198 /* ----------------------------------------------------------------------------
199  * the functions
200  * ------------------------------------------------------------------------- */
201 char *getSeverityName(Severity aSeverity);
202 LogLevel *parseLogLevel(Tcl_Interp * interp,
203 			char *definition, char *defaultfacility, int cnt);
204 Tcl_Obj *formatMessage(LogLevel * level, char *fmt, long maxCharInMsg,
205 		       Tcl_Obj * msg);
206 int doesPass(LogLevel * level, LogLevel * filter);
207 int doesPassFilters(LogLevel * logLevel, LogLevel ** logLevels, int size);
208 int logImpl(Tcl_Interp * interp, LogData * logData,
209 	    char *levelStr, Tcl_Obj * msg);
210 int webLog(Tcl_Interp * interp, char *levelStr, char *msg);
211 
212 int sendMsgToDestList(Tcl_Interp * interp,
213 		       LogData * logData, LogLevel * level, Tcl_Obj * msg);
214 
215 char * insertIntoDestList(LogData *logData, LogDest *logDest);
216 char * insertIntoFilterList(LogData *logData, LogLevel *logLevel);
217 
218 /* ----------------------------------------------------------------------------
219  * Logging
220  * ------------------------------------------------------------------------- */
221 #define WRITE_LOG 1		/* sends message to log facility */
222 #define SET_RESULT 2		/* store part of message in interpreter result */
223 #define INTERP_ERRORINFO 4	/* include tcl-interp's errorInfo in log message */
224 
225 /* default use:
226   LOG_MSG(,WRITE_LOG,...)  --> just write log msg
227   LOG_MSG(,SET_RESULT,...) --> just set interp result
228   LOG_MSG(,WRITE_LOG | SET_RESULT,...) --> log msg and set interp result
229   LOG_MSG(,0,...) --> don't do this
230 */
231 
232 void DLLEXPORT LOG_MSG(Tcl_Interp * interp, int flag, char *filename, int linenr,
233 	     char *cmd, char *level, char *msg, ...);
234 
235 #endif
236