xref: /reactos/base/services/telnetd/syslog.c (revision c2c66aff)
1*c2c66affSColin Finck /*
2*c2c66affSColin Finck  * syslog-client.c - syslog client implementation for windows
3*c2c66affSColin Finck  *
4*c2c66affSColin Finck  * Created by Alexander Yaworsky
5*c2c66affSColin Finck  *
6*c2c66affSColin Finck  * THIS SOFTWARE IS NOT COPYRIGHTED
7*c2c66affSColin Finck  *
8*c2c66affSColin Finck  * This source code is offered for use in the public domain. You may
9*c2c66affSColin Finck  * use, modify or distribute it freely.
10*c2c66affSColin Finck  *
11*c2c66affSColin Finck  * This code is distributed in the hope that it will be useful but
12*c2c66affSColin Finck  * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY
13*c2c66affSColin Finck  * DISCLAIMED. This includes but is not limited to warranties of
14*c2c66affSColin Finck  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15*c2c66affSColin Finck  *
16*c2c66affSColin Finck  */
17*c2c66affSColin Finck 
18*c2c66affSColin Finck /* define SYSLOG_CONF_DIR where syslog.host should be
19*c2c66affSColin Finck  */
20*c2c66affSColin Finck 
21*c2c66affSColin Finck #ifndef SYSLOG_CONF_DIR
22*c2c66affSColin Finck static const char *syslog_conf_dir = ".";
23*c2c66affSColin Finck #else
24*c2c66affSColin Finck static const char *syslog_conf_dir = SYSLOG_CONF_DIR;
25*c2c66affSColin Finck #endif
26*c2c66affSColin Finck 
27*c2c66affSColin Finck #include <stdio.h>
28*c2c66affSColin Finck #include <string.h>
29*c2c66affSColin Finck #include <winsock2.h>
30*c2c66affSColin Finck #include <ws2tcpip.h>
31*c2c66affSColin Finck #include "syslog.h"
32*c2c66affSColin Finck 
33*c2c66affSColin Finck #ifdef TEST
34*c2c66affSColin Finck #    define SYSLOG_DGRAM_SIZE 80
35*c2c66affSColin Finck #else
36*c2c66affSColin Finck #    define SYSLOG_DGRAM_SIZE 1024
37*c2c66affSColin Finck #endif
38*c2c66affSColin Finck 
39*c2c66affSColin Finck static BOOL initialized = FALSE;
40*c2c66affSColin Finck static int log_mask = 0xFF;
41*c2c66affSColin Finck static char *syslog_ident;
42*c2c66affSColin Finck static int syslog_facility;
43*c2c66affSColin Finck static char str_pid[ 40 ];
44*c2c66affSColin Finck static SOCKADDR_IN sa_logger;
45*c2c66affSColin Finck static SOCKET sock;
46*c2c66affSColin Finck static char local_hostname[ MAX_COMPUTERNAME_LENGTH + 1 ];
47*c2c66affSColin Finck static char datagramm[ SYSLOG_DGRAM_SIZE ];
48*c2c66affSColin Finck static int datagramm_size;
49*c2c66affSColin Finck 
50*c2c66affSColin Finck /******************************************************************************
51*c2c66affSColin Finck  * set_syslog_conf_dir
52*c2c66affSColin Finck  *
53*c2c66affSColin Finck  * maybe this function will be useful...
54*c2c66affSColin Finck  */
set_syslog_conf_dir(const char * dir)55*c2c66affSColin Finck const char* set_syslog_conf_dir( const char* dir )
56*c2c66affSColin Finck {
57*c2c66affSColin Finck     const char *ret = syslog_conf_dir;
58*c2c66affSColin Finck     syslog_conf_dir = dir;
59*c2c66affSColin Finck     return ret;
60*c2c66affSColin Finck }
61*c2c66affSColin Finck 
62*c2c66affSColin Finck /******************************************************************************
63*c2c66affSColin Finck  * init_logger_addr
64*c2c66affSColin Finck  *
65*c2c66affSColin Finck  * Read configuration file syslog.host. This file should contain host address
66*c2c66affSColin Finck  * and, optionally, port. Initialize sa_logger. If the configuration file does
67*c2c66affSColin Finck  * not exist, use localhost:514.
68*c2c66affSColin Finck  * Returns: 0 - ok, -1 - error.
69*c2c66affSColin Finck  */
init_logger_addr()70*c2c66affSColin Finck static void init_logger_addr()
71*c2c66affSColin Finck {
72*c2c66affSColin Finck     char pathname[ FILENAME_MAX ];
73*c2c66affSColin Finck     char *p;
74*c2c66affSColin Finck     FILE *fd;
75*c2c66affSColin Finck     char host[256];
76*c2c66affSColin Finck     struct hostent * phe;
77*c2c66affSColin Finck 
78*c2c66affSColin Finck     memset( &sa_logger, 0, sizeof(SOCKADDR_IN) );
79*c2c66affSColin Finck     sa_logger.sin_family = AF_INET;
80*c2c66affSColin Finck 
81*c2c66affSColin Finck     if( '\\' == syslog_conf_dir[0] || '/' == syslog_conf_dir[0] || ':' == syslog_conf_dir[1] )
82*c2c66affSColin Finck     {
83*c2c66affSColin Finck         /* absolute path */
84*c2c66affSColin Finck         strcpy( pathname, syslog_conf_dir );
85*c2c66affSColin Finck     }
86*c2c66affSColin Finck     else
87*c2c66affSColin Finck     {
88*c2c66affSColin Finck         /* relative path */
89*c2c66affSColin Finck         char *q;
90*c2c66affSColin Finck 
91*c2c66affSColin Finck         strcpy( pathname, __argv[0] );
92*c2c66affSColin Finck         p = strrchr( pathname, '\\' ) + 1;
93*c2c66affSColin Finck         q = strrchr( pathname, '/' ) + 1;
94*c2c66affSColin Finck         if( p < q )
95*c2c66affSColin Finck             *q = 0;
96*c2c66affSColin Finck         else if( p > q )
97*c2c66affSColin Finck             *p = 0;
98*c2c66affSColin Finck         else
99*c2c66affSColin Finck             pathname[0] = 0;
100*c2c66affSColin Finck         strcat( pathname, syslog_conf_dir );
101*c2c66affSColin Finck     }
102*c2c66affSColin Finck     p = &pathname[ strlen( pathname ) - 1 ];
103*c2c66affSColin Finck     if( '\\' != *p && '/' != *p )
104*c2c66affSColin Finck     {
105*c2c66affSColin Finck         p++; *p = '/';
106*c2c66affSColin Finck     }
107*c2c66affSColin Finck     strcpy( ++p, "syslog.host" );
108*c2c66affSColin Finck 
109*c2c66affSColin Finck     /* read destination host name */
110*c2c66affSColin Finck     fd = fopen( pathname, "r" );
111*c2c66affSColin Finck     if( !fd )
112*c2c66affSColin Finck         goto use_default;
113*c2c66affSColin Finck 
114*c2c66affSColin Finck     if( NULL == fgets( host, sizeof(host), fd ) )
115*c2c66affSColin Finck         host[0] = 0;
116*c2c66affSColin Finck     else
117*c2c66affSColin Finck     {
118*c2c66affSColin Finck         p = strchr( host, '\n' );
119*c2c66affSColin Finck         if( p )
120*c2c66affSColin Finck             *p = 0;
121*c2c66affSColin Finck         p = strchr( host, '\r' );
122*c2c66affSColin Finck         if( p )
123*c2c66affSColin Finck             *p = 0;
124*c2c66affSColin Finck     }
125*c2c66affSColin Finck     fclose( fd );
126*c2c66affSColin Finck 
127*c2c66affSColin Finck     p = strchr( host, ':' );
128*c2c66affSColin Finck     if( p )
129*c2c66affSColin Finck         *p++ = 0;
130*c2c66affSColin Finck 
131*c2c66affSColin Finck     phe = gethostbyname( host );
132*c2c66affSColin Finck     if( !phe )
133*c2c66affSColin Finck         goto use_default;
134*c2c66affSColin Finck 
135*c2c66affSColin Finck     memcpy( &sa_logger.sin_addr.s_addr, phe->h_addr, phe->h_length );
136*c2c66affSColin Finck 
137*c2c66affSColin Finck     if( p )
138*c2c66affSColin Finck         sa_logger.sin_port = htons( (unsigned short) strtoul( p, NULL, 0 ) );
139*c2c66affSColin Finck     else
140*c2c66affSColin Finck         sa_logger.sin_port = htons( SYSLOG_PORT );
141*c2c66affSColin Finck     return;
142*c2c66affSColin Finck 
143*c2c66affSColin Finck use_default:
144*c2c66affSColin Finck     sa_logger.sin_addr.S_un.S_addr = htonl( 0x7F000001 );
145*c2c66affSColin Finck     sa_logger.sin_port = htons( SYSLOG_PORT );
146*c2c66affSColin Finck }
147*c2c66affSColin Finck 
148*c2c66affSColin Finck /******************************************************************************
149*c2c66affSColin Finck  * closelog
150*c2c66affSColin Finck  *
151*c2c66affSColin Finck  * Close descriptor used to write to system logger.
152*c2c66affSColin Finck  */
closelog()153*c2c66affSColin Finck void closelog()
154*c2c66affSColin Finck {
155*c2c66affSColin Finck     if( !initialized )
156*c2c66affSColin Finck         return;
157*c2c66affSColin Finck     closesocket( sock );
158*c2c66affSColin Finck     WSACleanup();
159*c2c66affSColin Finck     initialized = FALSE;
160*c2c66affSColin Finck }
161*c2c66affSColin Finck 
162*c2c66affSColin Finck /******************************************************************************
163*c2c66affSColin Finck  * openlog
164*c2c66affSColin Finck  *
165*c2c66affSColin Finck  * Open connection to system logger.
166*c2c66affSColin Finck  */
openlog(char * ident,int option,int facility)167*c2c66affSColin Finck void openlog( char* ident, int option, int facility )
168*c2c66affSColin Finck {
169*c2c66affSColin Finck     BOOL failed = TRUE, wsa_initialized = FALSE;
170*c2c66affSColin Finck     WSADATA wsd;
171*c2c66affSColin Finck     SOCKADDR_IN sa_local;
172*c2c66affSColin Finck     DWORD n;
173*c2c66affSColin Finck     int size;
174*c2c66affSColin Finck 
175*c2c66affSColin Finck     if( initialized )
176*c2c66affSColin Finck         return;
177*c2c66affSColin Finck 
178*c2c66affSColin Finck     syslog_facility = facility? facility : LOG_USER;
179*c2c66affSColin Finck 
180*c2c66affSColin Finck     /* FIXME: should we reset logmask? */
181*c2c66affSColin Finck 
182*c2c66affSColin Finck     if( option & LOG_PID )
183*c2c66affSColin Finck         snprintf( str_pid, sizeof(str_pid), "[%lu]", GetCurrentProcessId() );
184*c2c66affSColin Finck     else
185*c2c66affSColin Finck         str_pid[0] = 0;
186*c2c66affSColin Finck 
187*c2c66affSColin Finck     /* FIXME: handle other options */
188*c2c66affSColin Finck 
189*c2c66affSColin Finck     n = sizeof(local_hostname);
190*c2c66affSColin Finck     if( !GetComputerName( local_hostname, &n ) )
191*c2c66affSColin Finck         goto done;
192*c2c66affSColin Finck 
193*c2c66affSColin Finck     sock = INVALID_SOCKET;
194*c2c66affSColin Finck     if( WSAStartup( MAKEWORD( 2, 2 ), &wsd ) )
195*c2c66affSColin Finck         goto done;
196*c2c66affSColin Finck     wsa_initialized = TRUE;
197*c2c66affSColin Finck 
198*c2c66affSColin Finck     init_logger_addr();
199*c2c66affSColin Finck 
200*c2c66affSColin Finck     for( n = 0;; n++ )
201*c2c66affSColin Finck     {
202*c2c66affSColin Finck         sock = socket( AF_INET, SOCK_DGRAM, 0 );
203*c2c66affSColin Finck         if( INVALID_SOCKET == sock )
204*c2c66affSColin Finck             goto done;
205*c2c66affSColin Finck 
206*c2c66affSColin Finck         memset( &sa_local, 0, sizeof(SOCKADDR_IN) );
207*c2c66affSColin Finck         sa_local.sin_family = AF_INET;
208*c2c66affSColin Finck         if( bind( sock, (SOCKADDR*) &sa_local, sizeof(SOCKADDR_IN) ) == 0 )
209*c2c66affSColin Finck             break;
210*c2c66affSColin Finck         closesocket( sock );
211*c2c66affSColin Finck         sock = INVALID_SOCKET;
212*c2c66affSColin Finck         if( n == 100 )
213*c2c66affSColin Finck             goto done;
214*c2c66affSColin Finck         Sleep(0);
215*c2c66affSColin Finck     }
216*c2c66affSColin Finck 
217*c2c66affSColin Finck     /* get size of datagramm */
218*c2c66affSColin Finck     size = sizeof(datagramm_size);
219*c2c66affSColin Finck     if( getsockopt( sock, SOL_SOCKET, SO_MAX_MSG_SIZE, (char*) &datagramm_size, &size ) )
220*c2c66affSColin Finck         goto done;
221*c2c66affSColin Finck     if( datagramm_size - strlen(local_hostname) - (ident? strlen(ident) : 0) < 64 )
222*c2c66affSColin Finck         goto done;
223*c2c66affSColin Finck     if( datagramm_size > sizeof(datagramm) )
224*c2c66affSColin Finck         datagramm_size = sizeof(datagramm);
225*c2c66affSColin Finck 
226*c2c66affSColin Finck     if( atexit( closelog ) )
227*c2c66affSColin Finck         goto done;
228*c2c66affSColin Finck 
229*c2c66affSColin Finck     syslog_ident = ident;
230*c2c66affSColin Finck     syslog_facility = facility;
231*c2c66affSColin Finck     failed = FALSE;
232*c2c66affSColin Finck 
233*c2c66affSColin Finck done:
234*c2c66affSColin Finck     if( failed )
235*c2c66affSColin Finck     {
236*c2c66affSColin Finck         if( sock != INVALID_SOCKET ) closesocket( sock );
237*c2c66affSColin Finck         if( wsa_initialized ) WSACleanup();
238*c2c66affSColin Finck     }
239*c2c66affSColin Finck     initialized = !failed;
240*c2c66affSColin Finck }
241*c2c66affSColin Finck 
242*c2c66affSColin Finck /******************************************************************************
243*c2c66affSColin Finck  * setlogmask
244*c2c66affSColin Finck  *
245*c2c66affSColin Finck  * Set the log mask level.
246*c2c66affSColin Finck  */
setlogmask(int mask)247*c2c66affSColin Finck int setlogmask( int mask )
248*c2c66affSColin Finck {
249*c2c66affSColin Finck     int ret = log_mask;
250*c2c66affSColin Finck 
251*c2c66affSColin Finck     if( mask )
252*c2c66affSColin Finck         log_mask = mask;
253*c2c66affSColin Finck     return ret;
254*c2c66affSColin Finck }
255*c2c66affSColin Finck 
256*c2c66affSColin Finck /******************************************************************************
257*c2c66affSColin Finck  * syslog
258*c2c66affSColin Finck  *
259*c2c66affSColin Finck  * Generate a log message using FMT string and option arguments.
260*c2c66affSColin Finck  */
syslog(int pri,char * fmt,...)261*c2c66affSColin Finck void syslog( int pri, char* fmt, ... )
262*c2c66affSColin Finck {
263*c2c66affSColin Finck     va_list ap;
264*c2c66affSColin Finck 
265*c2c66affSColin Finck     va_start( ap, fmt );
266*c2c66affSColin Finck     vsyslog( pri, fmt, ap );
267*c2c66affSColin Finck     va_end( ap );
268*c2c66affSColin Finck }
269*c2c66affSColin Finck 
270*c2c66affSColin Finck /******************************************************************************
271*c2c66affSColin Finck  * vsyslog
272*c2c66affSColin Finck  *
273*c2c66affSColin Finck  * Generate a log message using FMT and using arguments pointed to by AP.
274*c2c66affSColin Finck  */
vsyslog(int pri,char * fmt,va_list ap)275*c2c66affSColin Finck void vsyslog( int pri, char* fmt, va_list ap )
276*c2c66affSColin Finck {
277*c2c66affSColin Finck     static char *month[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
278*c2c66affSColin Finck                             "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
279*c2c66affSColin Finck     SYSTEMTIME stm;
280*c2c66affSColin Finck     int len;
281*c2c66affSColin Finck     char *p;
282*c2c66affSColin Finck 
283*c2c66affSColin Finck     if( !(LOG_MASK( LOG_PRI( pri )) & log_mask) )
284*c2c66affSColin Finck         return;
285*c2c66affSColin Finck 
286*c2c66affSColin Finck     openlog( NULL, 0, pri & LOG_FACMASK );
287*c2c66affSColin Finck     if( !initialized )
288*c2c66affSColin Finck         return;
289*c2c66affSColin Finck 
290*c2c66affSColin Finck     if( !(pri & LOG_FACMASK) )
291*c2c66affSColin Finck         pri |= syslog_facility;
292*c2c66affSColin Finck 
293*c2c66affSColin Finck     GetLocalTime( &stm );
294*c2c66affSColin Finck     len = sprintf( datagramm, "<%d>%s %2d %02d:%02d:%02d %s %s%s: ",
295*c2c66affSColin Finck                    pri,
296*c2c66affSColin Finck                    month[ stm.wMonth - 1 ], stm.wDay, stm.wHour, stm.wMinute, stm.wSecond,
297*c2c66affSColin Finck                    local_hostname, syslog_ident? syslog_ident : "", str_pid );
298*c2c66affSColin Finck     vsnprintf( datagramm + len, datagramm_size - len, fmt, ap );
299*c2c66affSColin Finck     p = strchr( datagramm, '\n' );
300*c2c66affSColin Finck     if( p )
301*c2c66affSColin Finck         *p = 0;
302*c2c66affSColin Finck     p = strchr( datagramm, '\r' );
303*c2c66affSColin Finck     if( p )
304*c2c66affSColin Finck         *p = 0;
305*c2c66affSColin Finck 
306*c2c66affSColin Finck     sendto( sock, datagramm, strlen(datagramm), 0, (SOCKADDR*) &sa_logger, sizeof(SOCKADDR_IN) );
307*c2c66affSColin Finck }
308*c2c66affSColin Finck 
309