コード例 #1
0
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;
}
コード例 #2
0
ファイル: fetchlog.c プロジェクト: dinuschen/fetchlog
/************************************************
 * 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() */