diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2007-08-20 17:27:40 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2007-08-20 17:27:40 +0000 |
commit | 45946f8b513d9c292613ac08c3ddf4a89b915752 (patch) | |
tree | d6ea51887431e4261a114b95989950d1973d3227 | |
parent | 63db27f9f4c0ec8b9abe3c32c8d699be0781ffd6 (diff) | |
download | busybox-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.c | 5 | ||||
-rw-r--r-- | runit/runit_lib.c | 147 | ||||
-rw-r--r-- | runit/runit_lib.h | 134 | ||||
-rw-r--r-- | runit/runsv.c | 151 | ||||
-rw-r--r-- | runit/runsvdir.c | 138 | ||||
-rw-r--r-- | runit/sv.c | 128 | ||||
-rw-r--r-- | runit/svlogd.c | 198 |
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. */ |
158 | struct dummy { | 158 | struct 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 | ||
163 | static smallint flag_dump_strings; | 162 | static 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 | |||
39 | unsigned byte_chr(char *s,unsigned n,int c) | 37 | unsigned 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 | |||
58 | int coe(int fd) | 53 | int 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 | |||
66 | void 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 | ||
97 | unsigned 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 | |||
109 | static /* as it isn't used anywhere else */ | 59 | static /* as it isn't used anywhere else */ |
110 | void tai_pack(char *s,const struct tai *t) | 60 | void 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 | |||
129 | void 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 | |||
138 | void tai_unpack(const char *s,struct tai *t) | 75 | void 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 | |||
156 | void taia_add(struct taia *t,const struct taia *u,const struct taia *v) | 91 | void 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 | |||
174 | int taia_less(const struct taia *t, const struct taia *u) | 106 | int 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 | |||
186 | void taia_now(struct taia *t) | 115 | void 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 | |||
198 | void taia_pack(char *s, const struct taia *t) | 125 | void 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 | ||
220 | void taia_sub(struct taia *t, const struct taia *u, const struct taia *v) | 145 | void 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 | |||
243 | void taia_uint(struct taia *t, unsigned s) | 164 | void 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 | |||
253 | static | 171 | static |
254 | uint64_t taia2millisec(const struct taia *t) | 172 | uint64_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 | |||
260 | void iopause(iopause_fd *x, unsigned len, struct taia *deadline, struct taia *stamp) | 177 | void 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 | ||
289 | int lock_ex(int fd) | 204 | int 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 | |||
297 | int lock_exnb(int fd) | 209 | int 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 | |||
305 | int open_append(const char *fn) | 214 | int 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 | |||
313 | int open_read(const char *fn) | 219 | int 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 | |||
321 | int open_trunc(const char *fn) | 224 | int 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 | |||
329 | int open_write(const char *fn) | 229 | int 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 | 234 | unsigned pmatch(const char *p, const char *s, unsigned len) | |
335 | /*** pmatch.c ***/ | 235 | { |
336 | |||
337 | unsigned 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 | |||
381 | int 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? | ||
390 | unsigned 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 | |||
25 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 25 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
26 | */ | 26 | */ |
27 | 27 | ||
28 | /*** byte.h ***/ | ||
29 | |||
30 | extern unsigned byte_chr(char *s,unsigned n,int c); | 28 | extern unsigned byte_chr(char *s,unsigned n,int c); |
31 | 29 | ||
32 | |||
33 | /*** coe.h ***/ | ||
34 | |||
35 | extern int coe(int); | 30 | extern 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 | //}; | |
45 | struct 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 | // |
53 | extern void tai_unpack(const char *,struct tai *); | 45 | //struct taia { |
54 | 46 | // struct tai sec; | |
55 | extern 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 *); | |
60 | struct 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 | |
68 | extern void taia_now(struct taia *); | 60 | //extern void taia_pack(char *,const struct taia *); |
69 | 61 | // | |
70 | extern void taia_add(struct taia *,const struct taia *,const struct taia *); | 62 | //extern void taia_uint(struct taia *,unsigned); |
71 | extern void taia_addsec(struct taia *,const struct taia *,int); | 63 | // |
72 | extern void taia_sub(struct taia *,const struct taia *,const struct taia *); | 64 | //typedef struct pollfd iopause_fd; |
73 | extern void taia_half(struct taia *,const struct taia *); | 65 | //#define IOPAUSE_READ POLLIN |
74 | extern 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 *); |
77 | extern 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 | |||
83 | extern void taia_uint(struct taia *,unsigned); | ||
84 | |||
85 | |||
86 | /*** fmt_ptime.h ***/ | ||
87 | |||
88 | #define FMT_PTIME 30 | ||
89 | |||
90 | /* NUL terminated */ | ||
91 | extern void fmt_ptime30nul(char *, struct taia *); | ||
92 | /* NOT terminated! */ | ||
93 | extern unsigned fmt_taia25(char *, struct taia *); | ||
94 | |||
95 | |||
96 | /*** iopause.h ***/ | ||
97 | |||
98 | typedef struct pollfd iopause_fd; | ||
99 | #define IOPAUSE_READ POLLIN | ||
100 | #define IOPAUSE_WRITE POLLOUT | ||
101 | |||
102 | extern void iopause(iopause_fd *,unsigned,struct taia *,struct taia *); | ||
103 | |||
104 | |||
105 | /*** lock.h ***/ | ||
106 | 69 | ||
107 | extern int lock_ex(int); | 70 | extern int lock_ex(int); |
108 | extern int lock_un(int); | 71 | extern int lock_un(int); |
109 | extern int lock_exnb(int); | 72 | extern int lock_exnb(int); |
110 | 73 | ||
111 | |||
112 | /*** open.h ***/ | ||
113 | |||
114 | extern int open_read(const char *); | 74 | extern int open_read(const char *); |
115 | extern int open_excl(const char *); | 75 | extern int open_excl(const char *); |
116 | extern int open_append(const char *); | 76 | extern int open_append(const char *); |
117 | extern int open_trunc(const char *); | 77 | extern int open_trunc(const char *); |
118 | extern int open_write(const char *); | 78 | extern int open_write(const char *); |
119 | 79 | ||
120 | |||
121 | /*** pmatch.h ***/ | ||
122 | |||
123 | extern unsigned pmatch(const char *, const char *, unsigned); | 80 | extern 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 | */ | ||
88 | typedef 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; | ||
97 | struct 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 | }; |
62 | static struct svdir svd[2]; | ||
63 | 62 | ||
63 | static struct svdir svd[2]; | ||
64 | static smallint sigterm; | 64 | static smallint sigterm; |
65 | static smallint haslog; | 65 | static smallint haslog; |
66 | static smallint pidchanged = 1; | 66 | static smallint pidchanged = 1; |
67 | static int logpipe[2]; | 67 | static int logpipe[2]; |
68 | static char *dir; | 68 | static char *dir; |
69 | 69 | ||
70 | #define usage() bb_show_usage() | ||
71 | |||
72 | static void fatal2_cannot(const char *m1, const char *m2) | 70 | static 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 | } |
91 | static void warnx_cannot(const char *m) | ||
92 | { | ||
93 | bb_error_msg("%s: warning: cannot %s", dir, m); | ||
94 | } | ||
95 | 89 | ||
96 | static void s_child(int sig_no) | 90 | static 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> | ||
132 | static void gettimeofday_ns(struct timespec *ts) | ||
133 | { | ||
134 | syscall(__NR_clock_gettime, CLOCK_REALTIME, ts); | ||
135 | } | ||
136 | |||
135 | static void update_status(struct svdir *s) | 137 | static 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 | ||
38 | struct service { | ||
39 | dev_t dev; | ||
40 | ino_t ino; | ||
41 | pid_t pid; | ||
42 | smallint isgone; | ||
43 | }; | ||
44 | |||
45 | struct service *sv; | ||
38 | static char *svdir; | 46 | static char *svdir; |
39 | static unsigned long dev; | ||
40 | static unsigned long ino; | ||
41 | static struct service { | ||
42 | unsigned long dev; | ||
43 | unsigned long ino; | ||
44 | int pid; | ||
45 | int isgone; | ||
46 | } *sv; | ||
47 | static int svnum; | 47 | static int svnum; |
48 | static int check = 1; | ||
49 | static char *rplog; | 48 | static char *rplog; |
50 | static int rploglen; | 49 | static int rploglen; |
51 | static int logpipe[2]; | 50 | static int logpipe[2]; |
52 | static iopause_fd io[1]; | 51 | static struct pollfd pfd[1]; |
53 | static struct taia stamplog; | 52 | static unsigned stamplog; |
54 | static int exitsoon; | 53 | static smallint check = 1; |
55 | static int pgrp; | 54 | static smallint exitsoon; |
55 | static smallint set_pgrp; | ||
56 | 56 | ||
57 | #define usage() bb_show_usage() | ||
58 | static void fatal2_cannot(const char *m1, const char *m2) | 57 | static 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 | ||
85 | static void runsv(int no, const char *name) | 84 | static 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); | |||
206 | int runsvdir_main(int argc, char **argv) | 208 | int 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 | |||
161 | static const char *acts; | 161 | static const char *acts; |
162 | static char **service; | 162 | static char **service; |
163 | static unsigned rc; | 163 | static unsigned rc; |
164 | static struct taia tstart, tnow; | 164 | /* "Bernstein" time format: unix + 0x400000000000000aULL */ |
165 | static char svstatus[20]; | 165 | static uint64_t tstart, tnow; |
166 | svstatus_t svstatus; | ||
166 | 167 | ||
167 | #define usage() bb_show_usage() | ||
168 | 168 | ||
169 | static void fatal_cannot(const char *m1) ATTRIBUTE_NORETURN; | 169 | static void fatal_cannot(const char *m1) ATTRIBUTE_NORETURN; |
170 | static void fatal_cannot(const char *m1) | 170 | static 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 | } |
198 | static void warn_cannot(const char *m1) | 198 | static 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); |
203 | static void warnx_cannot(const char *m1) | ||
204 | { | ||
205 | errno = 0; | ||
206 | warn_cannot(m1); | ||
207 | } | 203 | } |
208 | static void ok(const char *m1) | 204 | static 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 | ||
244 | static unsigned svstatus_print(const char *m) | 246 | static 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 | |||
36 | static unsigned verbose; | 40 | static unsigned verbose; |
37 | static int linemax = 1000; | 41 | static int linemax = 1000; |
38 | ////static int buflen = 1024; | 42 | ////static int buflen = 1024; |
@@ -41,7 +45,7 @@ static int linelen; | |||
41 | static char **fndir; | 45 | static char **fndir; |
42 | static int fdwdir; | 46 | static int fdwdir; |
43 | static int wstat; | 47 | static int wstat; |
44 | static struct taia trotate; | 48 | static unsigned nearest_rotate; |
45 | 49 | ||
46 | static char *line; | 50 | static char *line; |
47 | static smallint exitasap; | 51 | static smallint exitasap; |
@@ -55,7 +59,6 @@ static char repl; | |||
55 | static const char *replace = ""; | 59 | static const char *replace = ""; |
56 | 60 | ||
57 | static sigset_t *blocked_sigset; | 61 | static sigset_t *blocked_sigset; |
58 | static iopause_fd input; | ||
59 | static int fl_flag_0; | 62 | static int fl_flag_0; |
60 | 63 | ||
61 | static struct logdir { | 64 | static 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 */ | ||
136 | static 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! */ | ||
158 | static 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 | |||
131 | static unsigned processorstart(struct logdir *ld) | 177 | static unsigned processorstart(struct logdir *ld) |
132 | { | 178 | { |
133 | int pid; | 179 | int pid; |
@@ -264,15 +310,15 @@ static void rmoldest(struct logdir *ld) | |||
264 | static unsigned rotate(struct logdir *ld) | 310 | static 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) | |||
425 | static unsigned logdir_open(struct logdir *ld, const char *fn) | 470 | static 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 | ||
590 | static void logdirs_reopen(void) | 636 | static 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 */ |
617 | static int buffer_pread(int fd, char *s, unsigned len, struct taia *now) | 663 | static 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 | ||
710 | static void sig_alarm_handler(int sig_no) | 772 | static 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'; |