aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2007-08-20 17:27:40 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2007-08-20 17:27:40 +0000
commit45946f8b513d9c292613ac08c3ddf4a89b915752 (patch)
treed6ea51887431e4261a114b95989950d1973d3227
parent63db27f9f4c0ec8b9abe3c32c8d699be0781ffd6 (diff)
downloadbusybox-w32-45946f8b513d9c292613ac08c3ddf4a89b915752.tar.gz
busybox-w32-45946f8b513d9c292613ac08c3ddf4a89b915752.tar.bz2
busybox-w32-45946f8b513d9c292613ac08c3ddf4a89b915752.zip
runit/*: get rid of tai[a] time abstraction, it's too bloaty.
text data bss dec hex filename 772537 1058 11092 784687 bf92f busybox.t0/busybox 772459 1058 11060 784577 bf8c1 busybox.t1/busybox 772326 1058 11028 784412 bf81c busybox.t2/busybox 772158 1058 10980 784196 bf744 busybox.t3/busybox 771490 1055 10988 783533 bf4ad busybox.t4/busybox
-rw-r--r--coreutils/od_bloaty.c5
-rw-r--r--runit/runit_lib.c147
-rw-r--r--runit/runit_lib.h134
-rw-r--r--runit/runsv.c151
-rw-r--r--runit/runsvdir.c138
-rw-r--r--runit/sv.c128
-rw-r--r--runit/svlogd.c198
7 files changed, 392 insertions, 509 deletions
diff --git a/coreutils/od_bloaty.c b/coreutils/od_bloaty.c
index 8174ab6c9..44d0f2db0 100644
--- a/coreutils/od_bloaty.c
+++ b/coreutils/od_bloaty.c
@@ -155,9 +155,8 @@ static const signed char width_bytes[] ALIGN1 = {
155}; 155};
156/* Ensure that for each member of 'enum size_spec' there is an 156/* Ensure that for each member of 'enum size_spec' there is an
157 initializer in the width_bytes array. */ 157 initializer in the width_bytes array. */
158struct dummy { 158struct ERR_width_bytes_has_bad_size {
159 int assert_width_bytes_matches_size_spec_decl 159 char ERR_width_bytes_has_bad_size[ARRAY_SIZE(width_bytes) == N_SIZE_SPECS ? 1 : -1];
160 [ARRAY_SIZE(width_bytes) == N_SIZE_SPECS ? 1 : -1];
161}; 160};
162 161
163static smallint flag_dump_strings; 162static smallint flag_dump_strings;
diff --git a/runit/runit_lib.c b/runit/runit_lib.c
index 295b45f09..4b7950ca3 100644
--- a/runit/runit_lib.c
+++ b/runit/runit_lib.c
@@ -34,8 +34,6 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34#include "libbb.h" 34#include "libbb.h"
35#include "runit_lib.h" 35#include "runit_lib.h"
36 36
37/*** byte_chr.c ***/
38
39unsigned byte_chr(char *s,unsigned n,int c) 37unsigned byte_chr(char *s,unsigned n,int c)
40{ 38{
41 char ch; 39 char ch;
@@ -52,62 +50,14 @@ unsigned byte_chr(char *s,unsigned n,int c)
52 return t - s; 50 return t - s;
53} 51}
54 52
55
56/*** coe.c ***/
57
58int coe(int fd) 53int coe(int fd)
59{ 54{
60 return fcntl(fd,F_SETFD,FD_CLOEXEC); 55 return fcntl(fd, F_SETFD, FD_CLOEXEC);
61}
62
63
64/*** fmt_ptime.c ***/
65
66void fmt_ptime30nul(char *s, struct taia *ta) {
67 struct tm *t;
68 unsigned long u;
69
70 if (ta->sec.x < 4611686018427387914ULL)
71 return; /* impossible? */
72 u = ta->sec.x -4611686018427387914ULL;
73 t = gmtime((time_t*)&u);
74 if (!t)
75 return; /* huh? */
76 //fmt_ulong(s, 1900 + t->tm_year);
77 //s[4] = '-'; fmt_uint0(&s[5], t->tm_mon+1, 2);
78 //s[7] = '-'; fmt_uint0(&s[8], t->tm_mday, 2);
79 //s[10] = '_'; fmt_uint0(&s[11], t->tm_hour, 2);
80 //s[13] = ':'; fmt_uint0(&s[14], t->tm_min, 2);
81 //s[16] = ':'; fmt_uint0(&s[17], t->tm_sec, 2);
82 //s[19] = '.'; fmt_uint0(&s[20], ta->nano, 9);
83 sprintf(s, "%04u-%02u-%02u_%02u:%02u:%02u.%09u",
84 (unsigned)(1900 + t->tm_year),
85 (unsigned)(t->tm_mon+1),
86 (unsigned)(t->tm_mday),
87 (unsigned)(t->tm_hour),
88 (unsigned)(t->tm_min),
89 (unsigned)(t->tm_sec),
90 (unsigned)(ta->nano)
91 );
92 /* 4+1 + 2+1 + 2+1 + 2+1 + 2+1 + 2+1 + 9 = */
93 /* 5 + 3 + 3 + 3 + 3 + 3 + 9 = */
94 /* 20 (up to '.' inclusive) + 9 (not including '\0') */
95} 56}
96 57
97unsigned fmt_taia25(char *s, struct taia *t) { 58#ifdef UNUSED
98 static char pack[TAIA_PACK];
99
100 taia_pack(pack, t);
101 *s++ = '@';
102 bin2hex(s, pack, 12);
103 return 25;
104}
105
106
107/*** tai_pack.c ***/
108
109static /* as it isn't used anywhere else */ 59static /* as it isn't used anywhere else */
110void tai_pack(char *s,const struct tai *t) 60void tai_pack(char *s, const struct tai *t)
111{ 61{
112 uint64_t x; 62 uint64_t x;
113 63
@@ -122,19 +72,6 @@ void tai_pack(char *s,const struct tai *t)
122 s[0] = x; 72 s[0] = x;
123} 73}
124 74
125
126#ifdef UNUSED
127/*** tai_sub.c ***/
128
129void tai_sub(struct tai *t, const struct tai *u, const struct tai *v)
130{
131 t->x = u->x - v->x;
132}
133#endif
134
135
136/*** tai_unpack.c ***/
137
138void tai_unpack(const char *s,struct tai *t) 75void tai_unpack(const char *s,struct tai *t)
139{ 76{
140 uint64_t x; 77 uint64_t x;
@@ -151,8 +88,6 @@ void tai_unpack(const char *s,struct tai *t)
151} 88}
152 89
153 90
154/*** taia_add.c ***/
155
156void taia_add(struct taia *t,const struct taia *u,const struct taia *v) 91void taia_add(struct taia *t,const struct taia *u,const struct taia *v)
157{ 92{
158 t->sec.x = u->sec.x + v->sec.x; 93 t->sec.x = u->sec.x + v->sec.x;
@@ -168,9 +103,6 @@ void taia_add(struct taia *t,const struct taia *u,const struct taia *v)
168 } 103 }
169} 104}
170 105
171
172/*** taia_less.c ***/
173
174int taia_less(const struct taia *t, const struct taia *u) 106int taia_less(const struct taia *t, const struct taia *u)
175{ 107{
176 if (t->sec.x < u->sec.x) return 1; 108 if (t->sec.x < u->sec.x) return 1;
@@ -180,9 +112,6 @@ int taia_less(const struct taia *t, const struct taia *u)
180 return t->atto < u->atto; 112 return t->atto < u->atto;
181} 113}
182 114
183
184/*** taia_now.c ***/
185
186void taia_now(struct taia *t) 115void taia_now(struct taia *t)
187{ 116{
188 struct timeval now; 117 struct timeval now;
@@ -192,9 +121,7 @@ void taia_now(struct taia *t)
192 t->atto = 0; 121 t->atto = 0;
193} 122}
194 123
195 124/* UNUSED
196/*** taia_pack.c ***/
197
198void taia_pack(char *s, const struct taia *t) 125void taia_pack(char *s, const struct taia *t)
199{ 126{
200 unsigned long x; 127 unsigned long x;
@@ -213,9 +140,7 @@ void taia_pack(char *s, const struct taia *t)
213 s[1] = x & 255; x >>= 8; 140 s[1] = x & 255; x >>= 8;
214 s[0] = x; 141 s[0] = x;
215} 142}
216 143*/
217
218/*** taia_sub.c ***/
219 144
220void taia_sub(struct taia *t, const struct taia *u, const struct taia *v) 145void taia_sub(struct taia *t, const struct taia *u, const struct taia *v)
221{ 146{
@@ -235,11 +160,7 @@ void taia_sub(struct taia *t, const struct taia *u, const struct taia *v)
235 } 160 }
236} 161}
237 162
238
239/*** taia_uint.c ***/
240
241/* XXX: breaks tai encapsulation */ 163/* XXX: breaks tai encapsulation */
242
243void taia_uint(struct taia *t, unsigned s) 164void taia_uint(struct taia *t, unsigned s)
244{ 165{
245 t->sec.x = s; 166 t->sec.x = s;
@@ -247,16 +168,12 @@ void taia_uint(struct taia *t, unsigned s)
247 t->atto = 0; 168 t->atto = 0;
248} 169}
249 170
250
251/*** iopause.c ***/
252
253static 171static
254uint64_t taia2millisec(const struct taia *t) 172uint64_t taia2millisec(const struct taia *t)
255{ 173{
256 return (t->sec.x * 1000) + (t->nano / 1000000); 174 return (t->sec.x * 1000) + (t->nano / 1000000);
257} 175}
258 176
259
260void iopause(iopause_fd *x, unsigned len, struct taia *deadline, struct taia *stamp) 177void iopause(iopause_fd *x, unsigned len, struct taia *deadline, struct taia *stamp)
261{ 178{
262 int millisecs; 179 int millisecs;
@@ -282,59 +199,40 @@ void iopause(iopause_fd *x, unsigned len, struct taia *deadline, struct taia *st
282 /* XXX: how to handle EAGAIN? are kernels really this dumb? */ 199 /* XXX: how to handle EAGAIN? are kernels really this dumb? */
283 /* XXX: how to handle EINVAL? when exactly can this happen? */ 200 /* XXX: how to handle EINVAL? when exactly can this happen? */
284} 201}
285 202#endif
286
287/*** lock_ex.c ***/
288 203
289int lock_ex(int fd) 204int lock_ex(int fd)
290{ 205{
291 return flock(fd,LOCK_EX); 206 return flock(fd,LOCK_EX);
292} 207}
293 208
294
295/*** lock_exnb.c ***/
296
297int lock_exnb(int fd) 209int lock_exnb(int fd)
298{ 210{
299 return flock(fd,LOCK_EX | LOCK_NB); 211 return flock(fd,LOCK_EX | LOCK_NB);
300} 212}
301 213
302
303/*** open_append.c ***/
304
305int open_append(const char *fn) 214int open_append(const char *fn)
306{ 215{
307 return open(fn, O_WRONLY|O_NDELAY|O_APPEND|O_CREAT, 0600); 216 return open(fn, O_WRONLY|O_NDELAY|O_APPEND|O_CREAT, 0600);
308} 217}
309 218
310
311/*** open_read.c ***/
312
313int open_read(const char *fn) 219int open_read(const char *fn)
314{ 220{
315 return open(fn, O_RDONLY|O_NDELAY); 221 return open(fn, O_RDONLY|O_NDELAY);
316} 222}
317 223
318
319/*** open_trunc.c ***/
320
321int open_trunc(const char *fn) 224int open_trunc(const char *fn)
322{ 225{
323 return open(fn,O_WRONLY | O_NDELAY | O_TRUNC | O_CREAT,0644); 226 return open(fn,O_WRONLY | O_NDELAY | O_TRUNC | O_CREAT,0644);
324} 227}
325 228
326
327/*** open_write.c ***/
328
329int open_write(const char *fn) 229int open_write(const char *fn)
330{ 230{
331 return open(fn, O_WRONLY|O_NDELAY); 231 return open(fn, O_WRONLY|O_NDELAY);
332} 232}
333 233
334 234unsigned pmatch(const char *p, const char *s, unsigned len)
335/*** pmatch.c ***/ 235{
336
337unsigned pmatch(const char *p, const char *s, unsigned len) {
338 for (;;) { 236 for (;;) {
339 char c = *p++; 237 char c = *p++;
340 if (!c) return !len; 238 if (!c) return !len;
@@ -373,32 +271,3 @@ unsigned pmatch(const char *p, const char *s, unsigned len) {
373 } 271 }
374 return 0; 272 return 0;
375} 273}
376
377
378#ifdef UNUSED
379/*** seek_set.c ***/
380
381int seek_set(int fd,seek_pos pos)
382{
383 if (lseek(fd,(off_t) pos,SEEK_SET) == -1) return -1; return 0;
384}
385
386
387/*** str_chr.c ***/
388
389// strchrnul?
390unsigned str_chr(const char *s,int c)
391{
392 char ch;
393 const char *t;
394
395 ch = c;
396 t = s;
397 for (;;) {
398 if (!*t) break;
399 if (*t == ch) break;
400 ++t;
401 }
402 return t - s;
403}
404#endif
diff --git a/runit/runit_lib.h b/runit/runit_lib.h
index 1dadb6e47..c73befcb6 100644
--- a/runit/runit_lib.h
+++ b/runit/runit_lib.h
@@ -25,107 +25,75 @@ OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26*/ 26*/
27 27
28/*** byte.h ***/
29
30extern unsigned byte_chr(char *s,unsigned n,int c); 28extern unsigned byte_chr(char *s,unsigned n,int c);
31 29
32
33/*** coe.h ***/
34
35extern int coe(int); 30extern int coe(int);
36 31
37
38/*** direntry.h ***/
39
40#define direntry struct dirent 32#define direntry struct dirent
41 33
42 34//struct tai {
43/*** tai.h ***/ 35// uint64_t x;
44 36//};
45struct tai { 37//
46 uint64_t x; 38//#define tai_unix(t,u) ((void) ((t)->x = 0x400000000000000aULL + (uint64_t) (u)))
47}; 39//
48 40//#define TAI_PACK 8
49#define tai_unix(t,u) ((void) ((t)->x = 4611686018427387914ULL + (uint64_t) (u))) 41//extern void tai_unpack(const char *,struct tai *);
50 42//
51#define TAI_PACK 8 43//extern void tai_uint(struct tai *,unsigned);
52//extern void tai_pack(char *,const struct tai *); 44//
53extern void tai_unpack(const char *,struct tai *); 45//struct taia {
54 46// struct tai sec;
55extern void tai_uint(struct tai *,unsigned); 47// unsigned long nano; /* 0...999999999 */
56 48// unsigned long atto; /* 0...999999999 */
57 49//};
58/*** taia.h ***/ 50//
59 51//extern void taia_now(struct taia *);
60struct taia { 52//
61 struct tai sec; 53//extern void taia_add(struct taia *,const struct taia *,const struct taia *);
62 unsigned long nano; /* 0...999999999 */ 54//extern void taia_addsec(struct taia *,const struct taia *,int);
63 unsigned long atto; /* 0...999999999 */ 55//extern void taia_sub(struct taia *,const struct taia *,const struct taia *);
64}; 56//extern void taia_half(struct taia *,const struct taia *);
65 57//extern int taia_less(const struct taia *,const struct taia *);
66//extern void taia_tai(const struct taia *,struct tai *); 58//
67 59//#define TAIA_PACK 16
68extern void taia_now(struct taia *); 60//extern void taia_pack(char *,const struct taia *);
69 61//
70extern void taia_add(struct taia *,const struct taia *,const struct taia *); 62//extern void taia_uint(struct taia *,unsigned);
71extern void taia_addsec(struct taia *,const struct taia *,int); 63//
72extern void taia_sub(struct taia *,const struct taia *,const struct taia *); 64//typedef struct pollfd iopause_fd;
73extern void taia_half(struct taia *,const struct taia *); 65//#define IOPAUSE_READ POLLIN
74extern int taia_less(const struct taia *,const struct taia *); 66//#define IOPAUSE_WRITE POLLOUT
75 67//
76#define TAIA_PACK 16 68//extern void iopause(iopause_fd *,unsigned,struct taia *,struct taia *);
77extern void taia_pack(char *,const struct taia *);
78//extern void taia_unpack(const char *,struct taia *);
79
80//#define TAIA_FMTFRAC 19
81//extern unsigned taia_fmtfrac(char *,const struct taia *);
82
83extern void taia_uint(struct taia *,unsigned);
84
85
86/*** fmt_ptime.h ***/
87
88#define FMT_PTIME 30
89
90/* NUL terminated */
91extern void fmt_ptime30nul(char *, struct taia *);
92/* NOT terminated! */
93extern unsigned fmt_taia25(char *, struct taia *);
94
95
96/*** iopause.h ***/
97
98typedef struct pollfd iopause_fd;
99#define IOPAUSE_READ POLLIN
100#define IOPAUSE_WRITE POLLOUT
101
102extern void iopause(iopause_fd *,unsigned,struct taia *,struct taia *);
103
104
105/*** lock.h ***/
106 69
107extern int lock_ex(int); 70extern int lock_ex(int);
108extern int lock_un(int); 71extern int lock_un(int);
109extern int lock_exnb(int); 72extern int lock_exnb(int);
110 73
111
112/*** open.h ***/
113
114extern int open_read(const char *); 74extern int open_read(const char *);
115extern int open_excl(const char *); 75extern int open_excl(const char *);
116extern int open_append(const char *); 76extern int open_append(const char *);
117extern int open_trunc(const char *); 77extern int open_trunc(const char *);
118extern int open_write(const char *); 78extern int open_write(const char *);
119 79
120
121/*** pmatch.h ***/
122
123extern unsigned pmatch(const char *, const char *, unsigned); 80extern unsigned pmatch(const char *, const char *, unsigned);
124 81
125
126/*** str.h ***/
127
128//extern unsigned str_chr(const char *,int); /* never returns NULL */
129
130#define str_diff(s,t) strcmp((s), (t)) 82#define str_diff(s,t) strcmp((s), (t))
131#define str_equal(s,t) (!strcmp((s), (t))) 83#define str_equal(s,t) (!strcmp((s), (t)))
84
85/*
86 * runsv / supervise / sv stuff
87 */
88typedef struct svstatus_t {
89 uint64_t time_be64;
90 uint32_t time_nsec_be32;
91 uint32_t pid_le32;
92 uint8_t paused;
93 uint8_t want;
94 uint8_t got_term;
95 uint8_t run_or_finish;
96} svstatus_t;
97struct ERR_svstatus_must_be_20_bytes {
98 char ERR_svstatus_must_be_20_bytes[sizeof(svstatus_t) == 20 ? 1 : -1];
99};
diff --git a/runit/runsv.c b/runit/runsv.c
index f70b51390..baef6e13f 100644
--- a/runit/runsv.c
+++ b/runit/runsv.c
@@ -54,21 +54,19 @@ struct svdir {
54 smallint ctrl; 54 smallint ctrl;
55 smallint want; 55 smallint want;
56 smallint islog; 56 smallint islog;
57 struct taia start; 57 struct timespec start;
58 int fdlock; 58 int fdlock;
59 int fdcontrol; 59 int fdcontrol;
60 int fdcontrolwrite; 60 int fdcontrolwrite;
61}; 61};
62static struct svdir svd[2];
63 62
63static struct svdir svd[2];
64static smallint sigterm; 64static smallint sigterm;
65static smallint haslog; 65static smallint haslog;
66static smallint pidchanged = 1; 66static smallint pidchanged = 1;
67static int logpipe[2]; 67static int logpipe[2];
68static char *dir; 68static char *dir;
69 69
70#define usage() bb_show_usage()
71
72static void fatal2_cannot(const char *m1, const char *m2) 70static void fatal2_cannot(const char *m1, const char *m2)
73{ 71{
74 bb_perror_msg_and_die("%s: fatal: cannot %s%s", dir, m1, m2); 72 bb_perror_msg_and_die("%s: fatal: cannot %s%s", dir, m1, m2);
@@ -88,10 +86,6 @@ static void warn_cannot(const char *m)
88{ 86{
89 bb_perror_msg("%s: warning: cannot %s", dir, m); 87 bb_perror_msg("%s: warning: cannot %s", dir, m);
90} 88}
91static void warnx_cannot(const char *m)
92{
93 bb_error_msg("%s: warning: cannot %s", dir, m);
94}
95 89
96static void s_child(int sig_no) 90static void s_child(int sig_no)
97{ 91{
@@ -132,11 +126,19 @@ static int rename_or_warn(const char *old, const char *new)
132 return 0; 126 return 0;
133} 127}
134 128
129#define LESS(a,b) ((int)((unsigned)(b) - (unsigned)(a)) > 0)
130
131#include <sys/syscall.h>
132static void gettimeofday_ns(struct timespec *ts)
133{
134 syscall(__NR_clock_gettime, CLOCK_REALTIME, ts);
135}
136
135static void update_status(struct svdir *s) 137static void update_status(struct svdir *s)
136{ 138{
137 unsigned long l; 139 ssize_t sz;
138 int fd; 140 int fd;
139 char status[20]; 141 svstatus_t status;
140 142
141 /* pid */ 143 /* pid */
142 if (pidchanged) { 144 if (pidchanged) {
@@ -194,40 +196,29 @@ static void update_status(struct svdir *s)
194 s->islog ? "log/supervise/stat" : "log/supervise/stat"+4); 196 s->islog ? "log/supervise/stat" : "log/supervise/stat"+4);
195 197
196 /* supervise compatibility */ 198 /* supervise compatibility */
197 taia_pack(status, &s->start); 199 memset(&status, 0, sizeof(status));
198 l = (unsigned long)s->pid; 200 status.time_be64 = SWAP_BE64(s->start.tv_sec + 0x400000000000000aULL);
199 status[12] = l; l >>=8; 201 status.time_nsec_be32 = SWAP_BE32(s->start.tv_nsec);
200 status[13] = l; l >>=8; 202 status.pid_le32 = SWAP_LE32(s->pid);
201 status[14] = l; l >>=8;
202 status[15] = l;
203 if (s->ctrl & C_PAUSE) 203 if (s->ctrl & C_PAUSE)
204 status[16] = 1; 204 status.paused = 1;
205 else
206 status[16] = 0;
207 if (s->want == W_UP) 205 if (s->want == W_UP)
208 status[17] = 'u'; 206 status.want = 'u';
209 else 207 else
210 status[17] = 'd'; 208 status.want = 'd';
211 if (s->ctrl & C_TERM) 209 if (s->ctrl & C_TERM)
212 status[18] = 1; 210 status.got_term = 1;
213 else 211 status.run_or_finish = s->state;
214 status[18] = 0;
215 status[19] = s->state;
216 fd = open_trunc_or_warn("supervise/status.new"); 212 fd = open_trunc_or_warn("supervise/status.new");
217 if (fd < 0) 213 if (fd < 0)
218 return; 214 return;
219 l = write(fd, status, sizeof(status)); 215 sz = write(fd, &status, sizeof(status));
220 if (l < 0) { 216 close(fd);
217 if (sz != sizeof(status)) {
221 warn_cannot("write supervise/status.new"); 218 warn_cannot("write supervise/status.new");
222 close(fd);
223 unlink("supervise/status.new"); 219 unlink("supervise/status.new");
224 return; 220 return;
225 } 221 }
226 close(fd);
227 if (l < sizeof(status)) {
228 warnx_cannot("write supervise/status.new: partial write");
229 return;
230 }
231 rename_or_warn("supervise/status.new", 222 rename_or_warn("supervise/status.new",
232 s->islog ? "log/supervise/status" : "log/supervise/status"+4); 223 s->islog ? "log/supervise/status" : "log/supervise/status"+4);
233} 224}
@@ -329,7 +320,7 @@ static void startservice(struct svdir *s)
329 fatal2_cannot(s->islog ? "start log/" : "start ", *run); 320 fatal2_cannot(s->islog ? "start log/" : "start ", *run);
330 } 321 }
331 if (s->state != S_FINISH) { 322 if (s->state != S_FINISH) {
332 taia_now(&s->start); 323 gettimeofday_ns(&s->start);
333 s->state = S_RUN; 324 s->state = S_RUN;
334 } 325 }
335 s->pid = p; 326 s->pid = p;
@@ -346,39 +337,48 @@ static int ctrl(struct svdir *s, char c)
346 case 'd': /* down */ 337 case 'd': /* down */
347 s->want = W_DOWN; 338 s->want = W_DOWN;
348 update_status(s); 339 update_status(s);
349 if (s->pid && s->state != S_FINISH) stopservice(s); 340 if (s->pid && s->state != S_FINISH)
341 stopservice(s);
350 break; 342 break;
351 case 'u': /* up */ 343 case 'u': /* up */
352 s->want = W_UP; 344 s->want = W_UP;
353 update_status(s); 345 update_status(s);
354 if (s->pid == 0) startservice(s); 346 if (s->pid == 0)
347 startservice(s);
355 break; 348 break;
356 case 'x': /* exit */ 349 case 'x': /* exit */
357 if (s->islog) break; 350 if (s->islog)
351 break;
358 s->want = W_EXIT; 352 s->want = W_EXIT;
359 update_status(s); 353 update_status(s);
360 /* FALLTHROUGH */ 354 /* FALLTHROUGH */
361 case 't': /* sig term */ 355 case 't': /* sig term */
362 if (s->pid && s->state != S_FINISH) stopservice(s); 356 if (s->pid && s->state != S_FINISH)
357 stopservice(s);
363 break; 358 break;
364 case 'k': /* sig kill */ 359 case 'k': /* sig kill */
365 if (s->pid && !custom(s, c)) kill(s->pid, SIGKILL); 360 if (s->pid && !custom(s, c))
361 kill(s->pid, SIGKILL);
366 s->state = S_DOWN; 362 s->state = S_DOWN;
367 break; 363 break;
368 case 'p': /* sig pause */ 364 case 'p': /* sig pause */
369 if (s->pid && !custom(s, c)) kill(s->pid, SIGSTOP); 365 if (s->pid && !custom(s, c))
366 kill(s->pid, SIGSTOP);
370 s->ctrl |= C_PAUSE; 367 s->ctrl |= C_PAUSE;
371 update_status(s); 368 update_status(s);
372 break; 369 break;
373 case 'c': /* sig cont */ 370 case 'c': /* sig cont */
374 if (s->pid && !custom(s, c)) kill(s->pid, SIGCONT); 371 if (s->pid && !custom(s, c))
375 if (s->ctrl & C_PAUSE) s->ctrl &= ~C_PAUSE; 372 kill(s->pid, SIGCONT);
373 if (s->ctrl & C_PAUSE)
374 s->ctrl &= ~C_PAUSE;
376 update_status(s); 375 update_status(s);
377 break; 376 break;
378 case 'o': /* once */ 377 case 'o': /* once */
379 s->want = W_DOWN; 378 s->want = W_DOWN;
380 update_status(s); 379 update_status(s);
381 if (!s->pid) startservice(s); 380 if (!s->pid)
381 startservice(s);
382 break; 382 break;
383 case 'a': /* sig alarm */ 383 case 'a': /* sig alarm */
384 sig = SIGALRM; 384 sig = SIGALRM;
@@ -414,7 +414,8 @@ int runsv_main(int argc, char **argv)
414 int r; 414 int r;
415 char buf[256]; 415 char buf[256];
416 416
417 if (!argv[1] || argv[2]) usage(); 417 if (!argv[1] || argv[2])
418 bb_show_usage();
418 dir = argv[1]; 419 dir = argv[1];
419 420
420 xpipe(selfpipe); 421 xpipe(selfpipe);
@@ -435,22 +436,23 @@ int runsv_main(int argc, char **argv)
435 if (W_UP) svd[0].want = W_UP; 436 if (W_UP) svd[0].want = W_UP;
436 /* bss: svd[0].islog = 0; */ 437 /* bss: svd[0].islog = 0; */
437 /* bss: svd[1].pid = 0; */ 438 /* bss: svd[1].pid = 0; */
438 taia_now(&svd[0].start); 439 gettimeofday_ns(&svd[0].start);
439 if (stat("down", &s) != -1) svd[0].want = W_DOWN; 440 if (stat("down", &s) != -1) svd[0].want = W_DOWN;
440 441
441 if (stat("log", &s) == -1) { 442 if (stat("log", &s) == -1) {
442 if (errno != ENOENT) 443 if (errno != ENOENT)
443 warn_cannot("stat ./log"); 444 warn_cannot("stat ./log");
444 } else { 445 } else {
445 if (!S_ISDIR(s.st_mode)) 446 if (!S_ISDIR(s.st_mode)) {
446 warnx_cannot("stat log/down: log is not a directory"); 447 errno = 0;
447 else { 448 warn_cannot("stat log/down: log is not a directory");
449 } else {
448 haslog = 1; 450 haslog = 1;
449 svd[1].state = S_DOWN; 451 svd[1].state = S_DOWN;
450 svd[1].ctrl = C_NOOP; 452 svd[1].ctrl = C_NOOP;
451 svd[1].want = W_UP; 453 svd[1].want = W_UP;
452 svd[1].islog = 1; 454 svd[1].islog = 1;
453 taia_now(&svd[1].start); 455 gettimeofday_ns(&svd[1].start);
454 if (stat("log/down", &s) != -1) 456 if (stat("log/down", &s) != -1)
455 svd[1].want = W_DOWN; 457 svd[1].want = W_DOWN;
456 xpipe(logpipe); 458 xpipe(logpipe);
@@ -525,9 +527,8 @@ int runsv_main(int argc, char **argv)
525 coe(fd); 527 coe(fd);
526 } 528 }
527 for (;;) { 529 for (;;) {
528 iopause_fd x[3]; 530 struct pollfd x[3];
529 struct taia deadline; 531 unsigned deadline;
530 struct taia now;
531 char ch; 532 char ch;
532 533
533 if (haslog) 534 if (haslog)
@@ -538,32 +539,30 @@ int runsv_main(int argc, char **argv)
538 startservice(&svd[0]); 539 startservice(&svd[0]);
539 540
540 x[0].fd = selfpipe[0]; 541 x[0].fd = selfpipe[0];
541 x[0].events = IOPAUSE_READ; 542 x[0].events = POLLIN;
542 x[1].fd = svd[0].fdcontrol; 543 x[1].fd = svd[0].fdcontrol;
543 x[1].events = IOPAUSE_READ; 544 x[1].events = POLLIN;
544 if (haslog) { 545 /* x[2] is used only if haslog == 1 */
545 x[2].fd = svd[1].fdcontrol; 546 x[2].fd = svd[1].fdcontrol;
546 x[2].events = IOPAUSE_READ; 547 x[2].events = POLLIN;
547 }
548 taia_now(&now);
549 taia_uint(&deadline, 3600);
550 taia_add(&deadline, &now, &deadline);
551
552 sig_unblock(SIGTERM); 548 sig_unblock(SIGTERM);
553 sig_unblock(SIGCHLD); 549 sig_unblock(SIGCHLD);
554 iopause(x, 2+haslog, &deadline, &now); 550 poll(x, 2 + haslog, 3600*1000);
555 sig_block(SIGTERM); 551 sig_block(SIGTERM);
556 sig_block(SIGCHLD); 552 sig_block(SIGCHLD);
557 553
558 while (read(selfpipe[0], &ch, 1) == 1) 554 while (read(selfpipe[0], &ch, 1) == 1)
559 ; 555 continue;
556
560 for (;;) { 557 for (;;) {
561 int child; 558 int child;
562 int wstat; 559 int wstat;
563 560
564 child = wait_nohang(&wstat); 561 child = wait_nohang(&wstat);
565 if (!child) break; 562 if (!child)
566 if ((child == -1) && (errno != EINTR)) break; 563 break;
564 if ((child == -1) && (errno != EINTR))
565 break;
567 if (child == svd[0].pid) { 566 if (child == svd[0].pid) {
568 svd[0].pid = 0; 567 svd[0].pid = 0;
569 pidchanged = 1; 568 pidchanged = 1;
@@ -578,11 +577,11 @@ int runsv_main(int argc, char **argv)
578 } 577 }
579 } 578 }
580 svd[0].state = S_DOWN; 579 svd[0].state = S_DOWN;
581 taia_uint(&deadline, 1); 580 deadline = svd[0].start.tv_sec + 1;
582 taia_add(&deadline, &svd[0].start, &deadline); 581 gettimeofday_ns(&svd[0].start);
583 taia_now(&svd[0].start);
584 update_status(&svd[0]); 582 update_status(&svd[0]);
585 if (taia_less(&svd[0].start, &deadline)) sleep(1); 583 if (LESS(svd[0].start.tv_sec, deadline))
584 sleep(1);
586 } 585 }
587 if (haslog) { 586 if (haslog) {
588 if (child == svd[1].pid) { 587 if (child == svd[1].pid) {
@@ -590,11 +589,11 @@ int runsv_main(int argc, char **argv)
590 pidchanged = 1; 589 pidchanged = 1;
591 svd[1].state = S_DOWN; 590 svd[1].state = S_DOWN;
592 svd[1].ctrl &= ~C_TERM; 591 svd[1].ctrl &= ~C_TERM;
593 taia_uint(&deadline, 1); 592 deadline = svd[1].start.tv_sec + 1;
594 taia_add(&deadline, &svd[1].start, &deadline); 593 gettimeofday_ns(&svd[1].start);
595 taia_now(&svd[1].start);
596 update_status(&svd[1]); 594 update_status(&svd[1]);
597 if (taia_less(&svd[1].start, &deadline)) sleep(1); 595 if (LESS(svd[1].start.tv_sec, deadline))
596 sleep(1);
598 } 597 }
599 } 598 }
600 } 599 }
@@ -618,10 +617,6 @@ int runsv_main(int argc, char **argv)
618 update_status(&svd[1]); 617 update_status(&svd[1]);
619 close(logpipe[1]); 618 close(logpipe[1]);
620 close(logpipe[0]); 619 close(logpipe[0]);
621 //if (close(logpipe[1]) == -1)
622 // warn_cannot("close logpipe[1]");
623 //if (close(logpipe[0]) == -1)
624 // warn_cannot("close logpipe[0]");
625 } 620 }
626 } 621 }
627 } 622 }
diff --git a/runit/runsvdir.c b/runit/runsvdir.c
index 8db0fc189..38da7f8ae 100644
--- a/runit/runsvdir.c
+++ b/runit/runsvdir.c
@@ -35,26 +35,25 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 35
36#define MAXSERVICES 1000 36#define MAXSERVICES 1000
37 37
38struct service {
39 dev_t dev;
40 ino_t ino;
41 pid_t pid;
42 smallint isgone;
43};
44
45struct service *sv;
38static char *svdir; 46static char *svdir;
39static unsigned long dev;
40static unsigned long ino;
41static struct service {
42 unsigned long dev;
43 unsigned long ino;
44 int pid;
45 int isgone;
46} *sv;
47static int svnum; 47static int svnum;
48static int check = 1;
49static char *rplog; 48static char *rplog;
50static int rploglen; 49static int rploglen;
51static int logpipe[2]; 50static int logpipe[2];
52static iopause_fd io[1]; 51static struct pollfd pfd[1];
53static struct taia stamplog; 52static unsigned stamplog;
54static int exitsoon; 53static smallint check = 1;
55static int pgrp; 54static smallint exitsoon;
55static smallint set_pgrp;
56 56
57#define usage() bb_show_usage()
58static void fatal2_cannot(const char *m1, const char *m2) 57static void fatal2_cannot(const char *m1, const char *m2)
59{ 58{
60 bb_perror_msg_and_die("%s: fatal: cannot %s%s", svdir, m1, m2); 59 bb_perror_msg_and_die("%s: fatal: cannot %s%s", svdir, m1, m2);
@@ -84,25 +83,26 @@ static void s_hangup(int sig_no)
84 83
85static void runsv(int no, const char *name) 84static void runsv(int no, const char *name)
86{ 85{
87 int pid = fork(); 86 pid_t pid;
87 char *prog[3];
88
89 prog[0] = (char*)"runsv";
90 prog[1] = (char*)name;
91 prog[2] = NULL;
92
93 pid = vfork();
88 94
89 if (pid == -1) { 95 if (pid == -1) {
90 warn2_cannot("fork for ", name); 96 warn2_cannot("vfork", "");
91 return; 97 return;
92 } 98 }
93 if (pid == 0) { 99 if (pid == 0) {
94 /* child */ 100 /* child */
95 char *prog[3]; 101 if (set_pgrp)
96
97 prog[0] = (char*)"runsv";
98 prog[1] = (char*)name;
99 prog[2] = NULL;
100 if (pgrp)
101 setsid(); 102 setsid();
102 signal(SIGHUP, SIG_DFL); 103 signal(SIGHUP, SIG_DFL);
103 signal(SIGTERM, SIG_DFL); 104 signal(SIGTERM, SIG_DFL);
104 BB_EXECVP(prog[0], prog); 105 execvp(prog[0], prog);
105 //pathexec_run(*prog, prog, (char* const*)environ);
106 fatal2_cannot("start runsv ", name); 106 fatal2_cannot("start runsv ", name);
107 } 107 }
108 sv[no].pid = pid; 108 sv[no].pid = pid;
@@ -124,13 +124,15 @@ static void runsvdir(void)
124 sv[i].isgone = 1; 124 sv[i].isgone = 1;
125 errno = 0; 125 errno = 0;
126 while ((d = readdir(dir))) { 126 while ((d = readdir(dir))) {
127 if (d->d_name[0] == '.') continue; 127 if (d->d_name[0] == '.')
128 continue;
128 if (stat(d->d_name, &s) == -1) { 129 if (stat(d->d_name, &s) == -1) {
129 warn2_cannot("stat ", d->d_name); 130 warn2_cannot("stat ", d->d_name);
130 errno = 0; 131 errno = 0;
131 continue; 132 continue;
132 } 133 }
133 if (!S_ISDIR(s.st_mode)) continue; 134 if (!S_ISDIR(s.st_mode))
135 continue;
134 for (i = 0; i < svnum; i++) { 136 for (i = 0; i < svnum; i++) {
135 if ((sv[i].ino == s.st_ino) && (sv[i].dev == s.st_dev)) { 137 if ((sv[i].ino == s.st_ino) && (sv[i].dev == s.st_dev)) {
136 sv[i].isgone = 0; 138 sv[i].isgone = 0;
@@ -152,8 +154,8 @@ static void runsvdir(void)
152 memset(&sv[i], 0, sizeof(sv[i])); 154 memset(&sv[i], 0, sizeof(sv[i]));
153 sv[i].ino = s.st_ino; 155 sv[i].ino = s.st_ino;
154 sv[i].dev = s.st_dev; 156 sv[i].dev = s.st_dev;
155 //sv[i].pid = 0; 157 /*sv[i].pid = 0;*/
156 //sv[i].isgone = 0; 158 /*sv[i].isgone = 0;*/
157 runsv(i, d->d_name); 159 runsv(i, d->d_name);
158 check = 1; 160 check = 1;
159 } 161 }
@@ -196,9 +198,9 @@ static int setup_log(void)
196 warnx("cannot set filedescriptor for log"); 198 warnx("cannot set filedescriptor for log");
197 return -1; 199 return -1;
198 } 200 }
199 io[0].fd = logpipe[0]; 201 pfd[0].fd = logpipe[0];
200 io[0].events = IOPAUSE_READ; 202 pfd[0].events = POLLIN;
201 taia_now(&stamplog); 203 stamplog = monotonic_sec();
202 return 1; 204 return 1;
203} 205}
204 206
@@ -206,24 +208,28 @@ int runsvdir_main(int argc, char **argv);
206int runsvdir_main(int argc, char **argv) 208int runsvdir_main(int argc, char **argv)
207{ 209{
208 struct stat s; 210 struct stat s;
209 time_t mtime = 0; 211 dev_t last_dev = last_dev; /* for gcc */
212 ino_t last_ino = last_ino; /* for gcc */
213 time_t last_mtime = 0;
210 int wstat; 214 int wstat;
211 int curdir; 215 int curdir;
212 int pid; 216 int pid;
213 struct taia deadline; 217 unsigned deadline;
214 struct taia now; 218 unsigned now;
215 struct taia stampcheck; 219 unsigned stampcheck;
216 char ch; 220 char ch;
217 int i; 221 int i;
218 222
219 argv++; 223 argv++;
220 if (!argv || !*argv) usage(); 224 if (!*argv)
221 if (**argv == '-') { 225 bb_show_usage();
222 switch (*(*argv + 1)) { 226 if (argv[0][0] == '-') {
223 case 'P': pgrp = 1; 227 switch (argv[0][1]) {
228 case 'P': set_pgrp = 1;
224 case '-': ++argv; 229 case '-': ++argv;
225 } 230 }
226 if (!argv || !*argv) usage(); 231 if (!*argv)
232 bb_show_usage();
227 } 233 }
228 234
229 sig_catch(SIGTERM, s_term); 235 sig_catch(SIGTERM, s_term);
@@ -241,13 +247,14 @@ int runsvdir_main(int argc, char **argv)
241 fatal2_cannot("open current directory", ""); 247 fatal2_cannot("open current directory", "");
242 coe(curdir); 248 coe(curdir);
243 249
244 taia_now(&stampcheck); 250 stampcheck = monotonic_sec();
245 251
246 for (;;) { 252 for (;;) {
247 /* collect children */ 253 /* collect children */
248 for (;;) { 254 for (;;) {
249 pid = wait_nohang(&wstat); 255 pid = wait_nohang(&wstat);
250 if (pid <= 0) break; 256 if (pid <= 0)
257 break;
251 for (i = 0; i < svnum; i++) { 258 for (i = 0; i < svnum; i++) {
252 if (pid == sv[i].pid) { 259 if (pid == sv[i].pid) {
253 /* runsv has gone */ 260 /* runsv has gone */
@@ -258,31 +265,23 @@ int runsvdir_main(int argc, char **argv)
258 } 265 }
259 } 266 }
260 267
261 taia_now(&now); 268 now = monotonic_sec();
262 if (now.sec.x < (stampcheck.sec.x - 3)) { 269 if ((int)(now - stampcheck) >= 0) {
263 /* time warp */
264 warnx("time warp: resetting time stamp");
265 taia_now(&stampcheck);
266 taia_now(&now);
267 if (rplog) taia_now(&stamplog);
268 }
269 if (taia_less(&now, &stampcheck) == 0) {
270 /* wait at least a second */ 270 /* wait at least a second */
271 taia_uint(&deadline, 1); 271 stampcheck = now + 1;
272 taia_add(&stampcheck, &now, &deadline);
273 272
274 if (stat(svdir, &s) != -1) { 273 if (stat(svdir, &s) != -1) {
275 if (check || s.st_mtime != mtime 274 if (check || s.st_mtime != last_mtime
276 || s.st_ino != ino || s.st_dev != dev 275 || s.st_ino != last_ino || s.st_dev != last_dev
277 ) { 276 ) {
278 /* svdir modified */ 277 /* svdir modified */
279 if (chdir(svdir) != -1) { 278 if (chdir(svdir) != -1) {
280 mtime = s.st_mtime; 279 last_mtime = s.st_mtime;
281 dev = s.st_dev; 280 last_dev = s.st_dev;
282 ino = s.st_ino; 281 last_ino = s.st_ino;
283 check = 0; 282 check = 0;
284 if (now.sec.x <= (4611686018427387914ULL + (uint64_t)mtime)) 283 //if (now <= mtime)
285 sleep(1); 284 // sleep(1);
286 runsvdir(); 285 runsvdir();
287 while (fchdir(curdir) == -1) { 286 while (fchdir(curdir) == -1) {
288 warn2_cannot("change directory, pausing", ""); 287 warn2_cannot("change directory, pausing", "");
@@ -296,29 +295,30 @@ int runsvdir_main(int argc, char **argv)
296 } 295 }
297 296
298 if (rplog) { 297 if (rplog) {
299 if (taia_less(&now, &stamplog) == 0) { 298 if ((int)(now - stamplog) >= 0) {
300 write(logpipe[1], ".", 1); 299 write(logpipe[1], ".", 1);
301 taia_uint(&deadline, 900); 300 stamplog = now + 900;
302 taia_add(&stamplog, &now, &deadline);
303 } 301 }
304 } 302 }
305 taia_uint(&deadline, check ? 1 : 5); 303 deadline = now + (check ? 1 : 5);
306 taia_add(&deadline, &now, &deadline);
307 304
305 pfd[0].revents = 0;
308 sig_block(SIGCHLD); 306 sig_block(SIGCHLD);
309 if (rplog) 307 if (rplog)
310 iopause(io, 1, &deadline, &now); 308 poll(pfd, 1, deadline*1000);
311 else 309 else
312 iopause(0, 0, &deadline, &now); 310 sleep(deadline);
313 sig_unblock(SIGCHLD); 311 sig_unblock(SIGCHLD);
314 312
315 if (rplog && (io[0].revents | IOPAUSE_READ)) 313 if (pfd[0].revents & POLLIN) {
316 while (read(logpipe[0], &ch, 1) > 0) 314 while (read(logpipe[0], &ch, 1) > 0) {
317 if (ch) { 315 if (ch) {
318 for (i = 6; i < rploglen; i++) 316 for (i = 6; i < rploglen; i++)
319 rplog[i-1] = rplog[i]; 317 rplog[i-1] = rplog[i];
320 rplog[rploglen-1] = ch; 318 rplog[rploglen-1] = ch;
321 } 319 }
320 }
321 }
322 322
323 switch (exitsoon) { 323 switch (exitsoon) {
324 case 1: 324 case 1:
diff --git a/runit/sv.c b/runit/sv.c
index e9bfc75c5..c87f565cc 100644
--- a/runit/sv.c
+++ b/runit/sv.c
@@ -161,10 +161,10 @@ Exit Codes
161static const char *acts; 161static const char *acts;
162static char **service; 162static char **service;
163static unsigned rc; 163static unsigned rc;
164static struct taia tstart, tnow; 164/* "Bernstein" time format: unix + 0x400000000000000aULL */
165static char svstatus[20]; 165static uint64_t tstart, tnow;
166svstatus_t svstatus;
166 167
167#define usage() bb_show_usage()
168 168
169static void fatal_cannot(const char *m1) ATTRIBUTE_NORETURN; 169static void fatal_cannot(const char *m1) ATTRIBUTE_NORETURN;
170static void fatal_cannot(const char *m1) 170static void fatal_cannot(const char *m1)
@@ -195,15 +195,11 @@ static void failx(const char *m1)
195 errno = 0; 195 errno = 0;
196 fail(m1); 196 fail(m1);
197} 197}
198static void warn_cannot(const char *m1) 198static void warn(const char *m1)
199{ 199{
200 ++rc; 200 ++rc;
201 out("warning: cannot ", m1); 201 /* "warning: <service>: <m1>\n" */
202} 202 out("warning: ", m1);
203static void warnx_cannot(const char *m1)
204{
205 errno = 0;
206 warn_cannot(m1);
207} 203}
208static void ok(const char *m1) 204static void ok(const char *m1)
209{ 205{
@@ -222,32 +218,38 @@ static int svstatus_get(void)
222 : failx("runsv not running"); 218 : failx("runsv not running");
223 return 0; 219 return 0;
224 } 220 }
225 warn_cannot("open supervise/ok"); 221 warn("cannot open supervise/ok");
226 return -1; 222 return -1;
227 } 223 }
228 close(fd); 224 close(fd);
229 fd = open_read("supervise/status"); 225 fd = open_read("supervise/status");
230 if (fd == -1) { 226 if (fd == -1) {
231 warn_cannot("open supervise/status"); 227 warn("cannot open supervise/status");
232 return -1; 228 return -1;
233 } 229 }
234 r = read(fd, svstatus, 20); 230 r = read(fd, &svstatus, 20);
235 close(fd); 231 close(fd);
236 switch (r) { 232 switch (r) {
237 case 20: break; 233 case 20:
238 case -1: warn_cannot("read supervise/status"); return -1; 234 break;
239 default: warnx_cannot("read supervise/status: bad format"); return -1; 235 case -1:
236 warn("cannot read supervise/status");
237 return -1;
238 default:
239 errno = 0;
240 warn("cannot read supervise/status: bad format");
241 return -1;
240 } 242 }
241 return 1; 243 return 1;
242} 244}
243 245
244static unsigned svstatus_print(const char *m) 246static unsigned svstatus_print(const char *m)
245{ 247{
246 long diff; 248 int diff;
247 int pid; 249 int pid;
248 int normallyup = 0; 250 int normallyup = 0;
249 struct stat s; 251 struct stat s;
250 struct tai tstatus; 252 uint64_t timestamp;
251 253
252 if (stat("down", &s) == -1) { 254 if (stat("down", &s) == -1) {
253 if (errno != ENOENT) { 255 if (errno != ENOENT) {
@@ -256,13 +258,10 @@ static unsigned svstatus_print(const char *m)
256 } 258 }
257 normallyup = 1; 259 normallyup = 1;
258 } 260 }
259 pid = (unsigned char) svstatus[15]; 261 pid = SWAP_LE32(svstatus.pid_le32);
260 pid <<= 8; pid += (unsigned char)svstatus[14]; 262 timestamp = SWAP_BE64(svstatus.time_be64);
261 pid <<= 8; pid += (unsigned char)svstatus[13];
262 pid <<= 8; pid += (unsigned char)svstatus[12];
263 tai_unpack(svstatus, &tstatus);
264 if (pid) { 263 if (pid) {
265 switch (svstatus[19]) { 264 switch (svstatus.run_or_finish) {
266 case 1: printf("run: "); break; 265 case 1: printf("run: "); break;
267 case 2: printf("finish: "); break; 266 case 2: printf("finish: "); break;
268 } 267 }
@@ -270,16 +269,16 @@ static unsigned svstatus_print(const char *m)
270 } else { 269 } else {
271 printf("down: %s: ", m); 270 printf("down: %s: ", m);
272 } 271 }
273 diff = tnow.sec.x - tstatus.x; 272 diff = tnow - timestamp;
274 printf("%lds", (diff < 0 ? 0L : diff)); 273 printf("%us", (diff < 0 ? 0 : diff));
275 if (pid) { 274 if (pid) {
276 if (!normallyup) printf(", normally down"); 275 if (!normallyup) printf(", normally down");
277 if (svstatus[16]) printf(", paused"); 276 if (svstatus.paused) printf(", paused");
278 if (svstatus[17] == 'd') printf(", want down"); 277 if (svstatus.want == 'd') printf(", want down");
279 if (svstatus[18]) printf(", got TERM"); 278 if (svstatus.got_term) printf(", got TERM");
280 } else { 279 } else {
281 if (normallyup) printf(", normally up"); 280 if (normallyup) printf(", normally up");
282 if (svstatus[17] == 'u') printf(", want up"); 281 if (svstatus.want == 'u') printf(", want up");
283 } 282 }
284 return pid ? 1 : 2; 283 return pid ? 1 : 2;
285} 284}
@@ -336,7 +335,7 @@ static int check(const char *a)
336{ 335{
337 int r; 336 int r;
338 unsigned pid; 337 unsigned pid;
339 struct tai tstatus; 338 uint64_t timestamp;
340 339
341 r = svstatus_get(); 340 r = svstatus_get();
342 if (r == -1) 341 if (r == -1)
@@ -346,15 +345,12 @@ static int check(const char *a)
346 return 1; 345 return 1;
347 return -1; 346 return -1;
348 } 347 }
349 pid = (unsigned char)svstatus[15]; 348 pid = SWAP_LE32(svstatus.pid_le32);
350 pid <<= 8; pid += (unsigned char)svstatus[14];
351 pid <<= 8; pid += (unsigned char)svstatus[13];
352 pid <<= 8; pid += (unsigned char)svstatus[12];
353 switch (*a) { 349 switch (*a) {
354 case 'x': 350 case 'x':
355 return 0; 351 return 0;
356 case 'u': 352 case 'u':
357 if (!pid || svstatus[19] != 1) return 0; 353 if (!pid || svstatus.run_or_finish != 1) return 0;
358 if (!checkscript()) return 0; 354 if (!checkscript()) return 0;
359 break; 355 break;
360 case 'd': 356 case 'd':
@@ -364,14 +360,14 @@ static int check(const char *a)
364 if (pid && !checkscript()) return 0; 360 if (pid && !checkscript()) return 0;
365 break; 361 break;
366 case 't': 362 case 't':
367 if (!pid && svstatus[17] == 'd') break; 363 if (!pid && svstatus.want == 'd') break;
368 tai_unpack(svstatus, &tstatus); 364 timestamp = SWAP_BE64(svstatus.time_be64);
369 if ((tstart.sec.x > tstatus.x) || !pid || svstatus[18] || !checkscript()) 365 if ((tstart > timestamp) || !pid || svstatus.got_term || !checkscript())
370 return 0; 366 return 0;
371 break; 367 break;
372 case 'o': 368 case 'o':
373 tai_unpack(svstatus, &tstatus); 369 timestamp = SWAP_BE64(svstatus.time_be64);
374 if ((!pid && tstart.sec.x > tstatus.x) || (pid && svstatus[17] != 'd')) 370 if ((!pid && tstart > timestamp) || (pid && svstatus.want != 'd'))
375 return 0; 371 return 0;
376 } 372 }
377 printf(OK); 373 printf(OK);
@@ -384,12 +380,14 @@ static int control(const char *a)
384{ 380{
385 int fd, r; 381 int fd, r;
386 382
387 if (svstatus_get() <= 0) return -1; 383 if (svstatus_get() <= 0)
388 if (svstatus[17] == *a) return 0; 384 return -1;
385 if (svstatus.want == *a)
386 return 0;
389 fd = open_write("supervise/control"); 387 fd = open_write("supervise/control");
390 if (fd == -1) { 388 if (fd == -1) {
391 if (errno != ENODEV) 389 if (errno != ENODEV)
392 warn_cannot("open supervise/control"); 390 warn("cannot open supervise/control");
393 else 391 else
394 *a == 'x' ? ok("runsv not running") : failx("runsv not running"); 392 *a == 'x' ? ok("runsv not running") : failx("runsv not running");
395 return -1; 393 return -1;
@@ -397,7 +395,7 @@ static int control(const char *a)
397 r = write(fd, a, strlen(a)); 395 r = write(fd, a, strlen(a));
398 close(fd); 396 close(fd);
399 if (r != strlen(a)) { 397 if (r != strlen(a)) {
400 warn_cannot("write to supervise/control"); 398 warn("cannot write to supervise/control");
401 return -1; 399 return -1;
402 } 400 }
403 return 1; 401 return 1;
@@ -413,7 +411,7 @@ int sv_main(int argc, char **argv)
413 const char *varservice = "/var/service/"; 411 const char *varservice = "/var/service/";
414 unsigned services; 412 unsigned services;
415 char **servicex; 413 char **servicex;
416 unsigned long waitsec = 7; 414 unsigned waitsec = 7;
417 smallint kll = 0; 415 smallint kll = 0;
418 smallint verbose = 0; 416 smallint verbose = 0;
419 int (*act)(const char*); 417 int (*act)(const char*);
@@ -425,19 +423,19 @@ int sv_main(int argc, char **argv)
425 x = getenv("SVDIR"); 423 x = getenv("SVDIR");
426 if (x) varservice = x; 424 if (x) varservice = x;
427 x = getenv("SVWAIT"); 425 x = getenv("SVWAIT");
428 if (x) waitsec = xatoul(x); 426 if (x) waitsec = xatou(x);
429 427
430 opt = getopt32(argv, "w:v", &x); 428 opt = getopt32(argv, "w:v", &x);
431 if (opt & 1) waitsec = xatoul(x); // -w 429 if (opt & 1) waitsec = xatou(x); // -w
432 if (opt & 2) verbose = 1; // -v 430 if (opt & 2) verbose = 1; // -v
433 argc -= optind; 431 argc -= optind;
434 argv += optind; 432 argv += optind;
435 action = *argv++; 433 action = *argv++;
436 if (!action || !*argv) usage(); 434 if (!action || !*argv) bb_show_usage();
437 service = argv; 435 service = argv;
438 services = argc - 1; 436 services = argc - 1;
439 437
440 taia_now(&tnow); 438 tnow = time(0) + 0x400000000000000aULL;
441 tstart = tnow; 439 tstart = tnow;
442 curdir = open_read("."); 440 curdir = open_read(".");
443 if (curdir == -1) 441 if (curdir == -1)
@@ -467,7 +465,7 @@ int sv_main(int argc, char **argv)
467 kll = 1; 465 kll = 1;
468 break; 466 break;
469 case 'c': 467 case 'c':
470 if (!str_diff(action, "check")) { 468 if (str_equal(action, "check")) {
471 act = NULL; 469 act = NULL;
472 acts = "c"; 470 acts = "c";
473 break; 471 break;
@@ -479,15 +477,15 @@ int sv_main(int argc, char **argv)
479 if (!verbose) cbk = NULL; 477 if (!verbose) cbk = NULL;
480 break; 478 break;
481 case 's': 479 case 's':
482 if (!str_diff(action, "shutdown")) { 480 if (str_equal(action, "shutdown")) {
483 acts = "x"; 481 acts = "x";
484 break; 482 break;
485 } 483 }
486 if (!str_diff(action, "start")) { 484 if (str_equal(action, "start")) {
487 acts = "u"; 485 acts = "u";
488 break; 486 break;
489 } 487 }
490 if (!str_diff(action, "stop")) { 488 if (str_equal(action, "stop")) {
491 acts = "d"; 489 acts = "d";
492 break; 490 break;
493 } 491 }
@@ -496,34 +494,34 @@ int sv_main(int argc, char **argv)
496 cbk = NULL; 494 cbk = NULL;
497 break; 495 break;
498 case 'r': 496 case 'r':
499 if (!str_diff(action, "restart")) { 497 if (str_equal(action, "restart")) {
500 acts = "tcu"; 498 acts = "tcu";
501 break; 499 break;
502 } 500 }
503 usage(); 501 bb_show_usage();
504 case 'f': 502 case 'f':
505 if (!str_diff(action, "force-reload")) { 503 if (str_equal(action, "force-reload")) {
506 acts = "tc"; 504 acts = "tc";
507 kll = 1; 505 kll = 1;
508 break; 506 break;
509 } 507 }
510 if (!str_diff(action, "force-restart")) { 508 if (str_equal(action, "force-restart")) {
511 acts = "tcu"; 509 acts = "tcu";
512 kll = 1; 510 kll = 1;
513 break; 511 break;
514 } 512 }
515 if (!str_diff(action, "force-shutdown")) { 513 if (str_equal(action, "force-shutdown")) {
516 acts = "x"; 514 acts = "x";
517 kll = 1; 515 kll = 1;
518 break; 516 break;
519 } 517 }
520 if (!str_diff(action, "force-stop")) { 518 if (str_equal(action, "force-stop")) {
521 acts = "d"; 519 acts = "d";
522 kll = 1; 520 kll = 1;
523 break; 521 break;
524 } 522 }
525 default: 523 default:
526 usage(); 524 bb_show_usage();
527 } 525 }
528 526
529 servicex = service; 527 servicex = service;
@@ -547,11 +545,9 @@ int sv_main(int argc, char **argv)
547 } 545 }
548 546
549 if (cbk) while (1) { 547 if (cbk) while (1) {
550 //struct taia tdiff; 548 int diff;
551 long diff;
552 549
553 //taia_sub(&tdiff, &tnow, &tstart); 550 diff = tnow - tstart;
554 diff = tnow.sec.x - tstart.sec.x;
555 service = servicex; 551 service = servicex;
556 want_exit = 1; 552 want_exit = 1;
557 for (i = 0; i < services; ++i, ++service) { 553 for (i = 0; i < services; ++i, ++service) {
@@ -586,7 +582,7 @@ int sv_main(int argc, char **argv)
586 } 582 }
587 if (want_exit) break; 583 if (want_exit) break;
588 usleep(420000); 584 usleep(420000);
589 taia_now(&tnow); 585 tnow = time(0) + 0x400000000000000aULL;
590 } 586 }
591 return rc > 99 ? 99 : rc; 587 return rc > 99 ? 99 : rc;
592} 588}
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';