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