Last active
October 24, 2020 17:47
-
-
Save legionus/175563beed3f3f22c2a9f7734b66e685 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <sys/uio.h> | |
#include <unistd.h> | |
#include <limits.h> | |
#include <stdio.h> | |
#include <string.h> | |
#include <error.h> | |
enum record_fields_type { | |
RECORD_FIELD_TIME = 0, | |
RECORD_FIELD_HOST, | |
RECORD_FIELD_MSG, | |
RECORD_FIELD_COUNTS, | |
}; | |
#define RECORD_FIELD_REPEAT_MAX 5 | |
#define RECORD_FIELDS_MAX RECORD_FIELD_COUNTS * RECORD_FIELD_REPEAT_MAX | |
#define RECORDS_MAX RECORD_FIELDS_MAX * 2 + 1 | |
long int iov_max; | |
struct format { | |
char line[LINE_MAX]; | |
struct iovec record[RECORDS_MAX]; | |
struct { | |
enum record_fields_type source; | |
struct iovec *destination; | |
} rules[RECORD_FIELDS_MAX]; | |
}; | |
static void set_format_record(struct format *fmt, int i, char *s, size_t n) | |
{ | |
if (i >= iov_max) | |
error(1, 0, "too many parts in the record format"); | |
fmt->record[i].iov_base = s; | |
fmt->record[i].iov_len = n; | |
} | |
static void set_format_rule(struct format *fmt, int i, | |
enum record_fields_type t, struct iovec *v) | |
{ | |
if (i >= RECORD_FIELDS_MAX) | |
error(1, 0, "too many fields in the record"); | |
fmt->rules[i].source = t; | |
fmt->rules[i].destination = v; | |
} | |
static void parse_format(struct format *fmt, char *line) | |
{ | |
char *cur, *ptr; | |
int rec_nr, rule_nr, special; | |
strncpy(fmt->line, line, LINE_MAX); | |
memset(fmt->record, 0, sizeof(fmt->record[0]) * RECORDS_MAX); | |
memset(fmt->rules, 0, sizeof(fmt->rules[0]) * RECORD_FIELDS_MAX); | |
special = rec_nr = rule_nr = 0; | |
cur = ptr = fmt->line; | |
while (*ptr != '\0') { | |
enum record_fields_type ruletype; | |
if (special) { | |
switch (*ptr) { | |
case 't': ruletype = RECORD_FIELD_TIME; break; | |
case 'h': ruletype = RECORD_FIELD_HOST; break; | |
case 'm': ruletype = RECORD_FIELD_MSG; break; | |
case '%': | |
special = 0; | |
goto create_special; | |
default: | |
error(1, 0, "unexpected special: '%%%c'", *ptr); | |
} | |
special = 0; | |
goto create_rule; | |
} else if (*ptr == '%') | |
special = 1; | |
next: | |
ptr++; | |
continue; | |
create_rule: | |
set_format_record(fmt, rec_nr++, cur, (ptr - cur - 1)); | |
set_format_rule(fmt, rule_nr++, ruletype, fmt->record + rec_nr); | |
set_format_record(fmt, rec_nr++, NULL, 0); | |
cur = ptr + 1; | |
goto next; | |
create_special: | |
set_format_record(fmt, rec_nr++, cur, (ptr - cur - 1)); | |
cur = ptr; | |
goto next; | |
} | |
if (special) | |
error(1, 0, "unexpected '%%' at the end of line"); | |
if (cur != ptr) | |
set_format_record(fmt, rec_nr++, cur, (ptr - cur)); | |
} | |
static char *curtime = (char *) "May 2 12:34:56"; | |
static char *curhost = (char *) "localhost"; | |
static char *curmsg = (char *) "TEST"; | |
int main(int argc, char **argv) | |
{ | |
struct format fmt; | |
iov_max = sysconf(_SC_IOV_MAX); | |
printf("%s\n", argv[1]); | |
parse_format(&fmt, argv[1]); | |
for (int i = 0; i < RECORD_FIELDS_MAX; i++) { | |
if (!fmt.rules[i].destination) | |
continue; | |
switch (fmt.rules[i].source) { | |
case RECORD_FIELD_TIME: | |
fmt.rules[i].destination->iov_base = curtime; | |
fmt.rules[i].destination->iov_len = strlen(curtime); | |
break; | |
case RECORD_FIELD_HOST: | |
fmt.rules[i].destination->iov_base = curhost; | |
fmt.rules[i].destination->iov_len = strlen(curhost); | |
break; | |
case RECORD_FIELD_MSG: | |
fmt.rules[i].destination->iov_base = curmsg; | |
fmt.rules[i].destination->iov_len = strlen(curmsg); | |
break; | |
default: | |
break; | |
} | |
} | |
writev(STDOUT_FILENO, fmt.record, RECORDS_MAX); | |
printf("\n"); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment