c語言實現收集Linux的syslog

以只讀的方式打開syslog文件,定時收集,並將日誌輸出到終端

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <time.h>
#include <sys/stat.h>


#define OS_MAXSTR 65536
#define OS_HEADER_SIZE 128
#define OS_LOG_HEADER 256

#ifdef WIN32
#define FTELL_TT "%lld"
#define FTELL_INT64 (int64_t)
#else
#define FTELL_TT "%ld"
#define FTELL_INT64 (long)
#endif

int maximum_lines = 100000;
int sample_log_length = 64;
int loop_timeout = 2;
int64_t w_ftell (FILE *x) {

#ifndef WIN32
    int64_t z = ftell(x);
#else
    int64_t z = _ftelli64(x);
#endif

    if (z < 0)  {
        printf("Ftell function failed due to [(%d)-(%s)]\n", errno, strerror(errno));
        return -1;
    } else {
        return z;
    }
}

void read_syslog(FILE * fp, const char * file) {
    fpos_t fp_pos;
    long offset = 0;
    long rbytes = 0;
    int lines = 0;
    char str[OS_MAXSTR + 1];
    int __ms = 0;
    int __ms_reported = 0;


    fgetpos(fp, &fp_pos);
    for (offset = w_ftell(fp); fgets(str, OS_MAXSTR - OS_LOG_HEADER, fp) != NULL && (!maximum_lines || lines < maximum_lines) && offset >= 0; offset += rbytes) {
        rbytes = w_ftell(fp) - offset;
        lines++;
        /* Flow control */
        if (rbytes <= 0) {
            break;
        }

        /* Get the last occurrence of \n */
        if (str[rbytes - 1] == '\n') {
            str[rbytes - 1] = '\0';

            if ((int64_t)strlen(str) != rbytes - 1)
            {
                printf("Line in '%s' contains some zero-bytes (valid=" FTELL_TT "/ total=" FTELL_TT "). Dropping line.\n", file, FTELL_INT64 strlen(str), FTELL_INT64 rbytes - 1);
                continue;
            }
        }

        /* If we didn't get the new line, because the
         * size is large, send what we got so far.
         */
        else if (rbytes == OS_MAXSTR - OS_LOG_HEADER - 1) {
            /* Message size > maximum allowed */
            __ms = 1;
            str[rbytes - 1] = '\0';
        } else {
            /* We may not have gotten a line feed
             * because we reached EOF.
             */
             if (feof(fp)) {
                /* Message not complete. Return. */
                printf("Message not complete from '%s'. Trying again: '%.*s'%s\n", file, sample_log_length, str, rbytes > sample_log_length ? "..." : "");
                fsetpos(fp, &fp_pos);
                break;
            }
        }
        printf("Reading syslog message: '%.*s'\n", (int)rbytes, str);

        /* Incorrect message size */
        if (__ms) {
            // strlen(str) >= (OS_MAXSTR - OS_LOG_HEADER - 2)
            // truncate str before logging to ossec.log

            if (!__ms_reported) {
                printf("Large message size from file '%s' (length = " FTELL_TT "): '%.*s'...", file, FTELL_INT64 rbytes, sample_log_length, str);
                __ms_reported = 1;
            } else {
                printf("Large message size from file '%s' (length = " FTELL_TT "): '%.*s'...", file, FTELL_INT64 rbytes, sample_log_length, str);
            }

            for (offset += rbytes; fgets(str, OS_MAXSTR - 2, fp) != NULL; offset += rbytes) {
                rbytes = w_ftell(fp) - offset;

                /* Flow control */
                if (rbytes <= 0) {
                    break;
                }

                /* Get the last occurrence of \n */
                if (str[rbytes - 1] == '\n') {
                    break;
                }
            }
            __ms = 0;
        }
        fgetpos(fp, &fp_pos);
        continue;
    }
}

int main(int argc, char * argv[]) {
    char * filename = "/var/log/syslog";
    if (argc == 2)  {
        filename = argv[1];
    }
    FILE * file = fopen(filename, "r");
    if (file) {
        int int_error = 0, r = 0;
        struct timeval fp_timeout;
        struct stat tmp_stat;
        while (1) {
            fp_timeout.tv_sec = loop_timeout;
            fp_timeout.tv_usec = 0;
            
            if (r = select(0, NULL, NULL, NULL, &fp_timeout) < 0) {
                int_error++;
                if (int_error >= 5) {
                    printf("system error : select\n");
                    return -1;
                }
                continue;
            }
            read_syslog(file, filename);
        }
    } else {
       printf("open %s failed\n", filename);
    }
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章