added (long) GPL headers.
[swftools.git] / lib / log.c
1 /* log.c 
2    Logging facilities for displaying information on screen, as well as
3    (optional) storing it to a file and transmitting it over the network.
4
5    Part of the swftools package.
6    
7    Copyright (c) 2001 Matthias Kramm <kramm@quiss.org> 
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 2 of the License, or
12    (at your option) any later version.
13
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
22
23 #ifdef __NT__
24 #include "stdafx.h"
25 #include <string.h>
26 #include <winsock2.h>
27 #include <stdlib.h>
28 #include <malloc.h>
29 #if _MSC_VER > 1000
30 #pragma once
31 #endif // _MSC_VER > 1000
32 #else
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <stdarg.h>
36 #include <string.h>
37 #include <unistd.h>
38 #endif
39
40 #include "log.h"
41
42 int screenloglevel = 1;
43 static int fileloglevel = -1;
44 static int socketloglevel = -1;
45 static int maxloglevel = 1;
46 static FILE *logFile = 0;
47 #ifdef __NT__
48 static SOCKET logSocket;
49 #else
50 static int logSocket = 0;
51 #endif
52
53 static char bLogToSock = 0;
54
55 static void initlogSocket(char* servAddr, char* logPort);
56
57 void initLog(char* pLogName, int fileloglevel, char* servAddr, char* logPort, int serverlevel, int screenlevel)
58 {
59    screenloglevel = screenlevel;
60    fileloglevel = fileloglevel;
61    socketloglevel = screenlevel;
62
63    maxloglevel=screenloglevel;
64    if(fileloglevel>maxloglevel && pLogName)
65        maxloglevel=fileloglevel;
66    if(serverlevel>maxloglevel && servAddr)
67        maxloglevel=serverlevel;
68
69    if(!servAddr)
70        serverlevel = -1;
71    if(!pLogName)
72        fileloglevel = -1;
73
74    logFile = NULL;
75    bLogToSock = 0;
76
77    if (pLogName && fileloglevel>=0)
78    logFile = fopen(pLogName, "a+");
79    bLogToSock = (servAddr && logPort && (serverlevel>=0));
80    if(bLogToSock)
81        initlogSocket(servAddr, logPort);
82 }
83
84 static void initlogSocket(char* servAddr, char* logPort)
85 {
86 #ifndef __NT__
87    bLogToSock = 0;
88 #else
89    // init winsock
90    // check and prepare WinSock DLL
91    WORD wVersionRequested = MAKEWORD( 2, 2 );
92    WSADATA wsaData;
93    if ( WSAStartup(wVersionRequested, &wsaData) != 0 )
94    {
95       bLogToSock = false;
96       return;
97    }
98    // Confirm that the WinSock DLL supports 2.2.
99    // Note that if the DLL supports versions greater
100    // than 2.2 in addition to 2.2, it will still return
101    // 2.2 in wVersion since that is the version we
102    // requested.
103
104    if ( LOBYTE( wsaData.wVersion ) != 2 || HIBYTE( wsaData.wVersion ) != 2 )
105    {
106       bLogToSock = false;
107       return;
108    }
109
110    struct hostent *hp;
111    hp = gethostbyname(servAddr);
112    if (hp == NULL) // we don't know who this host is
113    {
114       bLogToSock = false;
115       return;
116    }
117
118    // connect socket
119    sockaddr_in SocketAddress;
120
121    memset(&SocketAddress, 0, sizeof(SocketAddress));
122    memcpy((char*)&SocketAddress.sin_addr, hp->h_addr, hp->h_length); // set address
123    SocketAddress.sin_family = hp->h_addrtype;
124    SocketAddress.sin_port = htons((u_short)atoi(logPort));
125
126    logSocket = socket(hp->h_addrtype, SOCK_STREAM, 0);
127    if (logSocket == INVALID_SOCKET)
128    {
129       bLogToSock = false;
130       return;
131    }
132
133    // try to connect to the specified socket
134    if ( connect(logSocket, (struct sockaddr*)&SocketAddress, sizeof (SocketAddress)) == SOCKET_ERROR) {
135       bLogToSock = false;
136       return;
137    }
138    bLogToSock = true;
139 #endif
140 }
141
142 void exitLog()
143 {
144    // close socket communication
145    if(bLogToSock)
146 #ifndef __NT__
147      close(logSocket);
148 #else
149      closesocket(logSocket);
150 #endif
151    // close file
152    if(logFile != NULL)
153      fclose(logFile);
154 }
155
156
157 static char * logimportance[]= {"Fatal","Error","Warning","Notice","Verbose","Debug"};
158 static int loglevels=6;
159 static char * logimportance2[]= {"       ","FATAL  ","ERROR  ","WARNING","NOTICE ","VERBOSE","DEBUG  "};
160 static inline void log(char* logString)
161 {
162    char timebuffer[32];
163    char* logBuffer;
164    char dbuffer[9];
165    char tbuffer[9];
166    int level;
167    char*lt;
168    char*gt;
169    int l;
170
171    logBuffer = (char*)malloc (strlen(logString) + 24 + 15);
172 #ifndef __NT__
173    {
174      /*time_t t = time(0);
175      tm*t2 = localtime(t);
176      strftime(dbuffer, 8, "%m %d", t2);
177      strftime(tbuffer, 8, "%m %d", t2);
178      dbuffer[0]=0; //FIXME
179      tbuffer[0]=0;*/
180      time_t t = time(0);
181      char* a = ctime(&t);
182      int l = strlen(a);
183      while(a[l-1] == 13 || a[l-1] == 10)
184        l--;
185      a[l]=0;
186      sprintf(timebuffer, "%s", a);
187    }
188 #else
189    _strdate( dbuffer );
190    _strtime( tbuffer );
191    sprintf(timebuffer, "%s - %s",dbuffer,tbuffer);
192 #endif
193
194    // search for <level> field
195    level = -1;
196    lt=strchr(logString, '<');
197    gt=strchr(logString, '>');
198    if(lt && gt && lt<gt)
199    {
200        int t;
201        for(t=0;t<loglevels;t++)
202        {
203 #ifndef __NT__
204            if(!strncasecmp(lt+1,logimportance[t],strlen(logimportance[t])))
205 #else
206            if(!strnicmp(lt+1,logimportance[t],strlen(logimportance[t])))
207 #endif
208            {
209                logString = gt+1;
210                while(logString[0]==' ') logString ++;
211                level = t;
212                break;
213            }
214        }
215    }
216    
217 //   sprintf(logBuffer, "%s: %s %s", timebuffer, logimportance2[level + 1],logString);
218    sprintf(logBuffer, "%s %s", logimportance2[level + 1],logString);
219
220    // we always do exactly one newline.
221    
222    l=strlen(logBuffer)-1;
223    while((logBuffer[l]==13 || logBuffer[l]==10) && l>=0)
224    {
225        logBuffer[l]=0;
226        l--;
227    }
228
229    if (level <= screenloglevel)
230    {
231        printf("%s\n", logBuffer); 
232        fflush(stdout);
233    }
234
235    if (level <= fileloglevel)
236    {
237        if (logFile != NULL)
238        {
239           fprintf(logFile, "%s\n", logBuffer); 
240           fflush(logFile);
241        }
242    }
243
244    if (level <= socketloglevel)
245    {
246        if (bLogToSock)
247        {
248           // send data
249 #ifndef __NT__
250           write(logSocket, logBuffer, strlen(logBuffer));
251 #else
252           send(logSocket, logBuffer, strlen(logBuffer), 0);
253 #endif
254        }
255    }
256    free (logBuffer);
257 }
258
259 void msg(const char* format, ...)
260 {
261     char buf[1024];
262         va_list arglist;
263         va_start(arglist, format);
264     
265     /* speed up hack */
266     if(format[0]=='<') {
267         char*z = "fewnvd";
268         char*x = strchr(z,format[1]);
269         if(x && (x-z)>maxloglevel)
270                 return;
271     }
272
273     vsprintf(buf, format, arglist);
274         va_end(arglist);
275     strcat(buf, "\n");
276     log(buf);
277 }
278