void win_start_event_channel(char *evt_log, char future, char *query) { wchar_t *wchannel = NULL; wchar_t *wquery = NULL; os_channel *channel = NULL; DWORD flags = EvtSubscribeToFutureEvents; EVT_HANDLE bookmark = NULL; EVT_HANDLE result = NULL; int status = 0; if ((channel = calloc(1, sizeof(os_channel))) == NULL) { log2file( "%s: ERROR: Could not calloc() memory for channel to start reading (%s) which returned [(%d)-(%s)]", ARGV0, evt_log, errno, strerror(errno)); goto cleanup; } channel->evt_log = evt_log; /* Create copy of event log string */ if ((channel->bookmark_name = strdup(channel->evt_log)) == NULL) { log2file( "%s: ERROR: Could not strdup() event log name to start reading (%s) which returned [(%d)-(%s)]", ARGV0, channel->evt_log, errno, strerror(errno)); goto cleanup; } /* Replace '/' with '_' */ if (strchr(channel->bookmark_name, '/')) { *(strrchr(channel->bookmark_name, '/')) = '_'; } /* Convert evt_log to Windows string */ if ((wchannel = convert_unix_string(channel->evt_log)) == NULL) { log2file( "%s: ERROR: Could not convert_unix_string() evt_log for (%s) which returned [(%d)-(%s)]", ARGV0, channel->evt_log, errno, strerror(errno)); goto cleanup; } /* Convert query to Windows string */ if (query) { if ((wquery = convert_unix_string(query)) == NULL) { log2file( "%s: ERROR: Could not convert_unix_string() query for (%s) which returned [(%d)-(%s)]", ARGV0, channel->evt_log, errno, strerror(errno)); goto cleanup; } } channel->bookmark_enabled = !future; if (channel->bookmark_enabled) { /* Create bookmark file name */ snprintf(channel->bookmark_filename, sizeof(channel->bookmark_filename), "%s/%s", BOOKMARKS_DIR, channel->bookmark_name); /* Try to read existing bookmark */ if ((bookmark = read_bookmark(channel)) != NULL) { flags = EvtSubscribeStartAfterBookmark; } } result = EvtSubscribe(NULL, NULL, wchannel, wquery, bookmark, channel, (EVT_SUBSCRIBE_CALLBACK)event_channel_callback, flags); if (result == NULL && flags == EvtSubscribeStartAfterBookmark) { result = EvtSubscribe(NULL, NULL, wchannel, wquery, NULL, channel, (EVT_SUBSCRIBE_CALLBACK)event_channel_callback, EvtSubscribeToFutureEvents); } if (result == NULL) { log2file( "%s: ERROR: Could not EvtSubscribe() for (%s) which returned (%lu)", ARGV0, channel->evt_log, GetLastError()); goto cleanup; } /* Success */ status = 1; cleanup: free(wchannel); free(wquery); if (status == 0) { free(channel->bookmark_name); free(channel); if (result != NULL) { EvtClose(result); } } if (bookmark != NULL) { EvtClose(bookmark); } return; }
/************************************************ * fetch_logfile( char *logfilename, char *bookmarkfile, int updbm_flag ) ************************************************ */ int fetch_logfile( char *logfile, char *bmfile, int updbm_flag ) { bookmark obm, nbm; /* old, new bookmark */ char *ibuf = NULL; /* input buf (--> the logfile) */ size_t ilen = 0; char *ipt = NULL; char *bmpt = NULL; /* points to first new char if bm exists */ char *obuf = NULL; /* output buf (filled backwards) */ int opos; /* first used char pos in obuf */ /* for CONV_NAGIOS3 */ int lastlinepos = 0; /* pos of beginning of lastline in obuf */ int lastlinelen = 0; /* len of lastline, excl. trailing '\' 'n' */ int r; /* write's returncode */ int i; int fd = -1; struct stat sb; char *lgfile = NULL; int llen = 0; int done = 0; if( read_bookmark( bmfile, &obm ) ) return RET_ERROR; if( (fd=open( logfile, O_RDONLY )) == -1 ) { perr( "open", logfile, errno ); return RET_ERROR; } if( fstat( fd, &sb ) == -1 ) { perr( "stat", logfile, errno ); close( fd ); return RET_ERROR; } nbm.last = (size_t) sb.st_size; nbm.mtime = sb.st_mtime; nbm.inode = sb.st_ino; /* something changed meanwhile ? */ if( obm.mtime==nbm.mtime && obm.inode==nbm.inode && obm.last==nbm.last ) { if( conv_G & CONV_OKMSG ) r = write( STDOUT_FILENO, OK_MESSAGE "\n", sizeof( OK_MESSAGE ) ); close( fd ); return RET_OK; } /*****************/ obuf = malloc( fetchlen_G+1 ); if( obuf == NULL ) { perr( "malloc", NULL, errno ); close( fd ); return RET_ERROR; } opos = fetchlen_G; *(obuf + opos) = '\0'; /* dummy: opos -> first used char in obuf */ if( conv_G & CONV_NEWLINE ) { /* when using CONV_NEWLINE the obuf is filled up like this: 1. init: write '\\' 'n' '\n' to the end (3 chars) 2. fill (copyline() ) by first prepend line contents and then prepend '\\' 'n' result: An additional '\\' 'n' at the beginning else 1. fill (copyline() ) by first prepend newline and then prepend line contents */ *(obuf + --opos) = '\n'; *(obuf + --opos) = 'n'; *(obuf + --opos) = '\\'; } lgfile = (char*)malloc( strlen(logfile) + sizeof(".X") ); if( lgfile == NULL ) { free( obuf ); perr( "malloc", NULL, errno ); close( fd ); return RET_ERROR; } /* read in all logfiles and backward fill obuf upto fetchlen_G chars */ for( i=-1; i<10; i++ ) { /* i==-1: logfile without suffix, else i==logfile suffix */ if( i==-1 ) { /* lgfile is already open and sb contains the stat */ strcpy( lgfile, logfile ); }else{ sprintf( lgfile, "%s.%1d", logfile, i ); if( (fd=open( lgfile, O_RDONLY )) == -1 ) { if( errno==ENOENT && i==0 ) { continue; /* some logrotator start with .1 */ }else if( errno==ENOENT && i>0 ) { break; }else{ perr( "open", lgfile, errno ); free( obuf ); free( lgfile ); return RET_ERROR; } } if( fstat( fd, &sb ) == -1 ) { perr( "stat", lgfile, errno ); free( obuf ); free( lgfile ); close( fd ); return RET_ERROR; } } ilen = (size_t) sb.st_size; if( ilen == 0 ) { close( fd ); if( obm.inode == sb.st_ino ) break; continue; } ibuf = mmap( NULL, ilen, PROT_READ, MAP_SHARED, fd, (off_t)0 ); if( ibuf == MAP_FAILED ) { perr( "mmap", lgfile, errno ); free( obuf ); free( lgfile ); close( fd ); return RET_ERROR; } #ifdef HAS_MADVISE if( madvise( ibuf, ilen, MADV_RANDOM ) ) { perr( "madvise", NULL, errno ); free( obuf ); free( lgfile ); close( fd ); munmap( ibuf, ilen ); return RET_ERROR; } #endif /* check for old bookmark */ bmpt = NULL; if( obm.inode == sb.st_ino ) { bmpt = ibuf+obm.last; } /* scan backwards for lines but the first */ done = 0; for( llen=1,ipt=ibuf+ilen-2; ipt>=ibuf; llen++,ipt-- ) { if( *ipt=='\n' ) { if( ipt+1<bmpt ) { done=1; break; } opos = copyline( opos, obuf, ipt+1, llen ); if( opos==0 ) { done=1; break; } llen = 0; } } /* copy first line ? */ if( ipt+1==ibuf && done==0 ) { if( ipt+1<bmpt ) { done=1; } else{ opos = copyline( opos, obuf, ipt+1, llen ); } if( opos==0 ) { done=1; } } munmap( ibuf, ilen ); close( fd ); if( done ) break; if( bmpt ) break; /* processed a bookmarked file? --> finito */ } if( updbm_flag ) { if( write_bookmark( bmfile, &nbm ) ) return RET_ERROR; } /* if in Nagios3 mode: prepend short message (the last line fetched) */ if( conv_G & CONV_NAGIOS3 ) { /* Nagios2 --> Nagios3 changed accepted format for plugin output. * Nagios2 accepted a line containing one or more '\'+'n' as a single * line. Nagios3 now supports multiline output, and as a result, lines * containing '\'+'n' are now handled as multiline messages (as well as * messages having '\n'). The new multiline format is: * SHORT_MESSAGE | OPTIONAL_PERFORMANCE_DATA * LONG_MESSAGE_LINE_1 * LONG_MESSAGE_LINE_2 * ... * LONG_MESSAGE_LINE_N * * In Nagios3 mode fetchlog copies LONG_MESSAGE_LINE_N as SHORT_MESSAGE * and leaves OPTIONAL_PERFORMANCE_DATA empty */ int oidx = fetchlen_G - 4; /* in obuf: last char, last line */ lastlinepos = oidx + 1; /* fallback value: empty line at end */ lastlinelen = 0; /* fallback value: empty line at end */ /* determine lastlinepos and lastlinelen */ while( oidx > 0 ) { if( *(obuf + oidx) == 'n' && *(obuf + oidx -1) == '\\' ) { lastlinepos = oidx + 1; lastlinelen = fetchlen_G - lastlinepos - 3; /* 3: \ n \n */ break; } oidx--; } /* case: obuf has enough room for SHORT_MESSAGE */ if( lastlinelen + 1 <= opos ) { /* +1 = '|' */ *(obuf + --opos) = '|'; memmove( obuf+opos-lastlinelen, obuf+lastlinepos, lastlinelen ); opos -= lastlinelen; /* case: obuf too small: SHORT_MESSAGE and fetched messages overlap, * but not LONG_MESSAGE_LINE_N */ }else if( lastlinelen + 6 <= lastlinepos ) { /* +6 = '|\n...' */ memmove( obuf, obuf+lastlinepos, lastlinelen ); *(obuf + lastlinelen + 0 ) = '|'; *(obuf + lastlinelen + 1 ) = '\\'; *(obuf + lastlinelen + 2 ) = 'n'; *(obuf + lastlinelen + 3 ) = '.'; *(obuf + lastlinelen + 4 ) = '.'; if( *(obuf + lastlinelen + 5 ) != '\\' ) { *(obuf + lastlinelen + 5 ) = '.'; } opos = 0; /* case: obuf too small: SHORT_MESSAGE and fetched messages overlap, * including LONG_MESSAGE_LINE_N */ }else{ memmove( obuf+lastlinepos+2, obuf+lastlinepos, lastlinelen ); opos = lastlinepos + 2; } } /* only return a message if there is something to print */ if( ((conv_G & CONV_NEWLINE)==0 && fetchlen_G-opos==0 ) || ((conv_G & CONV_NEWLINE)!=0 && ( ((conv_G & CONV_NAGIOS3)== 0 && fetchlen_G-opos==3 ) || ((conv_G & CONV_NAGIOS3)!= 0 && fetchlen_G-opos==4 ) ) ) ) { if( conv_G & CONV_OKMSG ) { r = write( STDOUT_FILENO, OK_MESSAGE "\n", sizeof( OK_MESSAGE ) ); } i = RET_OK; }else{ r = write( STDOUT_FILENO, obuf+opos,fetchlen_G-opos); i = RET_NEWMSG; } free( obuf ); free( lgfile ); return i; } /* fetch_logfile() */