以只读的方式打开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;
}