blob: 5a7d7d940a2068dd23a8fe14901c735f523ea8fb [file] [log] [blame] [raw]
/* timetag - toolbox
Copyright 2015-2017 Rivoreo
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*/
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <time.h>
#include <stdlib.h>
#ifdef _WIN32
#include <windows.h>
#ifdef _WIN32_WCE
#define BUFFER_SIZE 1024
#else
#define BUFFER_SIZE 2048
#endif
extern struct tm *gmtime_r(const time_t *, struct tm *);
extern struct tm *localtime_r(const time_t *, struct tm *);
#else
#define BUFFER_SIZE 4096
#endif
#define DEFAULT_FORMAT "%a %b %e %H:%M:%S %Z %Y "
static void print_usage(const char *name) {
fprintf(stderr, "Usage: %s [-u] [<format>]\n", name);
}
static void *mem2chr(const void *s, int c1, int c2, size_t n) {
char *p = (void *)s;
unsigned int i = 0;
while(i < n) {
if(p[i] == c1 || p[i] == c2) return p + i;
i++;
}
return NULL;
}
static void print_timetag(int utc, const char *format, const char *message, size_t msg_len) {
char buffer[512];
time_t t = time(NULL);
struct tm tm;
(utc ? gmtime_r : localtime_r)(&t, &tm);
size_t tag_len = strftime(buffer, sizeof buffer, format, &tm);
write(STDOUT_FILENO, buffer, tag_len);
write(STDOUT_FILENO, message, msg_len);
//write(STDOUT_FILENO, "\n", 1);
}
int timetag_main(int argc, char **argv) {
int utc = 0;
const char *format = NULL;
int i = 1;
int end_of_options = 0;
while(argv[i]) {
if(!end_of_options && argv[i][0] == '-') {
const char *o = argv[i] + 1;
while(*o) switch(*o++) {
case 'u':
utc = 1;
putenv("TZ=UTC");
tzset();
break;
case 'h':
print_usage(argv[0]);
return 0;
case '-':
if(o[1]) {
fprintf(stderr, "%s: Invalid option '%s'\n", argv[0], argv[i]);
return -1;
} else end_of_options = 1;
break;
default:
fprintf(stderr, "%s: Invalid option '-%c'\n", argv[0], o[-1]);
return -1;
}
} else {
if(format) {
fprintf(stderr, "%s: Extra format '%s'\n", argv[0], argv[i]);
return -1;
}
format = argv[i];
}
i++;
}
if(!format) format = DEFAULT_FORMAT;
char buffer[BUFFER_SIZE];
int s, ss = 0;
int no_tag = 0;
int r = 0;
do {
s = read(STDIN_FILENO, buffer + ss, sizeof buffer - ss);
if(s < 0) {
if(errno == EINTR) continue;
perror("read");
r = 1;
break;
}
char *br = mem2chr(buffer + ss, 0, '\n', s);
if(br) {
int skip_len = 0;
char *last_br;
do {
if(!*br) *br = '\n';
br++;
int msg_len = br - buffer - skip_len;
if(no_tag) {
write(STDOUT_FILENO, buffer + skip_len, msg_len);
no_tag = 0;
} else print_timetag(utc, format, buffer + skip_len, msg_len);
last_br = br;
br = mem2chr(br, 0, '\n', s - (br - (buffer + ss)));
skip_len += msg_len;
//fprintf(stderr, "br = %p, *br = '%c', skip_len = %d\n", br, br ? *br : 0, skip_len);
} while(br);
ss += s - skip_len;
memmove(buffer, last_br, ss);
} else {
ss += s;
if(ss == sizeof buffer) {
print_timetag(utc, format, buffer, sizeof buffer);
ss = 0;
no_tag = 1;
}
}
} while(s > 0);
if(ss) {
if(no_tag) write(STDOUT_FILENO, buffer, ss);
else print_timetag(utc, format, buffer, ss);
putchar('\n');
}
return r;
}