summaryrefslogtreecommitdiff
path: root/runit/svlogd.c
diff options
context:
space:
mode:
Diffstat (limited to 'runit/svlogd.c')
-rw-r--r--runit/svlogd.c198
1 files changed, 127 insertions, 71 deletions
diff --git a/runit/svlogd.c b/runit/svlogd.c
index 8632ba6a5..b8fa5645b 100644
--- a/runit/svlogd.c
+++ b/runit/svlogd.c
@@ -33,6 +33,10 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33#include "libbb.h" 33#include "libbb.h"
34#include "runit_lib.h" 34#include "runit_lib.h"
35 35
36#define LESS(a,b) ((int)((unsigned)(b) - (unsigned)(a)) > 0)
37
38#define FMT_PTIME 30
39
36static unsigned verbose; 40static unsigned verbose;
37static int linemax = 1000; 41static int linemax = 1000;
38////static int buflen = 1024; 42////static int buflen = 1024;
@@ -41,7 +45,7 @@ static int linelen;
41static char **fndir; 45static char **fndir;
42static int fdwdir; 46static int fdwdir;
43static int wstat; 47static int wstat;
44static struct taia trotate; 48static unsigned nearest_rotate;
45 49
46static char *line; 50static char *line;
47static smallint exitasap; 51static smallint exitasap;
@@ -55,7 +59,6 @@ static char repl;
55static const char *replace = ""; 59static const char *replace = "";
56 60
57static sigset_t *blocked_sigset; 61static sigset_t *blocked_sigset;
58static iopause_fd input;
59static int fl_flag_0; 62static int fl_flag_0;
60 63
61static struct logdir { 64static struct logdir {
@@ -68,14 +71,13 @@ static struct logdir {
68 unsigned sizemax; 71 unsigned sizemax;
69 unsigned nmax; 72 unsigned nmax;
70 unsigned nmin; 73 unsigned nmin;
71 /* int (not long) because of taia_uint() usage: */ 74 unsigned rotate_period;
72 unsigned tmax;
73 int ppid; 75 int ppid;
74 int fddir; 76 int fddir;
75 int fdcur; 77 int fdcur;
76 FILE* filecur; //// 78 FILE* filecur; ////
77 int fdlock; 79 int fdlock;
78 struct taia trotate; 80 unsigned next_rotate;
79 char fnsave[FMT_PTIME]; 81 char fnsave[FMT_PTIME];
80 char match; 82 char match;
81 char matcherr; 83 char matcherr;
@@ -128,6 +130,50 @@ static char* wstrdup(const char *str)
128 return s; 130 return s;
129} 131}
130 132
133/*** ex fmt_ptime.[ch] ***/
134
135/* NUL terminated */
136static void fmt_time_human_30nul(char *s)
137{
138 struct tm *t;
139 struct timeval tv;
140
141 gettimeofday(&tv, NULL);
142 t = gmtime(&(tv.tv_sec));
143 sprintf(s, "%04u-%02u-%02u_%02u:%02u:%02u.%06u000",
144 (unsigned)(1900 + t->tm_year),
145 (unsigned)(t->tm_mon + 1),
146 (unsigned)(t->tm_mday),
147 (unsigned)(t->tm_hour),
148 (unsigned)(t->tm_min),
149 (unsigned)(t->tm_sec),
150 (unsigned)(tv.tv_usec)
151 );
152 /* 4+1 + 2+1 + 2+1 + 2+1 + 2+1 + 2+1 + 9 = */
153 /* 5 + 3 + 3 + 3 + 3 + 3 + 9 = */
154 /* 20 (up to '.' inclusive) + 9 (not including '\0') */
155}
156
157/* NOT terminated! */
158static void fmt_time_bernstein_25(char *s)
159{
160 uint32_t pack[3];
161 struct timeval tv;
162 unsigned sec_hi;
163
164 gettimeofday(&tv, NULL);
165 sec_hi = (0x400000000000000aULL + tv.tv_sec) >> 32;
166 tv.tv_sec = (time_t)(0x400000000000000aULL) + tv.tv_sec;
167 tv.tv_usec *= 1000;
168 /* Network order is big-endian: most significant byte first.
169 * This is exactly what we want here */
170 pack[0] = htonl(sec_hi);
171 pack[1] = htonl(tv.tv_sec);
172 pack[2] = htonl(tv.tv_usec);
173 *s++ = '@';
174 bin2hex(s, (char*)pack, 12);
175}
176
131static unsigned processorstart(struct logdir *ld) 177static unsigned processorstart(struct logdir *ld)
132{ 178{
133 int pid; 179 int pid;
@@ -264,15 +310,15 @@ static void rmoldest(struct logdir *ld)
264static unsigned rotate(struct logdir *ld) 310static unsigned rotate(struct logdir *ld)
265{ 311{
266 struct stat st; 312 struct stat st;
267 struct taia now; 313 unsigned now;
268 314
269 if (ld->fddir == -1) { 315 if (ld->fddir == -1) {
270 ld->tmax = 0; 316 ld->rotate_period = 0;
271 return 0; 317 return 0;
272 } 318 }
273 if (ld->ppid) 319 if (ld->ppid)
274 while (!processorstop(ld)) 320 while (!processorstop(ld))
275 /* wait */; 321 continue;
276 322
277 while (fchdir(ld->fddir) == -1) 323 while (fchdir(ld->fddir) == -1)
278 pause2cannot("change directory, want rotate", ld->name); 324 pause2cannot("change directory, want rotate", ld->name);
@@ -284,17 +330,16 @@ static unsigned rotate(struct logdir *ld)
284 ld->fnsave[26] = 'u'; 330 ld->fnsave[26] = 'u';
285 ld->fnsave[27] = '\0'; 331 ld->fnsave[27] = '\0';
286 do { 332 do {
287 taia_now(&now); 333 fmt_time_bernstein_25(ld->fnsave);
288 fmt_taia25(ld->fnsave, &now);
289 errno = 0; 334 errno = 0;
290 stat(ld->fnsave, &st); 335 stat(ld->fnsave, &st);
291 } while (errno != ENOENT); 336 } while (errno != ENOENT);
292 337
293 if (ld->tmax && taia_less(&ld->trotate, &now)) { 338 now = monotonic_sec();
294 taia_uint(&ld->trotate, ld->tmax); 339 if (ld->rotate_period && LESS(ld->next_rotate, now)) {
295 taia_add(&ld->trotate, &now, &ld->trotate); 340 ld->next_rotate = now + ld->rotate_period;
296 if (taia_less(&ld->trotate, &trotate)) 341 if (LESS(ld->next_rotate, nearest_rotate))
297 trotate = ld->trotate; 342 nearest_rotate = ld->next_rotate;
298 } 343 }
299 344
300 if (ld->size > 0) { 345 if (ld->size > 0) {
@@ -425,11 +470,13 @@ static void logdir_close(struct logdir *ld)
425static unsigned logdir_open(struct logdir *ld, const char *fn) 470static unsigned logdir_open(struct logdir *ld, const char *fn)
426{ 471{
427 char buf[128]; 472 char buf[128];
428 struct taia now; 473 unsigned now;
429 char *new, *s, *np; 474 char *new, *s, *np;
430 int i; 475 int i;
431 struct stat st; 476 struct stat st;
432 477
478 now = monotonic_sec();
479
433 ld->fddir = open(fn, O_RDONLY|O_NDELAY); 480 ld->fddir = open(fn, O_RDONLY|O_NDELAY);
434 if (ld->fddir == -1) { 481 if (ld->fddir == -1) {
435 warn2("cannot open log directory", (char*)fn); 482 warn2("cannot open log directory", (char*)fn);
@@ -456,7 +503,7 @@ static unsigned logdir_open(struct logdir *ld, const char *fn)
456 ld->size = 0; 503 ld->size = 0;
457 ld->sizemax = 1000000; 504 ld->sizemax = 1000000;
458 ld->nmax = ld->nmin = 10; 505 ld->nmax = ld->nmin = 10;
459 ld->tmax = 0; 506 ld->rotate_period = 0;
460 ld->name = (char*)fn; 507 ld->name = (char*)fn;
461 ld->ppid = 0; 508 ld->ppid = 0;
462 ld->match = '+'; 509 ld->match = '+';
@@ -468,7 +515,8 @@ static unsigned logdir_open(struct logdir *ld, const char *fn)
468 if (i < 0 && errno != ENOENT) 515 if (i < 0 && errno != ENOENT)
469 bb_perror_msg(WARNING": %s/config", ld->name); 516 bb_perror_msg(WARNING": %s/config", ld->name);
470 if (i > 0) { 517 if (i > 0) {
471 if (verbose) bb_error_msg(INFO"read: %s/config", ld->name); 518 if (verbose)
519 bb_error_msg(INFO"read: %s/config", ld->name);
472 s = buf; 520 s = buf;
473 while (s) { 521 while (s) {
474 np = strchr(s, '\n'); 522 np = strchr(s, '\n');
@@ -508,12 +556,11 @@ static unsigned logdir_open(struct logdir *ld, const char *fn)
508 /*{ "d", 24*60*60 },*/ 556 /*{ "d", 24*60*60 },*/
509 { } 557 { }
510 }; 558 };
511 ld->tmax = xatou_sfx(&s[1], mh_suffixes); 559 ld->rotate_period = xatou_sfx(&s[1], mh_suffixes);
512 if (ld->tmax) { 560 if (ld->rotate_period) {
513 taia_uint(&ld->trotate, ld->tmax); 561 ld->next_rotate = now + ld->rotate_period;
514 taia_add(&ld->trotate, &now, &ld->trotate); 562 if (!tmaxflag || LESS(ld->next_rotate, nearest_rotate))
515 if (!tmaxflag || taia_less(&ld->trotate, &trotate)) 563 nearest_rotate = ld->next_rotate;
516 trotate = ld->trotate;
517 tmaxflag = 1; 564 tmaxflag = 1;
518 } 565 }
519 break; 566 break;
@@ -544,8 +591,7 @@ static unsigned logdir_open(struct logdir *ld, const char *fn)
544 ld->fnsave[26] = 'u'; 591 ld->fnsave[26] = 'u';
545 ld->fnsave[27] = '\0'; 592 ld->fnsave[27] = '\0';
546 do { 593 do {
547 taia_now(&now); 594 fmt_time_bernstein_25(ld->fnsave);
548 fmt_taia25(ld->fnsave, &now);
549 errno = 0; 595 errno = 0;
550 stat(ld->fnsave, &st); 596 stat(ld->fnsave, &st);
551 } while (errno != ENOENT); 597 } while (errno != ENOENT);
@@ -589,17 +635,17 @@ static unsigned logdir_open(struct logdir *ld, const char *fn)
589 635
590static void logdirs_reopen(void) 636static void logdirs_reopen(void)
591{ 637{
592 struct taia now;
593 int l; 638 int l;
594 int ok = 0; 639 int ok = 0;
595 640
596 tmaxflag = 0; 641 tmaxflag = 0;
597 taia_now(&now);
598 for (l = 0; l < dirn; ++l) { 642 for (l = 0; l < dirn; ++l) {
599 logdir_close(&dir[l]); 643 logdir_close(&dir[l]);
600 if (logdir_open(&dir[l], fndir[l])) ok = 1; 644 if (logdir_open(&dir[l], fndir[l]))
645 ok = 1;
601 } 646 }
602 if (!ok) fatalx("no functional log directories"); 647 if (!ok)
648 fatalx("no functional log directories");
603} 649}
604 650
605/* Will look good in libbb one day */ 651/* Will look good in libbb one day */
@@ -614,42 +660,55 @@ static ssize_t ndelay_read(int fd, void *buf, size_t count)
614} 660}
615 661
616/* Used for reading stdin */ 662/* Used for reading stdin */
617static int buffer_pread(int fd, char *s, unsigned len, struct taia *now) 663static int buffer_pread(int fd, char *s, unsigned len)
618{ 664{
665 unsigned now;
666 struct pollfd input;
619 int i; 667 int i;
620 668
621 if (rotateasap) { 669 input.fd = 0;
622 for (i = 0; i < dirn; ++i) 670 input.events = POLLIN|POLLHUP|POLLERR;
623 rotate(dir+i);
624 rotateasap = 0;
625 }
626 if (exitasap) {
627 if (linecomplete)
628 return 0;
629 len = 1;
630 }
631 if (reopenasap) {
632 logdirs_reopen();
633 reopenasap = 0;
634 }
635 taia_uint(&trotate, 2744);
636 taia_add(&trotate, now, &trotate);
637 for (i = 0; i < dirn; ++i)
638 if (dir[i].tmax) {
639 if (taia_less(&dir[i].trotate, now))
640 rotate(dir+i);
641 if (taia_less(&dir[i].trotate, &trotate))
642 trotate = dir[i].trotate;
643 }
644 671
645 do { 672 do {
673 if (rotateasap) {
674 for (i = 0; i < dirn; ++i)
675 rotate(dir + i);
676 rotateasap = 0;
677 }
678 if (exitasap) {
679 if (linecomplete)
680 return 0;
681 len = 1;
682 }
683 if (reopenasap) {
684 logdirs_reopen();
685 reopenasap = 0;
686 }
687 now = monotonic_sec();
688 nearest_rotate = now + (45 * 60 + 45);
689 for (i = 0; i < dirn; ++i) {
690 if (dir[i].rotate_period) {
691 if (LESS(dir[i].next_rotate, now))
692 rotate(dir + i);
693 if (LESS(dir[i].next_rotate, nearest_rotate))
694 nearest_rotate = dir[i].next_rotate;
695 }
696 }
697
646 sigprocmask(SIG_UNBLOCK, blocked_sigset, NULL); 698 sigprocmask(SIG_UNBLOCK, blocked_sigset, NULL);
647 iopause(&input, 1, &trotate, now); 699 i = nearest_rotate - now;
648// TODO: do not unblock/block, but use sigpending after iopause 700 if (i > 1000000)
649// to see whether there was any sig? (one syscall less...) 701 i = 1000000;
702 if (i <= 0)
703 i = 1;
704 poll(&input, 1, i * 1000);
650 sigprocmask(SIG_BLOCK, blocked_sigset, NULL); 705 sigprocmask(SIG_BLOCK, blocked_sigset, NULL);
706
651 i = ndelay_read(fd, s, len); 707 i = ndelay_read(fd, s, len);
652 if (i >= 0) break; 708 if (i >= 0)
709 break;
710 if (errno == EINTR)
711 continue;
653 if (errno != EAGAIN) { 712 if (errno != EAGAIN) {
654 warn("cannot read standard input"); 713 warn("cannot read standard input");
655 break; 714 break;
@@ -660,7 +719,8 @@ static int buffer_pread(int fd, char *s, unsigned len, struct taia *now)
660 if (i > 0) { 719 if (i > 0) {
661 int cnt; 720 int cnt;
662 linecomplete = (s[i-1] == '\n'); 721 linecomplete = (s[i-1] == '\n');
663 if (!repl) return i; 722 if (!repl)
723 return i;
664 724
665 cnt = i; 725 cnt = i;
666 while (--cnt >= 0) { 726 while (--cnt >= 0) {
@@ -698,13 +758,15 @@ static void sig_child_handler(int sig_no)
698 758
699 if (verbose) 759 if (verbose)
700 bb_error_msg(INFO"sig%s received", "child"); 760 bb_error_msg(INFO"sig%s received", "child");
701 while ((pid = wait_nohang(&wstat)) > 0) 761 while ((pid = wait_nohang(&wstat)) > 0) {
702 for (l = 0; l < dirn; ++l) 762 for (l = 0; l < dirn; ++l) {
703 if (dir[l].ppid == pid) { 763 if (dir[l].ppid == pid) {
704 dir[l].ppid = 0; 764 dir[l].ppid = 0;
705 processorstop(&dir[l]); 765 processorstop(&dir[l]);
706 break; 766 break;
707 } 767 }
768 }
769 }
708} 770}
709 771
710static void sig_alarm_handler(int sig_no) 772static void sig_alarm_handler(int sig_no)
@@ -795,8 +857,6 @@ int svlogd_main(int argc, char **argv)
795 } 857 }
796 /* line = xmalloc(linemax + (timestamp ? 26 : 0)); */ 858 /* line = xmalloc(linemax + (timestamp ? 26 : 0)); */
797 fndir = argv; 859 fndir = argv;
798 input.fd = 0;
799 input.events = IOPAUSE_READ;
800 /* We cannot set NONBLOCK on fd #0 permanently - this setting 860 /* We cannot set NONBLOCK on fd #0 permanently - this setting
801 * _isn't_ per-process! It is shared among all other processes 861 * _isn't_ per-process! It is shared among all other processes
802 * with the same stdin */ 862 * with the same stdin */
@@ -826,7 +886,6 @@ int svlogd_main(int argc, char **argv)
826 886
827 /* Each iteration processes one or more lines */ 887 /* Each iteration processes one or more lines */
828 while (1) { 888 while (1) {
829 struct taia now;
830 char stamp[FMT_PTIME]; 889 char stamp[FMT_PTIME];
831 char *lineptr; 890 char *lineptr;
832 char *printptr; 891 char *printptr;
@@ -846,8 +905,7 @@ int svlogd_main(int argc, char **argv)
846 if (!np && !exitasap) { 905 if (!np && !exitasap) {
847 i = linemax - stdin_cnt; /* avail. bytes at tail */ 906 i = linemax - stdin_cnt; /* avail. bytes at tail */
848 if (i >= 128) { 907 if (i >= 128) {
849 taia_now(&now); 908 i = buffer_pread(0, lineptr + stdin_cnt, i);
850 i = buffer_pread(0, lineptr + stdin_cnt, i, &now);
851 if (i <= 0) /* EOF or error on stdin */ 909 if (i <= 0) /* EOF or error on stdin */
852 exitasap = 1; 910 exitasap = 1;
853 else { 911 else {
@@ -879,11 +937,10 @@ int svlogd_main(int argc, char **argv)
879 printlen = linelen; 937 printlen = linelen;
880 printptr = lineptr; 938 printptr = lineptr;
881 if (timestamp) { 939 if (timestamp) {
882 taia_now(&now);
883 if (timestamp == 1) 940 if (timestamp == 1)
884 fmt_taia25(stamp, &now); 941 fmt_time_bernstein_25(stamp);
885 else /* 2: */ 942 else /* 2: */
886 fmt_ptime30nul(stamp, &now); 943 fmt_time_human_30nul(stamp);
887 printlen += 26; 944 printlen += 26;
888 printptr -= 26; 945 printptr -= 26;
889 memcpy(printptr, stamp, 25); 946 memcpy(printptr, stamp, 25);
@@ -905,8 +962,7 @@ int svlogd_main(int argc, char **argv)
905 /* read/write repeatedly until we see it */ 962 /* read/write repeatedly until we see it */
906 while (ch != '\n') { 963 while (ch != '\n') {
907 /* lineptr is emptied now, safe to use as buffer */ 964 /* lineptr is emptied now, safe to use as buffer */
908 taia_now(&now); 965 stdin_cnt = exitasap ? -1 : buffer_pread(0, lineptr, linemax);
909 stdin_cnt = exitasap ? -1 : buffer_pread(0, lineptr, linemax, &now);
910 if (stdin_cnt <= 0) { /* EOF or error on stdin */ 966 if (stdin_cnt <= 0) { /* EOF or error on stdin */
911 exitasap = 1; 967 exitasap = 1;
912 lineptr[0] = ch = '\n'; 968 lineptr[0] = ch = '\n';