- improve wording
[oweals/busybox.git] / runit / runit_lib.c
1 /*
2 Copyright (c) 2001-2006, Gerrit Pape
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
7
8    1. Redistributions of source code must retain the above copyright notice,
9       this list of conditions and the following disclaimer.
10    2. Redistributions in binary form must reproduce the above copyright
11       notice, this list of conditions and the following disclaimer in the
12       documentation and/or other materials provided with the distribution.
13    3. The name of the author may not be used to endorse or promote products
14       derived from this software without specific prior written permission.
15
16 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28 /* Busyboxed by Denis Vlasenko <vda.linux@googlemail.com> */
29 /* Collected into one file from runit's many tiny files */
30 /* TODO: review, eliminate unneeded stuff, move good stuff to libbb */
31
32 #include <sys/poll.h>
33 #include <sys/file.h>
34 #include "libbb.h"
35 #include "runit_lib.h"
36
37 /*** byte_chr.c ***/
38
39 unsigned byte_chr(char *s,unsigned n,int c)
40 {
41         char ch;
42         char *t;
43
44         ch = c;
45         t = s;
46         for (;;) {
47                 if (!n) break;
48                 if (*t == ch) break;
49                 ++t;
50                 --n;
51         }
52         return t - s;
53 }
54
55
56 /*** coe.c ***/
57
58 int coe(int fd)
59 {
60         return fcntl(fd,F_SETFD,FD_CLOEXEC);
61 }
62
63
64 /*** fd_copy.c ***/
65
66 int fd_copy(int to,int from)
67 {
68         if (to == from)
69                 return 0;
70         if (fcntl(from,F_GETFL,0) == -1)
71                 return -1;
72         close(to);
73         if (fcntl(from,F_DUPFD,to) == -1)
74                 return -1;
75         return 0;
76 }
77
78
79 /*** fd_move.c ***/
80
81 int fd_move(int to,int from)
82 {
83         if (to == from)
84                 return 0;
85         if (fd_copy(to,from) == -1)
86                 return -1;
87         close(from);
88         return 0;
89 }
90
91
92 /*** fmt_ptime.c ***/
93
94 void fmt_ptime30nul(char *s, struct taia *ta) {
95         struct tm *t;
96         unsigned long u;
97
98         if (ta->sec.x < 4611686018427387914ULL)
99                 return; /* impossible? */
100         u = ta->sec.x -4611686018427387914ULL;
101         t = gmtime((time_t*)&u);
102         if (!t)
103                 return; /* huh? */
104         //fmt_ulong(s, 1900 + t->tm_year);
105         //s[4] = '-'; fmt_uint0(&s[5], t->tm_mon+1, 2);
106         //s[7] = '-'; fmt_uint0(&s[8], t->tm_mday, 2);
107         //s[10] = '_'; fmt_uint0(&s[11], t->tm_hour, 2);
108         //s[13] = ':'; fmt_uint0(&s[14], t->tm_min, 2);
109         //s[16] = ':'; fmt_uint0(&s[17], t->tm_sec, 2);
110         //s[19] = '.'; fmt_uint0(&s[20], ta->nano, 9);
111         sprintf(s, "%04u-%02u-%02u_%02u:%02u:%02u.%09u",
112                 (unsigned)(1900 + t->tm_year),
113                 (unsigned)(t->tm_mon+1),
114                 (unsigned)(t->tm_mday),
115                 (unsigned)(t->tm_hour),
116                 (unsigned)(t->tm_min),
117                 (unsigned)(t->tm_sec),
118                 (unsigned)(ta->nano)
119         );
120         /* 4+1 + 2+1 + 2+1 + 2+1 + 2+1 + 2+1 + 9 = */
121         /* 5   + 3   + 3   + 3   + 3   + 3   + 9 = */
122         /* 20 (up to '.' inclusive) + 9 (not including '\0') */
123         return;
124 }
125
126 unsigned fmt_taia25(char *s, struct taia *t) {
127         static char pack[TAIA_PACK];
128
129         taia_pack(pack, t);
130         *s++ = '@';
131         bin2hex(s, pack, 12);
132         return 25;
133 }
134
135
136 /*** tai_pack.c ***/
137
138 static /* as it isn't used anywhere else */
139 void tai_pack(char *s,const struct tai *t)
140 {
141         uint64_t x;
142
143         x = t->x;
144         s[7] = x & 255; x >>= 8;
145         s[6] = x & 255; x >>= 8;
146         s[5] = x & 255; x >>= 8;
147         s[4] = x & 255; x >>= 8;
148         s[3] = x & 255; x >>= 8;
149         s[2] = x & 255; x >>= 8;
150         s[1] = x & 255; x >>= 8;
151         s[0] = x;
152 }
153
154
155 #ifdef UNUSED
156 /*** tai_sub.c ***/
157
158 void tai_sub(struct tai *t, const struct tai *u, const struct tai *v)
159 {
160         t->x = u->x - v->x;
161 }
162 #endif
163
164
165 /*** tai_unpack.c ***/
166
167 void tai_unpack(const char *s,struct tai *t)
168 {
169         uint64_t x;
170
171         x = (unsigned char) s[0];
172         x <<= 8; x += (unsigned char) s[1];
173         x <<= 8; x += (unsigned char) s[2];
174         x <<= 8; x += (unsigned char) s[3];
175         x <<= 8; x += (unsigned char) s[4];
176         x <<= 8; x += (unsigned char) s[5];
177         x <<= 8; x += (unsigned char) s[6];
178         x <<= 8; x += (unsigned char) s[7];
179         t->x = x;
180 }
181
182
183 /*** taia_add.c ***/
184
185 void taia_add(struct taia *t,const struct taia *u,const struct taia *v)
186 {
187         t->sec.x = u->sec.x + v->sec.x;
188         t->nano = u->nano + v->nano;
189         t->atto = u->atto + v->atto;
190         if (t->atto > 999999999UL) {
191                 t->atto -= 1000000000UL;
192                 ++t->nano;
193         }
194         if (t->nano > 999999999UL) {
195                 t->nano -= 1000000000UL;
196                 ++t->sec.x;
197         }
198 }
199
200
201 /*** taia_less.c ***/
202
203 int taia_less(const struct taia *t, const struct taia *u)
204 {
205         if (t->sec.x < u->sec.x) return 1;
206         if (t->sec.x > u->sec.x) return 0;
207         if (t->nano < u->nano) return 1;
208         if (t->nano > u->nano) return 0;
209         return t->atto < u->atto;
210 }
211
212
213 /*** taia_now.c ***/
214
215 void taia_now(struct taia *t)
216 {
217         struct timeval now;
218         gettimeofday(&now, NULL);
219         tai_unix(&t->sec, now.tv_sec);
220         t->nano = 1000 * now.tv_usec + 500;
221         t->atto = 0;
222 }
223
224
225 /*** taia_pack.c ***/
226
227 void taia_pack(char *s, const struct taia *t)
228 {
229         unsigned long x;
230
231         tai_pack(s, &t->sec);
232         s += 8;
233
234         x = t->atto;
235         s[7] = x & 255; x >>= 8;
236         s[6] = x & 255; x >>= 8;
237         s[5] = x & 255; x >>= 8;
238         s[4] = x;
239         x = t->nano;
240         s[3] = x & 255; x >>= 8;
241         s[2] = x & 255; x >>= 8;
242         s[1] = x & 255; x >>= 8;
243         s[0] = x;
244 }
245
246
247 /*** taia_sub.c ***/
248
249 void taia_sub(struct taia *t, const struct taia *u, const struct taia *v)
250 {
251         unsigned long unano = u->nano;
252         unsigned long uatto = u->atto;
253
254         t->sec.x = u->sec.x - v->sec.x;
255         t->nano = unano - v->nano;
256         t->atto = uatto - v->atto;
257         if (t->atto > uatto) {
258                 t->atto += 1000000000UL;
259                 --t->nano;
260         }
261         if (t->nano > unano) {
262                 t->nano += 1000000000UL;
263                 --t->sec.x;
264         }
265 }
266
267
268 /*** taia_uint.c ***/
269
270 /* XXX: breaks tai encapsulation */
271
272 void taia_uint(struct taia *t, unsigned s)
273 {
274         t->sec.x = s;
275         t->nano = 0;
276         t->atto = 0;
277 }
278
279
280 /*** iopause.c ***/
281
282 static
283 uint64_t taia2millisec(const struct taia *t)
284 {
285         return (t->sec.x * 1000) + (t->nano / 1000000);
286 }
287
288
289 void iopause(iopause_fd *x, unsigned len, struct taia *deadline, struct taia *stamp)
290 {
291         int millisecs;
292         int i;
293
294         if (taia_less(deadline, stamp))
295                 millisecs = 0;
296         else {
297                 uint64_t m;
298                 struct taia t;
299                 t = *stamp;
300                 taia_sub(&t, deadline, &t);
301                 millisecs = m = taia2millisec(&t);
302                 if (m > 1000) millisecs = 1000;
303                 millisecs += 20;
304         }
305
306         for (i = 0; i < len; ++i)
307                 x[i].revents = 0;
308
309         poll(x, len, millisecs);
310         /* XXX: some kernels apparently need x[0] even if len is 0 */
311         /* XXX: how to handle EAGAIN? are kernels really this dumb? */
312         /* XXX: how to handle EINVAL? when exactly can this happen? */
313 }
314
315
316 /*** lock_ex.c ***/
317
318 int lock_ex(int fd)
319 {
320         return flock(fd,LOCK_EX);
321 }
322
323
324 /*** lock_exnb.c ***/
325
326 int lock_exnb(int fd)
327 {
328         return flock(fd,LOCK_EX | LOCK_NB);
329 }
330
331
332 /*** open_append.c ***/
333
334 int open_append(const char *fn)
335 {
336         return open(fn, O_WRONLY|O_NDELAY|O_APPEND|O_CREAT, 0600);
337 }
338
339
340 /*** open_read.c ***/
341
342 int open_read(const char *fn)
343 {
344         return open(fn, O_RDONLY|O_NDELAY);
345 }
346
347
348 /*** open_trunc.c ***/
349
350 int open_trunc(const char *fn)
351 {
352         return open(fn,O_WRONLY | O_NDELAY | O_TRUNC | O_CREAT,0644);
353 }
354
355
356 /*** open_write.c ***/
357
358 int open_write(const char *fn)
359 {
360         return open(fn, O_WRONLY|O_NDELAY);
361 }
362
363
364 /*** pmatch.c ***/
365
366 unsigned pmatch(const char *p, const char *s, unsigned len) {
367         for (;;) {
368                 char c = *p++;
369                 if (!c) return !len;
370                 switch (c) {
371                 case '*':
372                         if (!(c = *p)) return 1;
373                         for (;;) {
374                                 if (!len) return 0;
375                                 if (*s == c) break;
376                                 ++s; --len;
377                         }
378                         continue;
379                 case '+':
380                         if ((c = *p++) != *s) return 0;
381                         for (;;) {
382                                 if (!len) return 1;
383                                 if (*s != c) break;
384                                 ++s; --len;
385                         }
386                         continue;
387                         /*
388                 case '?':
389                         if (*p == '?') {
390                                 if (*s != '?') return 0;
391                                 ++p;
392                         }
393                         ++s; --len;
394                         continue;
395                         */
396                 default:
397                         if (!len) return 0;
398                         if (*s != c) return 0;
399                         ++s; --len;
400                         continue;
401                 }
402         }
403         return 0;
404 }
405
406
407 #ifdef UNUSED
408 /*** seek_set.c ***/
409
410 int seek_set(int fd,seek_pos pos)
411 {
412         if (lseek(fd,(off_t) pos,SEEK_SET) == -1) return -1; return 0;
413 }
414 #endif
415
416
417 /*** sig_block.c ***/
418
419 void sig_block(int sig)
420 {
421         sigset_t ss;
422         sigemptyset(&ss);
423         sigaddset(&ss, sig);
424         sigprocmask(SIG_BLOCK, &ss, NULL);
425 }
426
427 void sig_unblock(int sig)
428 {
429         sigset_t ss;
430         sigemptyset(&ss);
431         sigaddset(&ss, sig);
432         sigprocmask(SIG_UNBLOCK, &ss, NULL);
433 }
434
435 void sig_blocknone(void)
436 {
437         sigset_t ss;
438         sigemptyset(&ss);
439         sigprocmask(SIG_SETMASK, &ss, NULL);
440 }
441
442
443 /*** sig_catch.c ***/
444
445 void sig_catch(int sig,void (*f)(int))
446 {
447         struct sigaction sa;
448         sa.sa_handler = f;
449         sa.sa_flags = 0;
450         sigemptyset(&sa.sa_mask);
451         sigaction(sig,&sa, NULL);
452 }
453
454
455 /*** sig_pause.c ***/
456
457 void sig_pause(void)
458 {
459         sigset_t ss;
460         sigemptyset(&ss);
461         sigsuspend(&ss);
462 }
463
464
465 /*** str_chr.c ***/
466
467 unsigned str_chr(const char *s,int c)
468 {
469         char ch;
470         const char *t;
471
472         ch = c;
473         t = s;
474         for (;;) {
475                 if (!*t) break;
476                 if (*t == ch) break;
477                 ++t;
478         }
479         return t - s;
480 }
481
482
483 /*** wait_nohang.c ***/
484
485 int wait_nohang(int *wstat)
486 {
487         return waitpid(-1, wstat, WNOHANG);
488 }
489
490
491 /*** wait_pid.c ***/
492
493 int wait_pid(int *wstat, int pid)
494 {
495         int r;
496
497         do
498                 r = waitpid(pid, wstat, 0);
499         while ((r == -1) && (errno == EINTR));
500         return r;
501 }