Back to index

nagios-plugins  1.4.16
fetchlog.c
Go to the documentation of this file.
00001 /*****************************************************************************
00002  *
00003  * fetchlog.c - logfile fetcher: pick up last new messages of a logfile
00004  *
00005  * Copyright (c) 2002 Alexander Haderer (alexander.haderer@charite.de)
00006  *
00007  *  Last Update:      $Author: afrika $
00008  *  Update Date:      $Date: 2002/12/17 18:40:05 $
00009  *  Source File:      $Source: /home/cvsroot/tools/fetchlog/fetchlog.c,v $
00010  *  CVS/RCS Revision: $Revision: 1.3 $
00011  *  Status:           $State: Exp $
00012  *
00013  *  CVS/RCS Log at end of file
00014  *
00015  * License:
00016  *
00017  * This program is free software; you can redistribute it and/or modify
00018  * it under the terms of the GNU General Public License as published by
00019  * the Free Software Foundation; either version 2 of the License, or
00020  * (at your option) any later version.
00021  *
00022  * This program is distributed in the hope that it will be useful,
00023  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00024  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00025  * GNU General Public License for more details.
00026  *
00027  * You should have received a copy of the GNU General Public License
00028  * along with this program; if not, write to the Free Software
00029  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00030  *
00031  *****************************************************************************/
00032 
00033 
00034 #include <stdio.h>   /* sprintf */
00035 #include <stdlib.h>  /* atoi */
00036 #include <ctype.h>   /* isalpha */
00037 #include <string.h>  /* strcat, strcpy */
00038 #include <fcntl.h>   /* open close */
00039 #include <sys/types.h>      /* stat */
00040 #include <sys/stat.h>       /* stat */
00041 #include <sys/mman.h>       /* mmap, madvise */
00042 #include <unistd.h>  /* access */
00043 #include <errno.h>   /* errno */
00044 
00045 /*************************************************
00046  * constants
00047  *************************************************/
00048 
00049 #define LINELEN  160        /* max length of a logfile line we will read */
00050 
00051 #define MIN_FIRSTCOL 1      /* Min first col for fetching      */
00052 #define MAX_LASTCOL  LINELEN /* Max last col for fetching      */
00053 #define MIN_COLS     20     /* Min no of cols to fetch  */
00054 #define MIN_FETCHLEN    50  /* Min length of fetched data */
00055 #define MAX_FETCHLEN    2000       /* Max length of fetched data */
00056 
00057 #define OK_MESSAGE   "OK: no messages"
00058 #define ERR_MESSAGE  "ERROR: fetchlog: "
00059 
00060 /* suffix for temp bookmarkfile:  mkstemp() template */
00061 #define FETCH_FILE_SUFFIX "XXXXXX"  
00062 
00063 /* conversion flags */
00064 #define CONV_NONE    0
00065 #define CONV_BRACKET 1
00066 #define CONV_PERCENT 2
00067 #define CONV_NEWLINE 4
00068 #define CONV_OKMSG   8
00069 #define CONV_SHELL   16
00070 #define CONV_ALL     (CONV_BRACKET|CONV_PERCENT|CONV_NEWLINE|CONV_OKMSG|CONV_SHELL )
00071 
00072 /* return/exit codes */
00073 #ifdef PRE_093_EXIT_CODES
00074 /* RET_ERROR and RET_NEWMSG pre 0.93 version                   Nagios:*/
00075 #define RET_OK              0      /* ok, no messages          ok */
00076 #define RET_NEWMSG   1      /* logfile has new messages        warn */
00077 #define RET_ERROR    2      /* internal error           critical */
00078 #define RET_PARAM    (-1)   /* wrong parameter, print help */
00079 #else
00080 /* 0.93 and later (Nagios compliant)                           Nagios:*/
00081 #define RET_OK              0      /* ok, no messages          ok */
00082 #define RET_ERROR    1      /* internal error           warn */
00083 #define RET_NEWMSG   2      /* logfile has new messages critical */
00084 #define RET_PARAM    3      /* wrong parameter, print help */
00085 #endif
00086 
00087 /* version info */
00088 #ifdef PRE_093_EXIT_CODES
00089 #define FL_VERSION (FETCHLOG_VERSION_NO " (PRE_0.93_EXIT_CODES)")
00090 #else
00091 #define FL_VERSION FETCHLOG_VERSION_NO
00092 #endif
00093 
00094 /*************************************************
00095  * typedefs
00096  *************************************************/
00097 typedef struct {
00098     long start;             /* pos first char of the very last line fetched */
00099     long last;              /* one behind the last char of the very last line f. */
00100     long linelen;    /* len of stored line 'line' */
00101     char line[LINELEN];     /* the very last line prev. fetched */
00102     time_t mtime;    /* mtime of logfile when this bookmark was valid */
00103 } bookmark;
00104 
00105 /*************************************************
00106  * prototypes
00107  *************************************************/
00108 void usage( void );
00109 int fetch_logfile( char *logfilename, char *bookmarkfile, int updbm_flag );
00110 int read_bookmark( char *bmfile, bookmark *bm );
00111 int write_bookmark( char *bmfile, bookmark *bm );
00112 int copyline( int opos, char *obuf, char *ipt, int illen );
00113 int check_farg( char *farg, int *conv );
00114 void perr( char *msg1, char *msg2, int err );
00115 
00116 /*************************************************
00117  * globals
00118  *************************************************/
00119 
00120 /* fetching */
00121 int firstcol_G = MIN_FIRSTCOL;
00122 int lastcol_G = MAX_LASTCOL;
00123 int fetchlen_G = MAX_FETCHLEN;
00124 int conv_G = CONV_NONE;
00125 
00126 
00127 
00128 /*************************************************
00129  * code...
00130  *************************************************/
00131 
00132 /************************************************
00133  * perr( .. )
00134  * print error message to stdout with respect to fetchlen_G
00135  ************************************************
00136  */
00137 void perr( char *msg1, char *msg2, int err ) {
00138     char *msg = NULL;
00139     int len = 0;
00140 
00141     if( !msg1 ) return;
00142 
00143     len = sizeof( ERR_MESSAGE ) + strlen( msg1 ) + 1;   /* 1 == '\n' */
00144     if( msg2 ) len += strlen( msg2 ) + 2;        /* 2 == ': ' */
00145     if( err ) len += strlen( strerror( err ) ) + 2;     /* 2 == ': ' */
00146 
00147     if( (msg=malloc( len ) ) == NULL ) { exit( RET_ERROR ); }
00148 
00149     strcpy( msg, ERR_MESSAGE );
00150     strcat( msg, msg1 );
00151     if( msg2 ) {
00152        strcat( msg, ": " );
00153        strcat( msg, msg2 );
00154     }
00155     if( err ) {
00156        strcat( msg, ": " );
00157        strcat( msg, strerror( err ) );
00158     }
00159     if( len-1 <= fetchlen_G ) {
00160        strcat( msg, "\n" );
00161     }else{
00162        msg[fetchlen_G-1] = '\n';
00163        msg[fetchlen_G-2] = '~';
00164        len = fetchlen_G + 1;
00165     }
00166     write( STDOUT_FILENO, msg, len-1 );
00167     free( msg );
00168 }
00169 
00170 /************************************************
00171  * read_bookmark( char *bmfile, bookmark *bm );
00172  * return: 0: ok    1: error
00173  ************************************************
00174  */
00175 int read_bookmark( char *bmfile, bookmark *bm ) {
00176     int fd = -1;
00177     struct stat sb;
00178 
00179     fd = open( bmfile, O_RDONLY );
00180     if( fd == -1 ) {
00181        if( errno == ENOENT ) {
00182            /* no bookmarkfile --> acts like infinite old bookmarkfile */
00183            bm->start = -1;
00184            bm->last = -1;
00185            bm->linelen = 0;
00186            bm->line[0] = '\0';
00187            bm->mtime = 0;
00188            return 0;
00189        }else{
00190            perr( "open", bmfile, errno );
00191            return 1;
00192        }
00193     }
00194     if( fstat( fd, &sb ) == -1 ) {
00195        perr( "stat", bmfile, errno );
00196        close( fd );
00197        return 1;
00198     }
00199     if( (int)sb.st_size != sizeof(bookmark) || 
00200        ((sb.st_mode & S_IFMT) != S_IFREG) ) 
00201     {
00202        perr( "no file/wrong size", bmfile, 0);
00203        close( fd );
00204        return 1;
00205     }
00206     if( read( fd, bm, sizeof(bookmark)) != sizeof( bookmark ) ) {
00207        perr( "file to short", bmfile, 0 );
00208        close( fd );
00209        return 1;
00210     }
00211     close( fd );
00212     
00213     if( bm->start < 0 || bm->last < 0 || 
00214        bm->linelen < 0 || bm->linelen > LINELEN ) 
00215     {
00216        perr( "file damaged", bmfile, 0 );
00217        return 1;
00218     }
00219     return 0;  /* ok */
00220 
00221 }   /* read_bookmark() */
00222 
00223 
00224 /************************************************
00225  * write_bookmark( char *bmfile, bookmark *bm );
00226  * return: 0: ok    1: error
00227  ************************************************
00228  */
00229 int write_bookmark( char *bmfile, bookmark *bm ) {
00230 
00231     char *nbmfile = NULL; /* new bmfile (a tmp file to be renamed to bmfile) */
00232     int nbmfd = -1;
00233 
00234     nbmfile = (char*)malloc( strlen(bmfile) + sizeof(FETCH_FILE_SUFFIX) );
00235     if( nbmfile == NULL ) {
00236        perr("malloc", NULL, errno );
00237        return 1;
00238     }
00239     strcpy( nbmfile, bmfile );
00240     strcat( nbmfile, FETCH_FILE_SUFFIX );
00241     nbmfd = mkstemp( nbmfile );
00242     if( nbmfd == -1 ) {
00243        perr( "mkstemp", nbmfile, errno );
00244        free( nbmfile );
00245        return 1;
00246     }
00247     if( write( nbmfd, bm, sizeof( bookmark ) ) != sizeof( bookmark )  ) {
00248        perr( "write", nbmfile, errno );
00249        close( nbmfd );
00250        unlink( nbmfile );
00251        free( nbmfile );
00252        return 1;
00253     }
00254     close( nbmfd );
00255     if( rename( nbmfile, bmfile ) == -1 ) { 
00256        perr( "rename tmpfile to", bmfile, errno );
00257        unlink( nbmfile );
00258        free( nbmfile );
00259        return 1;
00260     }
00261     free( nbmfile );
00262     return 0; /* ok */
00263     
00264 }   /* write_bookmark() */
00265 
00266 
00267 
00268 /************************************************
00269  * fetch_logfile( char *logfilename, char *bookmarkfile, int updbm_flag ) 
00270  ************************************************
00271  */
00272 int fetch_logfile( char *logfile, char *bmfile, int updbm_flag ) {
00273 
00274     bookmark obm, nbm;             /* old, new bookmark */
00275 
00276     char *ibuf = NULL;             /* input buf (--> the logfile) */
00277     size_t ilen = 0;
00278     char *ipt  = NULL;
00279     char *bmpt = NULL;             /* points to first new char if bm exists */
00280 
00281     char *obuf = NULL;             /* output buf (filled backwards) */
00282     int opos;               /* first used char pos in obuf */
00283 
00284     int i;
00285     int fd = -1;
00286     struct stat sb;
00287     char *lgfile = NULL;
00288     int llen = 0;
00289     int done = 0;
00290     int logfiletouch = 0;   /* 1: logfile only touched, nothing appended */
00291 
00292     memset( obm.line, 0, LINELEN );
00293     memset( nbm.line, 0, LINELEN );
00294     nbm.start = -1;
00295     nbm.last = -1;
00296     nbm.linelen = 0;
00297     nbm.mtime = 0;
00298 
00299     if( read_bookmark( bmfile, &obm ) ) return RET_ERROR;
00300 
00301     if( (fd=open( logfile, O_RDONLY ))  == -1 ) {
00302        perr( "open", logfile, errno );
00303        return RET_ERROR;
00304     }
00305     if( fstat( fd, &sb ) == -1 ) {
00306        perr( "stat", logfile, errno );
00307        close( fd );
00308        return RET_ERROR;
00309     }
00310     if( obm.mtime == sb.st_mtime ) {
00311        if( conv_G & CONV_OKMSG ) 
00312            write( STDOUT_FILENO, OK_MESSAGE "\n", sizeof( OK_MESSAGE ) );
00313        close( fd );
00314        return RET_OK;
00315     }
00316     nbm.mtime = sb.st_mtime;
00317 
00318     /*****************/
00319 
00320     obuf = malloc( fetchlen_G+1 );
00321     if( obuf == NULL ) {
00322        perr( "malloc", NULL,  errno );
00323        close( fd );
00324        return RET_ERROR;
00325     }
00326     opos = fetchlen_G;
00327     *(obuf + opos) = '\0';  /* dummy: opos -> first used char in obuf */
00328     if( conv_G & CONV_NEWLINE ) {
00329        /* when using CONV_NEWLINE the obuf is filled up like this:
00330             1. init: write '\\'  'n'  '\n' to the end (3 chars)
00331             2. fill (copyline() ) by first prepend line contents and 
00332               then prepend '\\' 'n'
00333             result: An additional '\\'  'n'  at the beginning 
00334           else
00335             1. fill (copyline() ) by first prepend newline and then prepend 
00336               line contents 
00337        */
00338        *(obuf + --opos) = '\n';
00339        *(obuf + --opos) = 'n';
00340        *(obuf + --opos) = '\\';
00341     }
00342 
00343     lgfile = (char*)malloc( strlen(logfile) + sizeof(".X") );
00344     if( lgfile == NULL ) {
00345        free( obuf );
00346        perr( "malloc", NULL, errno );
00347        close( fd );
00348        return RET_ERROR;
00349     }
00350 
00351     /* read in all logfiles and backward fill obuf upto fetchlen_G chars */
00352 
00353     for( i=-1; i<10; i++ ) {
00354        /* i==-1: logfile without suffix, else i==logfile suffix */
00355        if( i==-1 ) {
00356            /* lgfile is already open and sb contains the stat */
00357            strcpy( lgfile, logfile );
00358        }else{
00359            sprintf( lgfile, "%s.%1d", logfile, i );
00360        
00361            if( (fd=open( lgfile, O_RDONLY )) == -1 ) {
00362               if( errno==ENOENT && i>-1 ) { break; }
00363               else{
00364                   perr( "open", lgfile, errno );
00365                   free( obuf ); free( lgfile );
00366                   return RET_ERROR;
00367               }
00368            }
00369            if( fstat( fd, &sb ) == -1 ) {
00370               perr( "stat", lgfile, errno );
00371               free( obuf ); free( lgfile ); close( fd );
00372               return RET_ERROR;
00373            }
00374        }
00375        
00376        ilen = (size_t) sb.st_size;
00377        if( ilen == 0 ) {
00378            close( fd );
00379            continue;
00380        }
00381        ibuf = mmap( NULL, ilen, PROT_READ, MAP_SHARED, fd, (off_t)0 );
00382        if( ibuf == MAP_FAILED ) {
00383            perr( "mmap", lgfile, errno );
00384            free( obuf ); free( lgfile ); close( fd );
00385            return RET_ERROR;
00386        }
00387        
00388 #ifndef NO_MADVISE
00389        if( madvise( ibuf, ilen, MADV_RANDOM ) ) {
00390            perr( "madvise", NULL, errno );
00391            free( obuf ); free( lgfile ); close( fd );
00392            munmap( ibuf, ilen );
00393            return RET_ERROR;
00394        }
00395 #endif
00396        
00397        /* setup data for new bookmark */
00398        if( nbm.start == -1 ) {
00399            for( ipt=ibuf+ilen-2; ipt>=ibuf; ipt-- ) {
00400               if( *ipt=='\n' ) break;
00401            }
00402            nbm.last = ilen;
00403            nbm.start = ipt-ibuf+1;
00404            nbm.linelen = ibuf+ilen-(ipt+1);
00405            if( nbm.linelen > LINELEN ) nbm.linelen = LINELEN;
00406            memcpy( nbm.line, ipt+1, nbm.linelen );
00407        }
00408 
00409        /* check for old bookmark */
00410        bmpt = NULL;
00411        if( obm.mtime && obm.start+obm.linelen<=ilen && 
00412            !memcmp( obm.line, ibuf+obm.start, obm.linelen ) ) 
00413        {
00414            /* stop if 1st logfile modified but nothing append since last bm */
00415            if( i==-1 && obm.last==ilen ) { 
00416               logfiletouch = 1;
00417               munmap( ibuf, ilen );
00418               close( fd );
00419               break;
00420            }else{
00421               bmpt = ibuf+obm.last;
00422            }
00423        }
00424 
00425        /* scan backwards for lines but the first */
00426        done = 0;
00427        for( llen=1,ipt=ibuf+ilen-2; ipt>=ibuf; llen++,ipt-- ) {
00428            if( *ipt=='\n' ) {
00429               if( ipt+1<bmpt ) { done=1; break; }
00430               opos = copyline( opos, obuf, ipt+1, llen );
00431               if( opos==0 ) { done=1; break; }
00432               llen = 0;
00433            }
00434        }
00435        if( ipt+1==ibuf && done==0 ) {     /* copy first line ? */
00436            if( ipt+1<bmpt ) { done=1; }
00437            else{ opos = copyline( opos, obuf, ipt+1, llen ); }
00438            if( opos==0 ) { done=1; }
00439        }
00440 
00441        munmap( ibuf, ilen );
00442        close( fd );
00443        if( done ) break;
00444     }
00445 
00446     if( updbm_flag && nbm.start != -1 ) {
00447        if( write_bookmark( bmfile, &nbm ) ) return RET_ERROR;
00448     }
00449 
00450     if( logfiletouch ) {
00451        if( conv_G & CONV_OKMSG ) 
00452            write( STDOUT_FILENO, OK_MESSAGE "\n", sizeof( OK_MESSAGE ) );
00453        free( obuf ); free( lgfile );
00454        return RET_OK;
00455     }else{
00456        write( STDOUT_FILENO, obuf+opos,fetchlen_G-opos);
00457     }
00458 
00459     free( obuf ); free( lgfile );
00460     return RET_NEWMSG;
00461 
00462 }   /* fetch_logfile() */
00463 
00464 
00465 /************************************************
00466  * copyline( int opos, char *obuf, char *ipt, int illen );
00467  * trim new line (ipt, illen), copy it to obuf, convert it, return new opos
00468  ************************************************
00469  */
00470 int copyline( int opos, char *obuf, char *ipt, int illen ) {
00471 
00472     char *p = NULL;
00473     int len = 0;
00474     int i;
00475 
00476     if( conv_G & CONV_NEWLINE ) {
00477        /* fill obuf: 
00478           prepend  concat( '\\' + 'n' + iline )   (newline sequence first) */
00479        if( opos > 2 ) {
00480            if( illen <= firstcol_G ) {
00481               *(obuf+opos-1) = 'n'; *(obuf+opos-2) = '\\'; 
00482               opos -= 2;
00483            }else{
00484               len = illen - 1;  /* -1 : skip newline */
00485               /* Note: lastcol_G means 'show inklusive column lastcol' */
00486               if( len > lastcol_G+1 )  len = lastcol_G;
00487               len -= firstcol_G - 1;
00488               if( len+2 > opos ) {
00489                   memcpy( obuf+2, ipt+firstcol_G-1+len+2-opos, opos-2 );
00490                   len = opos - 2;
00491               }else{
00492                   memcpy( obuf+opos-len, ipt+firstcol_G-1, len );
00493               }
00494               if( illen-1 > lastcol_G+1 ) *(obuf+opos-1) = '~';
00495               opos -= len+2;
00496               *(obuf+opos+1) = 'n'; 
00497               *(obuf+opos+0) = '\\'; 
00498            }
00499        }else{
00500            opos = 0;
00501        }
00502        if( opos==0 ) {
00503            p = obuf;
00504            *p++='\\'; *p++='n'; *p++='.'; *p++='.'; *p++='.';
00505            if( obuf[5]=='n' ) { *p++='.'; }
00506        }
00507     }else{
00508        /* without newline conversion */
00509 
00510        /* fill obuf: 
00511           prepend concat( iline + '\n' )  (newline char last) */
00512        if( opos > 1 ) {
00513            if( illen <= firstcol_G ) {
00514               *(obuf+opos-1) = '\n'; 
00515               opos -= 1;
00516            }else{
00517               len = illen - 1;  /* -1 : skip newline */
00518               /* Note: lastcol_G means 'show inklusive column lastcol' */
00519               if( len > lastcol_G+1 )  len = lastcol_G;
00520               len -= firstcol_G - 1;
00521               if( len+1 > opos ) {
00522                   memcpy( obuf, ipt+firstcol_G-1+len+1-opos, opos-1 );
00523                   len = opos - 1;
00524               }else{
00525                   memcpy( obuf+opos-len-1, ipt+firstcol_G-1, len );
00526               }
00527               *(obuf+opos-1) = '\n'; 
00528               if( illen-1 > lastcol_G+1 ) *(obuf+opos-2) = '~';
00529               opos -= len+1;
00530            }
00531        }else{
00532            opos = 0;
00533        }
00534        if( opos==0 ) {
00535            p = obuf;
00536            *p++='.'; *p++='.'; *p++='.';
00537        }
00538     }
00539 
00540     p = obuf+opos;
00541     if( conv_G & CONV_NEWLINE )  p += 2;  /* +2: skip '\\' 'n' */
00542 
00543     if( conv_G & CONV_PERCENT ) {
00544        for( i=0; i<len; i++ ) {
00545            if( *(p+i) == '%' ) *(p+i) = 'p';
00546        }
00547     }
00548 
00549     if( conv_G & CONV_BRACKET ) {
00550        for( i=0; i<len; i++ ) {
00551            if(      *(p+i) == '<' ) *(p+i) = '(';
00552            else if( *(p+i) == '>' ) *(p+i) = ')';
00553        }
00554     }
00555 
00556     if( conv_G & CONV_SHELL ) {
00557        for( i=0; i<len; i++ ) {
00558            if(      *(p+i) == '$' )  *(p+i) = '_';
00559            else if( *(p+i) == '\'' ) *(p+i) = '_';
00560            else if( *(p+i) == '\"' ) *(p+i) = '_';
00561            else if( *(p+i) == '`' )  *(p+i) = '_';
00562            else if( *(p+i) == '^' )  *(p+i) = '_';
00563            else if( *(p+i) == '\\' ) *(p+i) = '/';
00564        }
00565     }
00566 
00567     return opos;
00568 
00569 }   /* copyline() */
00570 
00571 
00572 /************************************************
00573  * check_farg( char *farg ) 
00574  * check if -f arg is in proper format for sccanf(): nnn:nnn:nnnn:XXXXX
00575  ************************************************
00576  */
00577 int check_farg( char *farg, int *conv ) {
00578     char *pt = farg;
00579     int numdig = 0;
00580     int numc = 0;
00581 
00582     *conv = 0;
00583 
00584     for( numdig=0 ; *pt; pt++ ) {
00585        if( isdigit( (int) *pt ) ) numdig++;
00586        else if( *pt==':' ) break;
00587        else return 1;
00588     }
00589     if( numdig <1 || numdig > 3 ) return 1;
00590 
00591     for( pt++,numdig=0 ; *pt; pt++ ) {
00592        if( isdigit( (int) *pt ) ) numdig++;
00593        else if( *pt==':' ) break;
00594        else return 1;
00595     }
00596     if( numdig <1 || numdig > 3 ) return 1;
00597 
00598     for( pt++,numdig=0 ; *pt; pt++ ) {
00599        if( isdigit( (int) *pt ) ) numdig++;
00600        else if( *pt==':' ) break;
00601        else return 1;
00602     }
00603     if( numdig <1 || numdig > 4 ) return 1;
00604 
00605     for( pt++,numc=0 ; *pt; pt++ ) {
00606        if     ( *pt=='b' ) { *conv |= CONV_BRACKET; numc++; }
00607        else if( *pt=='p' ) { *conv |= CONV_PERCENT; numc++; }
00608        else if( *pt=='n' ) { *conv |= CONV_NEWLINE; numc++; }
00609        else if( *pt=='o' ) { *conv |= CONV_OKMSG;   numc++; }
00610        else if( *pt=='s' ) { *conv |= CONV_SHELL;   numc++; }
00611        else return 1;
00612     }
00613     if( numc > 5 ) return 1;
00614     return 0; /* ok */
00615 
00616 }   /* check_farg() */
00617 
00618 /*************************************************/
00619 void usage( void ) {
00620 
00621     printf(
00622        "fetchlog - fetch the last new log messages - version %s \n\n"
00623        "   usage 1: fetchlog -f firstcol:lastcol:len:conv logfile bmfile\n"
00624        "   usage 2: fetchlog -F firstcol:lastcol:len:conv logfile bmfile\n"
00625        "   usage 3: fetchlog [ -V | -h ] \n\n"
00626        "1: Read all messages of <logfile> newer than the "
00627        "bookmark in <bmfile>. Print\n"
00628        "at most <len> bytes from column "
00629        "<firstcol> upto column <lastcol> of last new \nmessages to stdout. "
00630        "Adds '...' characters when skipping old lines or '~' when\n"
00631        "cutting long lines. <conv> sets output conversion:\n"
00632        "      'b': convert < and > to ( and ) for safe HTML output\n"
00633        "      'p': convert %% to p for safe printf output\n"
00634        "      's': convert $'\"`^\\ to _____/ for safe shell parameter input\n"
00635        "      'n': convert newline to \\n for single line output\n"
00636        "      'o': show '%s' message if no new messages\n"
00637        "  0  <  <firstcol>  <  <lastcol>  <  %d\n"
00638        "  <lastcol> - <firstcol> > %d \n"
00639        "  <len> valid range %d..%d\n"
00640        "  <conv> is zero ore more of 'bpsno' \n"
00641        "  <logfile> absolute path to logfile\n"
00642        "  <bmfile> absolute path to bookmarkfile\n"
00643        "2: like 1 and update <bmfile> to mark fetched messages as 'read'\n"
00644        "3: print version (-V) or print this help message (-h) \n"
00645        , FL_VERSION, 
00646        OK_MESSAGE,MAX_LASTCOL+1,MIN_COLS-1,MIN_FETCHLEN, MAX_FETCHLEN
00647        );
00648 
00649 } /* usage() */
00650 
00651 /*************************************************/
00652 
00653 int main(int argc, char **argv)
00654 {
00655     int  ret=0;
00656 
00657     /* check args */
00658     if (argc == 2) {
00659        if( argv[1][0] == '-' && argv[1][1] == 'V' ) {
00660            printf( "fetchlog version %s \n", FL_VERSION );
00661            exit( RET_PARAM );
00662        }
00663     }else if (argc == 5) {
00664        if( argv[1][0] == '-' && 
00665            argv[3][0] == '/' && isalpha((int)argv[3][1]) &&
00666            argv[4][0] == '/' && isalpha((int)argv[4][1]) ) {
00667            if( argv[1][1] == 'f' || argv[1][1] == 'F' ) {
00668               if( check_farg( argv[2], &conv_G ) ) {
00669                   usage();
00670                   exit( RET_PARAM );
00671               }
00672               ret = sscanf( argv[2], "%3d:%3d:%4d", 
00673                            &firstcol_G, &lastcol_G, &fetchlen_G );
00674               if( ret != 3 ) {
00675                   usage();
00676                   exit( RET_PARAM );
00677               }
00678               if( firstcol_G >= MIN_FIRSTCOL &&
00679                   lastcol_G >= firstcol_G + MIN_COLS &&
00680                   lastcol_G <= MAX_LASTCOL &&
00681                   fetchlen_G >= MIN_FETCHLEN &&
00682                   fetchlen_G <= MAX_FETCHLEN ) {
00683                   
00684                   if( argv[1][1] == 'f' ) {
00685                      exit( fetch_logfile( argv[3], argv[4], 0 ) );
00686                   }else{
00687                      exit( fetch_logfile( argv[3], argv[4], 1 ) );
00688                   }
00689               }
00690            }
00691        }
00692     }
00693     usage();
00694     exit( RET_PARAM );
00695 
00696 }   /* main() */
00697 
00698 /*
00699  * CVS/RCS Log:
00700  * $Log: fetchlog.c,v $
00701  * Revision 1.3  2002/12/17 18:40:05  afrika
00702  * exit code now nagios compatible
00703  *
00704  * Revision 1.2  2002/12/17 18:04:48  afrika
00705  * - inserted CVS tags
00706  * - change docs: Netsaint --> Nagios(TM)
00707  *
00708  *
00709  */
00710