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