#include <sys/poll.h>
#include <sys/file.h>
-#include "busybox.h"
+#include "libbb.h"
#include "runit_lib.h"
-static unsigned verbose;
-static int linemax = 1000;
-////static int buflen = 1024;
-static int linelen;
+#define LESS(a,b) ((int)((unsigned)(b) - (unsigned)(a)) > 0)
-static char **fndir;
-static int fdwdir;
-static int wstat;
-static struct taia trotate;
+#define FMT_PTIME 30
-static char *line;
-static smallint exitasap;
-static smallint rotateasap;
-static smallint reopenasap;
-static smallint linecomplete = 1;
-
-static smallint tmaxflag;
-
-static char repl;
-static const char *replace = "";
-
-sigset_t blocked_sigset;
-static iopause_fd input;
-static int fl_flag_0;
-
-static struct logdir {
-//// char *btmp;
+struct logdir {
+ ////char *btmp;
/* pattern list to match, in "aa\0bb\0\cc\0\0" form */
char *inst;
char *processor;
unsigned sizemax;
unsigned nmax;
unsigned nmin;
- /* int (not long) because of taia_uint() usage: */
- unsigned tmax;
+ unsigned rotate_period;
int ppid;
int fddir;
int fdcur;
+ FILE* filecur; ////
int fdlock;
- struct taia trotate;
+ unsigned next_rotate;
char fnsave[FMT_PTIME];
char match;
char matcherr;
-} *dir;
-static unsigned dirn;
+};
+
+
+struct globals {
+ struct logdir *dir;
+ unsigned verbose;
+ int linemax;
+ ////int buflen;
+ int linelen;
+
+ int fdwdir;
+ char **fndir;
+ int wstat;
+ unsigned nearest_rotate;
+
+ smallint exitasap;
+ smallint rotateasap;
+ smallint reopenasap;
+ smallint linecomplete;
+ smallint tmaxflag;
+
+ char repl;
+ const char *replace;
+ int fl_flag_0;
+ unsigned dirn;
+
+ sigset_t blocked_sigset;
+};
+#define G (*(struct globals*)ptr_to_globals)
+#define dir (G.dir )
+#define verbose (G.verbose )
+#define linemax (G.linemax )
+#define buflen (G.buflen )
+#define linelen (G.linelen )
+#define fndir (G.fndir )
+#define fdwdir (G.fdwdir )
+#define wstat (G.wstat )
+#define nearest_rotate (G.nearest_rotate)
+#define exitasap (G.exitasap )
+#define rotateasap (G.rotateasap )
+#define reopenasap (G.reopenasap )
+#define linecomplete (G.linecomplete )
+#define tmaxflag (G.tmaxflag )
+#define repl (G.repl )
+#define replace (G.replace )
+#define blocked_sigset (G.blocked_sigset)
+#define fl_flag_0 (G.fl_flag_0 )
+#define dirn (G.dirn )
+#define INIT_G() do { \
+ SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
+ linemax = 1000; \
+ /*buflen = 1024;*/ \
+ linecomplete = 1; \
+ replace = ""; \
+} while (0)
+
+#define line bb_common_bufsiz1
+
#define FATAL "fatal: "
#define WARNING "warning: "
{
bb_error_msg_and_die(FATAL"%s", m0);
}
-static void warn(const char *m0) {
+static void warn(const char *m0)
+{
bb_perror_msg(WARNING"%s", m0);
}
static void warn2(const char *m0, const char *m1)
return s;
}
+/*** ex fmt_ptime.[ch] ***/
+
+/* NUL terminated */
+static void fmt_time_human_30nul(char *s)
+{
+ struct tm *t;
+ struct timeval tv;
+
+ gettimeofday(&tv, NULL);
+ t = gmtime(&(tv.tv_sec));
+ sprintf(s, "%04u-%02u-%02u_%02u:%02u:%02u.%06u000",
+ (unsigned)(1900 + t->tm_year),
+ (unsigned)(t->tm_mon + 1),
+ (unsigned)(t->tm_mday),
+ (unsigned)(t->tm_hour),
+ (unsigned)(t->tm_min),
+ (unsigned)(t->tm_sec),
+ (unsigned)(tv.tv_usec)
+ );
+ /* 4+1 + 2+1 + 2+1 + 2+1 + 2+1 + 2+1 + 9 = */
+ /* 5 + 3 + 3 + 3 + 3 + 3 + 9 = */
+ /* 20 (up to '.' inclusive) + 9 (not including '\0') */
+}
+
+/* NOT terminated! */
+static void fmt_time_bernstein_25(char *s)
+{
+ uint32_t pack[3];
+ struct timeval tv;
+ unsigned sec_hi;
+
+ gettimeofday(&tv, NULL);
+ sec_hi = (0x400000000000000aULL + tv.tv_sec) >> 32;
+ tv.tv_sec = (time_t)(0x400000000000000aULL) + tv.tv_sec;
+ tv.tv_usec *= 1000;
+ /* Network order is big-endian: most significant byte first.
+ * This is exactly what we want here */
+ pack[0] = htonl(sec_hi);
+ pack[1] = htonl(tv.tv_sec);
+ pack[2] = htonl(tv.tv_usec);
+ *s++ = '@';
+ bin2hex(s, (char*)pack, 12);
+}
+
static unsigned processorstart(struct logdir *ld)
{
int pid;
int fd;
/* child */
- sig_uncatch(SIGTERM);
- sig_uncatch(SIGALRM);
- sig_uncatch(SIGHUP);
+ bb_signals(0
+ + (1 << SIGTERM)
+ + (1 << SIGALRM)
+ + (1 << SIGHUP)
+ , SIG_DFL);
sig_unblock(SIGTERM);
sig_unblock(SIGALRM);
sig_unblock(SIGHUP);
if (verbose)
bb_error_msg(INFO"processing: %s/%s", ld->name, ld->fnsave);
fd = xopen(ld->fnsave, O_RDONLY|O_NDELAY);
- if (fd_move(0, fd) == -1)
- bb_perror_msg_and_die(FATAL"cannot %s processor %s", "move filedescriptor for", ld->name);
+ xmove_fd(fd, 0);
ld->fnsave[26] = 't';
fd = xopen(ld->fnsave, O_WRONLY|O_NDELAY|O_TRUNC|O_CREAT);
- if (fd_move(1, fd) == -1)
- bb_perror_msg_and_die(FATAL"cannot %s processor %s", "move filedescriptor for", ld->name);
+ xmove_fd(fd, 1);
fd = open_read("state");
if (fd == -1) {
if (errno != ENOENT)
close(xopen("state", O_WRONLY|O_NDELAY|O_TRUNC|O_CREAT));
fd = xopen("state", O_RDONLY|O_NDELAY);
}
- if (fd_move(4, fd) == -1)
- bb_perror_msg_and_die(FATAL"cannot %s processor %s", "move filedescriptor for", ld->name);
+ xmove_fd(fd, 4);
fd = xopen("newstate", O_WRONLY|O_NDELAY|O_TRUNC|O_CREAT);
- if (fd_move(5, fd) == -1)
- bb_perror_msg_and_die(FATAL"cannot %s processor %s", "move filedescriptor for", ld->name);
+ xmove_fd(fd, 5);
// getenv("SHELL")?
prog[0] = (char*)"sh";
prog[1] = (char*)"-c";
prog[2] = ld->processor;
- prog[3] = '\0';
- execve("/bin/sh", prog, environ);
+ prog[3] = NULL;
+ execv("/bin/sh", prog);
bb_perror_msg_and_die(FATAL"cannot %s processor %s", "run", ld->name);
}
ld->ppid = pid;
if (ld->ppid) {
sig_unblock(SIGHUP);
- while (wait_pid(&wstat, ld->ppid) == -1)
+ while (safe_waitpid(ld->ppid, &wstat, 0) == -1)
pause2cannot("wait for processor", ld->name);
sig_block(SIGHUP);
ld->ppid = 0;
static unsigned rotate(struct logdir *ld)
{
struct stat st;
- struct taia now;
+ unsigned now;
if (ld->fddir == -1) {
- ld->tmax = 0;
+ ld->rotate_period = 0;
return 0;
}
if (ld->ppid)
while (!processorstop(ld))
- /* wait */;
+ continue;
while (fchdir(ld->fddir) == -1)
pause2cannot("change directory, want rotate", ld->name);
ld->fnsave[26] = 'u';
ld->fnsave[27] = '\0';
do {
- taia_now(&now);
- fmt_taia25(ld->fnsave, &now);
+ fmt_time_bernstein_25(ld->fnsave);
errno = 0;
stat(ld->fnsave, &st);
} while (errno != ENOENT);
- if (ld->tmax && taia_less(&ld->trotate, &now)) {
- taia_uint(&ld->trotate, ld->tmax);
- taia_add(&ld->trotate, &now, &ld->trotate);
- if (taia_less(&ld->trotate, &trotate))
- trotate = ld->trotate;
+ now = monotonic_sec();
+ if (ld->rotate_period && LESS(ld->next_rotate, now)) {
+ ld->next_rotate = now + ld->rotate_period;
+ if (LESS(ld->next_rotate, nearest_rotate))
+ nearest_rotate = ld->next_rotate;
}
if (ld->size > 0) {
- while (fsync(ld->fdcur) == -1)
+ while (fflush(ld->filecur) || fsync(ld->fdcur) == -1)
pause2cannot("fsync current logfile", ld->name);
while (fchmod(ld->fdcur, 0744) == -1)
pause2cannot("set mode of current", ld->name);
- close(ld->fdcur);
+ ////close(ld->fdcur);
+ fclose(ld->filecur);
+
if (verbose) {
bb_error_msg(INFO"rename: %s/current %s %u", ld->name,
ld->fnsave, ld->size);
pause2cannot("rename current", ld->name);
while ((ld->fdcur = open("current", O_WRONLY|O_NDELAY|O_APPEND|O_CREAT, 0600)) == -1)
pause2cannot("create new current", ld->name);
- coe(ld->fdcur);
+ /* we presume this cannot fail */
+ ld->filecur = fdopen(ld->fdcur, "a"); ////
+ setvbuf(ld->filecur, NULL, _IOFBF, linelen); ////
+ close_on_exec_on(ld->fdcur);
ld->size = 0;
while (fchmod(ld->fdcur, 0644) == -1)
pause2cannot("set mode of current", ld->name);
if (len > (ld->sizemax - ld->size))
len = ld->sizemax - ld->size;
}
- while ((i = full_write(ld->fdcur, s, len)) == -1) {
+ while (1) {
+ ////i = full_write(ld->fdcur, s, len);
+ ////if (i != -1) break;
+ i = fwrite(s, 1, len, ld->filecur);
+ if (i == len) break;
+
if ((errno == ENOSPC) && (ld->nmin < ld->nmax)) {
DIR *d;
struct dirent *f;
ld->fddir = -1;
if (ld->fdcur == -1)
return; /* impossible */
- while (fsync(ld->fdcur) == -1)
+ while (fflush(ld->filecur) || fsync(ld->fdcur) == -1)
pause2cannot("fsync current logfile", ld->name);
while (fchmod(ld->fdcur, 0744) == -1)
pause2cannot("set mode of current", ld->name);
- close(ld->fdcur);
+ ////close(ld->fdcur);
+ fclose(ld->filecur);
ld->fdcur = -1;
if (ld->fdlock == -1)
return; /* impossible */
static unsigned logdir_open(struct logdir *ld, const char *fn)
{
char buf[128];
- struct taia now;
+ unsigned now;
char *new, *s, *np;
int i;
struct stat st;
+ now = monotonic_sec();
+
ld->fddir = open(fn, O_RDONLY|O_NDELAY);
if (ld->fddir == -1) {
warn2("cannot open log directory", (char*)fn);
return 0;
}
- coe(ld->fddir);
+ close_on_exec_on(ld->fddir);
if (fchdir(ld->fddir) == -1) {
logdir_close(ld);
warn2("cannot change directory", (char*)fn);
pause1cannot("change to initial working directory");
return 0;
}
- coe(ld->fdlock);
+ close_on_exec_on(ld->fdlock);
ld->size = 0;
ld->sizemax = 1000000;
ld->nmax = ld->nmin = 10;
- ld->tmax = 0;
+ ld->rotate_period = 0;
ld->name = (char*)fn;
ld->ppid = 0;
ld->match = '+';
/* read config */
i = open_read_close("config", buf, sizeof(buf));
- if (i < 0)
- warn2("cannot read config", ld->name);
+ if (i < 0 && errno != ENOENT)
+ bb_perror_msg(WARNING"%s/config", ld->name);
if (i > 0) {
- if (verbose) bb_error_msg(INFO"read: %s/config", ld->name);
+ if (verbose)
+ bb_error_msg(INFO"read: %s/config", ld->name);
s = buf;
while (s) {
np = strchr(s, '\n');
- if (np) *np++ = '\0';
+ if (np)
+ *np++ = '\0';
switch (s[0]) {
case '+':
case '-':
case 'e':
case 'E':
+ /* Add '\n'-terminated line to ld->inst */
while (1) {
- int l = asprintf(&new, "%s%s\n", ld->inst?:"", s);
- if (l >= 0 && new) break;
+ int l = asprintf(&new, "%s%s\n", ld->inst ? : "", s);
+ if (l >= 0 && new)
+ break;
pause_nomem();
}
free(ld->inst);
break;
case 's': {
static const struct suffix_mult km_suffixes[] = {
- { "k", 1024 },
- { "m", 1024*1024 },
- { NULL, 0 }
+ { "k", 1024 },
+ { "m", 1024*1024 },
+ { }
};
ld->sizemax = xatou_sfx(&s[1], km_suffixes);
break;
break;
case 't': {
static const struct suffix_mult mh_suffixes[] = {
- { "m", 60 },
- { "h", 60*60 },
- /*{ "d", 24*60*60 },*/
- { NULL, 0 }
+ { "m", 60 },
+ { "h", 60*60 },
+ /*{ "d", 24*60*60 },*/
+ { }
};
- ld->tmax = xatou_sfx(&s[1], mh_suffixes);
- if (ld->tmax) {
- taia_uint(&ld->trotate, ld->tmax);
- taia_add(&ld->trotate, &now, &ld->trotate);
- if (!tmaxflag || taia_less(&ld->trotate, &trotate))
- trotate = ld->trotate;
+ ld->rotate_period = xatou_sfx(&s[1], mh_suffixes);
+ if (ld->rotate_period) {
+ ld->next_rotate = now + ld->rotate_period;
+ if (!tmaxflag || LESS(ld->next_rotate, nearest_rotate))
+ nearest_rotate = ld->next_rotate;
tmaxflag = 1;
}
break;
s = ld->inst;
while (s) {
np = strchr(s, '\n');
- if (np) *np++ = '\0';
+ if (np)
+ *np++ = '\0';
s = np;
}
}
/* open current */
i = stat("current", &st);
if (i != -1) {
- if (st.st_size && ! (st.st_mode & S_IXUSR)) {
+ if (st.st_size && !(st.st_mode & S_IXUSR)) {
ld->fnsave[25] = '.';
ld->fnsave[26] = 'u';
ld->fnsave[27] = '\0';
do {
- taia_now(&now);
- fmt_taia25(ld->fnsave, &now);
+ fmt_time_bernstein_25(ld->fnsave);
errno = 0;
stat(ld->fnsave, &st);
} while (errno != ENOENT);
rmoldest(ld);
i = -1;
} else {
- /* Be paranoid: st.st_size can be not just bigger, but WIDER! */
- /* (bug in original svlogd. remove this comment when fixed there) */
+ /* st.st_size can be not just bigger, but WIDER!
+ * This code is safe: if st.st_size > 4GB, we select
+ * ld->sizemax (because it's "unsigned") */
ld->size = (st.st_size > ld->sizemax) ? ld->sizemax : st.st_size;
}
} else {
}
while ((ld->fdcur = open("current", O_WRONLY|O_NDELAY|O_APPEND|O_CREAT, 0600)) == -1)
pause2cannot("open current", ld->name);
- coe(ld->fdcur);
+ /* we presume this cannot fail */
+ ld->filecur = fdopen(ld->fdcur, "a"); ////
+ setvbuf(ld->filecur, NULL, _IOFBF, linelen); ////
+
+ close_on_exec_on(ld->fdcur);
while (fchmod(ld->fdcur, 0644) == -1)
pause2cannot("set mode of current", ld->name);
static void logdirs_reopen(void)
{
- struct taia now;
int l;
int ok = 0;
tmaxflag = 0;
- taia_now(&now);
for (l = 0; l < dirn; ++l) {
logdir_close(&dir[l]);
- if (logdir_open(&dir[l], fndir[l])) ok = 1;
+ if (logdir_open(&dir[l], fndir[l]))
+ ok = 1;
}
- if (!ok) fatalx("no functional log directories");
+ if (!ok)
+ fatalx("no functional log directories");
}
/* Will look good in libbb one day */
}
/* Used for reading stdin */
-static int buffer_pread(int fd, char *s, unsigned len)
+static int buffer_pread(/*int fd, */char *s, unsigned len)
{
- struct taia now;
+ unsigned now;
+ struct pollfd input;
int i;
- if (rotateasap) {
- for (i = 0; i < dirn; ++i)
- rotate(dir+i);
- rotateasap = 0;
- }
- if (exitasap) {
- if (linecomplete)
- return 0;
- len = 1;
- }
- if (reopenasap) {
- logdirs_reopen();
- reopenasap = 0;
- }
- taia_now(&now);
- taia_uint(&trotate, 2744);
- taia_add(&trotate, &now, &trotate);
- for (i = 0; i < dirn; ++i)
- if (dir[i].tmax) {
- if (taia_less(&dir[i].trotate, &now))
- rotate(dir+i);
- if (taia_less(&dir[i].trotate, &trotate))
- trotate = dir[i].trotate;
+ input.fd = 0;
+ input.events = POLLIN;
+
+ do {
+ if (rotateasap) {
+ for (i = 0; i < dirn; ++i)
+ rotate(dir + i);
+ rotateasap = 0;
+ }
+ if (exitasap) {
+ if (linecomplete)
+ return 0;
+ len = 1;
+ }
+ if (reopenasap) {
+ logdirs_reopen();
+ reopenasap = 0;
+ }
+ now = monotonic_sec();
+ nearest_rotate = now + (45 * 60 + 45);
+ for (i = 0; i < dirn; ++i) {
+ if (dir[i].rotate_period) {
+ if (LESS(dir[i].next_rotate, now))
+ rotate(dir + i);
+ if (LESS(dir[i].next_rotate, nearest_rotate))
+ nearest_rotate = dir[i].next_rotate;
+ }
}
- while (1) {
sigprocmask(SIG_UNBLOCK, &blocked_sigset, NULL);
- iopause(&input, 1, &trotate, &now);
+ i = nearest_rotate - now;
+ if (i > 1000000)
+ i = 1000000;
+ if (i <= 0)
+ i = 1;
+ poll(&input, 1, i * 1000);
sigprocmask(SIG_BLOCK, &blocked_sigset, NULL);
- i = ndelay_read(fd, s, len);
- if (i >= 0) break;
+
+ i = ndelay_read(0, s, len);
+ if (i >= 0)
+ break;
+ if (errno == EINTR)
+ continue;
if (errno != EAGAIN) {
warn("cannot read standard input");
break;
}
/* else: EAGAIN - normal, repeat silently */
- }
+ } while (!exitasap);
if (i > 0) {
int cnt;
linecomplete = (s[i-1] == '\n');
- if (!repl) return i;
+ if (!repl)
+ return i;
cnt = i;
while (--cnt >= 0) {
return i;
}
-
static void sig_term_handler(int sig_no)
{
if (verbose)
if (verbose)
bb_error_msg(INFO"sig%s received", "child");
- while ((pid = wait_nohang(&wstat)) > 0)
- for (l = 0; l < dirn; ++l)
+ while ((pid = wait_any_nohang(&wstat)) > 0) {
+ for (l = 0; l < dirn; ++l) {
if (dir[l].ppid == pid) {
dir[l].ppid = 0;
processorstop(&dir[l]);
break;
}
+ }
+ }
}
static void sig_alarm_handler(int sig_no)
}
}
+int svlogd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int svlogd_main(int argc, char **argv)
{
- struct taia now;
char *r,*l,*b;
ssize_t stdin_cnt = 0;
int i;
unsigned timestamp = 0;
void* (*memRchr)(const void *, int, size_t) = memchr;
-#define line bb_common_bufsiz1
+ INIT_G();
opt_complementary = "tt:vv";
- opt = getopt32(argc, argv, "r:R:l:b:tv",
+ opt = getopt32(argv, "r:R:l:b:tv",
&r, &replace, &l, &b, ×tamp, &verbose);
if (opt & 1) { // -r
repl = r[0];
if (linemax == 0) linemax = BUFSIZ-26;
if (linemax < 256) linemax = 256;
}
-//// if (opt & 8) { // -b
-//// buflen = xatoi_u(b);
-//// if (buflen == 0) buflen = 1024;
-//// }
+ ////if (opt & 8) { // -b
+ //// buflen = xatoi_u(b);
+ //// if (buflen == 0) buflen = 1024;
+ ////}
//if (opt & 0x10) timestamp++; // -t
//if (opt & 0x20) verbose++; // -v
//if (timestamp > 2) timestamp = 2;
if (dirn <= 0) usage();
////if (buflen <= linemax) usage();
fdwdir = xopen(".", O_RDONLY|O_NDELAY);
- coe(fdwdir);
- dir = xmalloc(dirn * sizeof(struct logdir));
+ close_on_exec_on(fdwdir);
+ dir = xzalloc(dirn * sizeof(struct logdir));
for (i = 0; i < dirn; ++i) {
dir[i].fddir = -1;
dir[i].fdcur = -1;
////dir[i].btmp = xmalloc(buflen);
- dir[i].ppid = 0;
+ /*dir[i].ppid = 0;*/
}
/* line = xmalloc(linemax + (timestamp ? 26 : 0)); */
fndir = argv;
- input.fd = 0;
- input.events = IOPAUSE_READ;
/* We cannot set NONBLOCK on fd #0 permanently - this setting
* _isn't_ per-process! It is shared among all other processes
* with the same stdin */
- fl_flag_0 = fcntl(0, F_GETFL, 0);
+ fl_flag_0 = fcntl(0, F_GETFL);
sigemptyset(&blocked_sigset);
sigaddset(&blocked_sigset, SIGTERM);
sigaddset(&blocked_sigset, SIGALRM);
sigaddset(&blocked_sigset, SIGHUP);
sigprocmask(SIG_BLOCK, &blocked_sigset, NULL);
- sig_catch(SIGTERM, sig_term_handler);
- sig_catch(SIGCHLD, sig_child_handler);
- sig_catch(SIGALRM, sig_alarm_handler);
- sig_catch(SIGHUP, sig_hangup_handler);
+ bb_signals_recursive(1 << SIGTERM, sig_term_handler);
+ bb_signals_recursive(1 << SIGCHLD, sig_child_handler);
+ bb_signals_recursive(1 << SIGALRM, sig_alarm_handler);
+ bb_signals_recursive(1 << SIGHUP, sig_hangup_handler);
logdirs_reopen();
if (!timestamp)
memRchr = memrchr;
+ setvbuf(stderr, NULL, _IOFBF, linelen);
+
/* Each iteration processes one or more lines */
while (1) {
char stamp[FMT_PTIME];
char ch;
lineptr = line;
- /* Prepare timestamp if needed */
- if (timestamp) {
- taia_now(&now);
- switch (timestamp) {
- case 1:
- fmt_taia25(stamp, &now);
- break;
- default: /* case 2: */
- fmt_ptime30nul(stamp, &now);
- break;
- }
+ if (timestamp)
lineptr += 26;
- }
/* lineptr[0..linemax-1] - buffer for stdin */
/* (possibly has some unprocessed data from prev loop) */
if (!np && !exitasap) {
i = linemax - stdin_cnt; /* avail. bytes at tail */
if (i >= 128) {
- i = buffer_pread(0, lineptr + stdin_cnt, i);
+ i = buffer_pread(/*0, */lineptr + stdin_cnt, i);
if (i <= 0) /* EOF or error on stdin */
exitasap = 1;
else {
/* linelen == no of chars incl. '\n' (or == stdin_cnt) */
ch = lineptr[linelen-1];
- /* TODO: biggest performance hit is coming from the fact
- * that we do not buffer writes. We may read many lines
- * in one read() above, but will do one write()
- * per line below. Should we use stdio? */
+ /* Biggest performance hit was coming from the fact
+ * that we did not buffer writes. We were reading many lines
+ * in one read() above, but wrote one line per write().
+ * We are using stdio to fix that */
/* write out lineptr[0..linelen-1] to each log destination
* (or lineptr[-26..linelen-1] if timestamping) */
printlen = linelen;
printptr = lineptr;
if (timestamp) {
+ if (timestamp == 1)
+ fmt_time_bernstein_25(stamp);
+ else /* 2: */
+ fmt_time_human_30nul(stamp);
printlen += 26;
printptr -= 26;
memcpy(printptr, stamp, 25);
if (ld->fddir == -1) continue;
if (ld->inst)
logmatch(ld);
- if (ld->matcherr == 'e')
- full_write(2, printptr, printlen);
+ if (ld->matcherr == 'e') {
+ /* runit-1.8.0 compat: if timestamping, do it on stderr too */
+ ////full_write(2, printptr, printlen);
+ fwrite(printptr, 1, printlen, stderr);
+ }
if (ld->match != '+') continue;
buffer_pwrite(i, printptr, printlen);
}
/* read/write repeatedly until we see it */
while (ch != '\n') {
/* lineptr is emptied now, safe to use as buffer */
- stdin_cnt = exitasap ? -1 : buffer_pread(0, lineptr, linemax);
+ stdin_cnt = exitasap ? -1 : buffer_pread(/*0, */lineptr, linemax);
if (stdin_cnt <= 0) { /* EOF or error on stdin */
exitasap = 1;
lineptr[0] = ch = '\n';
/* linelen == no of chars incl. '\n' (or == stdin_cnt) */
for (i = 0; i < dirn; ++i) {
if (dir[i].fddir == -1) continue;
- if (dir[i].matcherr == 'e')
- full_write(2, lineptr, linelen);
+ if (dir[i].matcherr == 'e') {
+ ////full_write(2, lineptr, linelen);
+ fwrite(lineptr, 1, linelen, stderr);
+ }
if (dir[i].match != '+') continue;
buffer_pwrite(i, lineptr, linelen);
}
/* Move unprocessed data to the front of line */
memmove((timestamp ? line+26 : line), lineptr, stdin_cnt);
}
+ fflush(NULL);////
}
for (i = 0; i < dirn; ++i) {