blob: 181d43836fffbb98a0c4e6c86b3c725599c4f02d [file] [log] [blame]
Denis Vlasenko83ea6432006-11-16 02:27:24 +00001/*
2Copyright (c) 2001-2006, Gerrit Pape
3All rights reserved.
4
5Redistribution and use in source and binary forms, with or without
6modification, 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
16THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25ADVISED 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
Denis Vlasenkoe2473f82007-01-27 22:22:17 +000037#if 0
Denis Vlasenko83ea6432006-11-16 02:27:24 +000038/*** buffer.c ***/
39
40void buffer_init(buffer *s,int (*op)(int fd,char *buf,unsigned len),int fd,char *buf,unsigned len)
41{
42 s->x = buf;
43 s->fd = fd;
44 s->op = op;
45 s->p = 0;
46 s->n = len;
47}
48
49
50/*** buffer_get.c ***/
51
52static int oneread(int (*op)(int fd,char *buf,unsigned len),int fd,char *buf,unsigned len)
53{
54 int r;
55
56 for (;;) {
57 r = op(fd,buf,len);
Denis Vlasenko8c783952007-01-27 22:21:52 +000058 if (r == -1 && errno == EINTR)
59 continue;
Denis Vlasenko83ea6432006-11-16 02:27:24 +000060 return r;
61 }
62}
63
64static int getthis(buffer *s,char *buf,unsigned len)
65{
66 if (len > s->p) len = s->p;
67 s->p -= len;
68 memcpy(buf,s->x + s->n,len);
69 s->n += len;
70 return len;
71}
72
73int buffer_feed(buffer *s)
74{
75 int r;
76
Denis Vlasenko8c783952007-01-27 22:21:52 +000077 if (s->p)
78 return s->p;
Denis Vlasenko83ea6432006-11-16 02:27:24 +000079 r = oneread(s->op,s->fd,s->x,s->n);
Denis Vlasenko8c783952007-01-27 22:21:52 +000080 if (r <= 0)
81 return r;
Denis Vlasenko83ea6432006-11-16 02:27:24 +000082 s->p = r;
83 s->n -= r;
Denis Vlasenko8c783952007-01-27 22:21:52 +000084 if (s->n > 0)
85 memmove(s->x + s->n,s->x,r);
Denis Vlasenko83ea6432006-11-16 02:27:24 +000086 return r;
87}
88
89int buffer_bget(buffer *s,char *buf,unsigned len)
90{
91 int r;
Denis Vlasenkof7996f32007-01-11 17:20:00 +000092
Denis Vlasenko8c783952007-01-27 22:21:52 +000093 if (s->p > 0)
94 return getthis(s,buf,len);
95 if (s->n <= len)
96 return oneread(s->op,s->fd,buf,s->n);
97 r = buffer_feed(s);
98 if (r <= 0)
99 return r;
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000100 return getthis(s,buf,len);
101}
102
103int buffer_get(buffer *s,char *buf,unsigned len)
104{
105 int r;
Denis Vlasenkof7996f32007-01-11 17:20:00 +0000106
Denis Vlasenko8c783952007-01-27 22:21:52 +0000107 if (s->p > 0)
108 return getthis(s,buf,len);
109 if (s->n <= len)
110 return oneread(s->op,s->fd,buf,len);
111 r = buffer_feed(s);
112 if (r <= 0)
113 return r;
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000114 return getthis(s,buf,len);
115}
116
117char *buffer_peek(buffer *s)
118{
119 return s->x + s->n;
120}
121
122void buffer_seek(buffer *s,unsigned len)
123{
124 s->n += len;
125 s->p -= len;
126}
127
128
129/*** buffer_put.c ***/
130
131static int allwrite(int (*op)(int fd,char *buf,unsigned len),int fd,const char *buf,unsigned len)
132{
133 int w;
134
135 while (len) {
136 w = op(fd,(char*)buf,len);
137 if (w == -1) {
Denis Vlasenko8c783952007-01-27 22:21:52 +0000138 if (errno == EINTR)
139 continue;
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000140 return -1; /* note that some data may have been written */
141 }
Denis Vlasenko8c783952007-01-27 22:21:52 +0000142 /* if (w == 0) ; luser's fault */
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000143 buf += w;
144 len -= w;
145 }
146 return 0;
147}
148
149int buffer_flush(buffer *s)
150{
151 int p;
Denis Vlasenkof7996f32007-01-11 17:20:00 +0000152
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000153 p = s->p;
154 if (!p) return 0;
155 s->p = 0;
156 return allwrite(s->op,s->fd,s->x,p);
157}
158
159int buffer_putalign(buffer *s,const char *buf,unsigned len)
160{
161 unsigned n;
Denis Vlasenkof7996f32007-01-11 17:20:00 +0000162
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000163 while (len > (n = s->n - s->p)) {
164 memcpy(s->x + s->p,buf,n);
165 s->p += n;
166 buf += n;
167 len -= n;
168 if (buffer_flush(s) == -1) return -1;
169 }
170 /* now len <= s->n - s->p */
171 memcpy(s->x + s->p,buf,len);
172 s->p += len;
173 return 0;
174}
175
176int buffer_put(buffer *s,const char *buf,unsigned len)
177{
178 unsigned n;
Denis Vlasenkof7996f32007-01-11 17:20:00 +0000179
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000180 n = s->n;
181 if (len > n - s->p) {
182 if (buffer_flush(s) == -1) return -1;
183 /* now s->p == 0 */
184 if (n < BUFFER_OUTSIZE) n = BUFFER_OUTSIZE;
185 while (len > s->n) {
186 if (n > len) n = len;
187 if (allwrite(s->op,s->fd,buf,n) == -1) return -1;
188 buf += n;
189 len -= n;
190 }
191 }
192 /* now len <= s->n - s->p */
193 memcpy(s->x + s->p,buf,len);
194 s->p += len;
195 return 0;
196}
197
198int buffer_putflush(buffer *s,const char *buf,unsigned len)
199{
Denis Vlasenko8c783952007-01-27 22:21:52 +0000200 if (buffer_flush(s) == -1)
201 return -1;
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000202 return allwrite(s->op,s->fd,buf,len);
203}
204
205int buffer_putsalign(buffer *s,const char *buf)
206{
207 return buffer_putalign(s,buf,strlen(buf));
208}
209
210int buffer_puts(buffer *s,const char *buf)
211{
212 return buffer_put(s,buf,strlen(buf));
213}
214
215int buffer_putsflush(buffer *s,const char *buf)
216{
217 return buffer_putflush(s,buf,strlen(buf));
218}
219
220
221/*** buffer_read.c ***/
222
223int buffer_unixread(int fd,char *buf,unsigned len)
224{
225 return read(fd,buf,len);
226}
227
228
229/*** buffer_write.c ***/
230
231int buffer_unixwrite(int fd,char *buf,unsigned len)
232{
233 return write(fd,buf,len);
234}
Denis Vlasenkoe2473f82007-01-27 22:22:17 +0000235#endif
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000236
237
238/*** byte_chr.c ***/
239
240unsigned byte_chr(char *s,unsigned n,int c)
241{
242 char ch;
243 char *t;
244
245 ch = c;
246 t = s;
247 for (;;) {
Denis Vlasenko8c783952007-01-27 22:21:52 +0000248 if (!n) break;
249 if (*t == ch) break;
250 ++t;
251 --n;
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000252 }
253 return t - s;
254}
255
256
257/*** coe.c ***/
258
259int coe(int fd)
260{
261 return fcntl(fd,F_SETFD,FD_CLOEXEC);
262}
263
264
265/*** fd_copy.c ***/
266
267int fd_copy(int to,int from)
268{
Denis Vlasenko8c783952007-01-27 22:21:52 +0000269 if (to == from)
270 return 0;
271 if (fcntl(from,F_GETFL,0) == -1)
272 return -1;
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000273 close(to);
Denis Vlasenko8c783952007-01-27 22:21:52 +0000274 if (fcntl(from,F_DUPFD,to) == -1)
275 return -1;
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000276 return 0;
277}
278
279
280/*** fd_move.c ***/
281
282int fd_move(int to,int from)
283{
Denis Vlasenko8c783952007-01-27 22:21:52 +0000284 if (to == from)
285 return 0;
286 if (fd_copy(to,from) == -1)
287 return -1;
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000288 close(from);
289 return 0;
290}
291
292
Denis Vlasenkoe2473f82007-01-27 22:22:17 +0000293#if 0
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000294/*** fifo.c ***/
295
Denis Vlasenko8c783952007-01-27 22:21:52 +0000296int fifo_make(const char *fn,int mode)
297{
Denis Vlasenkoe2473f82007-01-27 22:22:17 +0000298 return mkfifo(fn, mode);
Denis Vlasenko8c783952007-01-27 22:21:52 +0000299}
Denis Vlasenkoe2473f82007-01-27 22:22:17 +0000300#endif
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000301
302
303/*** fmt_ptime.c ***/
304
Denis Vlasenko8c783952007-01-27 22:21:52 +0000305void fmt_ptime30nul(char *s, struct taia *ta) {
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000306 struct tm *t;
307 unsigned long u;
308
Denis Vlasenko8c783952007-01-27 22:21:52 +0000309 if (ta->sec.x < 4611686018427387914ULL)
310 return; /* impossible? */
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000311 u = ta->sec.x -4611686018427387914ULL;
Denis Vlasenko8c783952007-01-27 22:21:52 +0000312 t = gmtime((time_t*)&u);
313 if (!t)
314 return; /* huh? */
315 //fmt_ulong(s, 1900 + t->tm_year);
316 //s[4] = '-'; fmt_uint0(&s[5], t->tm_mon+1, 2);
317 //s[7] = '-'; fmt_uint0(&s[8], t->tm_mday, 2);
318 //s[10] = '_'; fmt_uint0(&s[11], t->tm_hour, 2);
319 //s[13] = ':'; fmt_uint0(&s[14], t->tm_min, 2);
320 //s[16] = ':'; fmt_uint0(&s[17], t->tm_sec, 2);
321 //s[19] = '.'; fmt_uint0(&s[20], ta->nano, 9);
322 sprintf(s, "%04u-%02u-%02u_%02u:%02u:%02u.%09u",
323 (unsigned)(1900 + t->tm_year),
324 (unsigned)(t->tm_mon+1),
325 (unsigned)(t->tm_mday),
326 (unsigned)(t->tm_hour),
327 (unsigned)(t->tm_min),
328 (unsigned)(t->tm_sec),
329 (unsigned)(ta->nano)
330 );
331 /* 4+1 + 2+1 + 2+1 + 2+1 + 2+1 + 2+1 + 9 = */
332 /* 5 + 3 + 3 + 3 + 3 + 3 + 9 = */
333 /* 20 (up to '.' inclusive) + 9 (not including '\0') */
334 return;
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000335}
336
Denis Vlasenko8c783952007-01-27 22:21:52 +0000337unsigned fmt_taia25(char *s, struct taia *t) {
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000338 static char pack[TAIA_PACK];
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000339
340 taia_pack(pack, t);
Denis Vlasenko3a34d0c2007-01-12 22:10:34 +0000341 *s++ = '@';
342 bin2hex(s, pack, 12);
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000343 return 25;
344}
345
346
Denis Vlasenko8c783952007-01-27 22:21:52 +0000347#ifdef UNUSED
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000348/*** fmt_uint.c ***/
349
350unsigned fmt_uint(char *s,unsigned u)
351{
352 return fmt_ulong(s,u);
353}
354
355
356/*** fmt_uint0.c ***/
357
358unsigned fmt_uint0(char *s,unsigned u,unsigned n)
359{
360 unsigned len;
Denis Vlasenko8c783952007-01-27 22:21:52 +0000361 len = fmt_uint(FMT_LEN, u);
362 while (len < n) {
363 if (s)
364 *s++ = '0';
365 ++len;
366 }
367 if (s)
368 fmt_uint(s, u);
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000369 return len;
370}
Denis Vlasenko8c783952007-01-27 22:21:52 +0000371#endif
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000372
373
Denis Vlasenko8c783952007-01-27 22:21:52 +0000374#ifdef UNUSED
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000375/*** fmt_ulong.c ***/
376
377unsigned fmt_ulong(char *s,unsigned long u)
378{
379 unsigned len; unsigned long q;
380 len = 1; q = u;
381 while (q > 9) { ++len; q /= 10; }
382 if (s) {
383 s += len;
Denis Vlasenkobf0a2012006-12-26 10:42:51 +0000384 do { *--s = '0' + (u % 10); u /= 10; } while (u); /* handles u == 0 */
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000385 }
386 return len;
387}
Denis Vlasenko8c783952007-01-27 22:21:52 +0000388#endif
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000389
390
Denis Vlasenko8c783952007-01-27 22:21:52 +0000391#ifdef UNUSED
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000392/*** tai_now.c ***/
393
394void tai_now(struct tai *t)
395{
Denis Vlasenko8c783952007-01-27 22:21:52 +0000396 tai_unix(t, time(NULL));
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000397}
Denis Vlasenko8c783952007-01-27 22:21:52 +0000398#endif
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000399
400
401/*** tai_pack.c ***/
402
Denis Vlasenko8c783952007-01-27 22:21:52 +0000403static /* as it isn't used anywhere else */
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000404void tai_pack(char *s,const struct tai *t)
405{
406 uint64_t x;
407
408 x = t->x;
409 s[7] = x & 255; x >>= 8;
410 s[6] = x & 255; x >>= 8;
411 s[5] = x & 255; x >>= 8;
412 s[4] = x & 255; x >>= 8;
413 s[3] = x & 255; x >>= 8;
414 s[2] = x & 255; x >>= 8;
415 s[1] = x & 255; x >>= 8;
416 s[0] = x;
417}
418
419
Denis Vlasenko8c783952007-01-27 22:21:52 +0000420#ifdef UNUSED
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000421/*** tai_sub.c ***/
422
Denis Vlasenko8c783952007-01-27 22:21:52 +0000423void tai_sub(struct tai *t, const struct tai *u, const struct tai *v)
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000424{
425 t->x = u->x - v->x;
426}
Denis Vlasenko8c783952007-01-27 22:21:52 +0000427#endif
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000428
429
430/*** tai_unpack.c ***/
431
432void tai_unpack(const char *s,struct tai *t)
433{
434 uint64_t x;
435
436 x = (unsigned char) s[0];
437 x <<= 8; x += (unsigned char) s[1];
438 x <<= 8; x += (unsigned char) s[2];
439 x <<= 8; x += (unsigned char) s[3];
440 x <<= 8; x += (unsigned char) s[4];
441 x <<= 8; x += (unsigned char) s[5];
442 x <<= 8; x += (unsigned char) s[6];
443 x <<= 8; x += (unsigned char) s[7];
444 t->x = x;
445}
446
447
448/*** taia_add.c ***/
449
450/* XXX: breaks tai encapsulation */
451
452void taia_add(struct taia *t,const struct taia *u,const struct taia *v)
453{
454 t->sec.x = u->sec.x + v->sec.x;
455 t->nano = u->nano + v->nano;
456 t->atto = u->atto + v->atto;
457 if (t->atto > 999999999UL) {
458 t->atto -= 1000000000UL;
459 ++t->nano;
460 }
461 if (t->nano > 999999999UL) {
462 t->nano -= 1000000000UL;
463 ++t->sec.x;
464 }
465}
466
467
Denis Vlasenko8c783952007-01-27 22:21:52 +0000468#ifdef UNUSED
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000469/*** taia_frac.c ***/
470
471double taia_frac(const struct taia *t)
472{
473 return (t->atto * 0.000000001 + t->nano) * 0.000000001;
474}
475
476
Denis Vlasenko8c783952007-01-27 22:21:52 +0000477/*** taia_approx.c ***/
478
479double taia_approx(const struct taia *t)
480{
481 return t->sec->x + taia_frac(t);
482}
483#endif
484
485static
486uint64_t taia2millisec(const struct taia *t)
487{
488 return (t->sec.x * 1000) + (t->nano / 1000000);
489}
490
491
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000492/*** taia_less.c ***/
493
494/* XXX: breaks tai encapsulation */
495
Denis Vlasenkoe2473f82007-01-27 22:22:17 +0000496int taia_less(const struct taia *t, const struct taia *u)
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000497{
498 if (t->sec.x < u->sec.x) return 1;
499 if (t->sec.x > u->sec.x) return 0;
500 if (t->nano < u->nano) return 1;
501 if (t->nano > u->nano) return 0;
502 return t->atto < u->atto;
503}
504
505
506/*** taia_now.c ***/
507
508void taia_now(struct taia *t)
509{
510 struct timeval now;
Denis Vlasenko8c783952007-01-27 22:21:52 +0000511 gettimeofday(&now, NULL);
512 tai_unix(&t->sec, now.tv_sec);
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000513 t->nano = 1000 * now.tv_usec + 500;
514 t->atto = 0;
515}
516
517
518/*** taia_pack.c ***/
519
Denis Vlasenko8c783952007-01-27 22:21:52 +0000520void taia_pack(char *s, const struct taia *t)
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000521{
522 unsigned long x;
523
Denis Vlasenko8c783952007-01-27 22:21:52 +0000524 tai_pack(s, &t->sec);
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000525 s += 8;
526
527 x = t->atto;
528 s[7] = x & 255; x >>= 8;
529 s[6] = x & 255; x >>= 8;
530 s[5] = x & 255; x >>= 8;
531 s[4] = x;
532 x = t->nano;
533 s[3] = x & 255; x >>= 8;
534 s[2] = x & 255; x >>= 8;
535 s[1] = x & 255; x >>= 8;
536 s[0] = x;
537}
538
539
540/*** taia_sub.c ***/
541
542/* XXX: breaks tai encapsulation */
543
Denis Vlasenkoe2473f82007-01-27 22:22:17 +0000544void taia_sub(struct taia *t, const struct taia *u, const struct taia *v)
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000545{
546 unsigned long unano = u->nano;
547 unsigned long uatto = u->atto;
Denis Vlasenkof7996f32007-01-11 17:20:00 +0000548
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000549 t->sec.x = u->sec.x - v->sec.x;
550 t->nano = unano - v->nano;
551 t->atto = uatto - v->atto;
552 if (t->atto > uatto) {
553 t->atto += 1000000000UL;
554 --t->nano;
555 }
556 if (t->nano > unano) {
557 t->nano += 1000000000UL;
558 --t->sec.x;
559 }
560}
561
562
563/*** taia_uint.c ***/
564
565/* XXX: breaks tai encapsulation */
566
Denis Vlasenkoe2473f82007-01-27 22:22:17 +0000567void taia_uint(struct taia *t, unsigned s)
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000568{
569 t->sec.x = s;
570 t->nano = 0;
571 t->atto = 0;
572}
573
574
575/*** stralloc_cat.c ***/
Denis Vlasenko8a00f442006-11-17 18:58:16 +0000576#if 0
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000577
578int stralloc_cat(stralloc *sato,const stralloc *safrom)
579{
580 return stralloc_catb(sato,safrom->s,safrom->len);
581}
582
583
584/*** stralloc_catb.c ***/
585
586int stralloc_catb(stralloc *sa,const char *s,unsigned n)
587{
588 if (!sa->s) return stralloc_copyb(sa,s,n);
589 if (!stralloc_readyplus(sa,n + 1)) return 0;
590 memcpy(sa->s + sa->len,s,n);
591 sa->len += n;
592 sa->s[sa->len] = 'Z'; /* ``offensive programming'' */
593 return 1;
594}
595
596
597/*** stralloc_cats.c ***/
598
599int stralloc_cats(stralloc *sa,const char *s)
600{
601 return stralloc_catb(sa,s,strlen(s));
602}
603
604
605/*** stralloc_eady.c ***/
606
607GEN_ALLOC_ready(stralloc,char,s,len,a,i,n,x,30,stralloc_ready)
608GEN_ALLOC_readyplus(stralloc,char,s,len,a,i,n,x,30,stralloc_readyplus)
609
610
611/*** stralloc_opyb.c ***/
612
613int stralloc_copyb(stralloc *sa,const char *s,unsigned n)
614{
615 if (!stralloc_ready(sa,n + 1)) return 0;
616 memcpy(sa->s,s,n);
617 sa->len = n;
618 sa->s[n] = 'Z'; /* ``offensive programming'' */
619 return 1;
620}
621
622
623/*** stralloc_opys.c ***/
624
625int stralloc_copys(stralloc *sa,const char *s)
626{
627 return stralloc_copyb(sa,s,strlen(s));
628}
629
630
631/*** stralloc_pend.c ***/
632
633GEN_ALLOC_append(stralloc,char,s,len,a,i,n,x,30,stralloc_readyplus,stralloc_append)
634
Denis Vlasenko8a00f442006-11-17 18:58:16 +0000635#endif /* stralloc */
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000636
637/*** iopause.c ***/
638
639void iopause(iopause_fd *x,unsigned len,struct taia *deadline,struct taia *stamp)
640{
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000641 int millisecs;
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000642 int i;
643
644 if (taia_less(deadline,stamp))
645 millisecs = 0;
646 else {
Denis Vlasenko8c783952007-01-27 22:21:52 +0000647 uint64_t m;
648 struct taia t;
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000649 t = *stamp;
Denis Vlasenko8c783952007-01-27 22:21:52 +0000650 taia_sub(&t, deadline, &t);
651 millisecs = m = taia2millisec(&t);
652 if (m > 1000) millisecs = 1000;
653 millisecs += 20;
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000654 }
655
Denis Vlasenko8c783952007-01-27 22:21:52 +0000656 for (i = 0; i < len; ++i)
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000657 x[i].revents = 0;
658
Denis Vlasenko8c783952007-01-27 22:21:52 +0000659 poll(x, len, millisecs);
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000660 /* XXX: some kernels apparently need x[0] even if len is 0 */
661 /* XXX: how to handle EAGAIN? are kernels really this dumb? */
662 /* XXX: how to handle EINVAL? when exactly can this happen? */
663}
664
665
666/*** lock_ex.c ***/
667
668int lock_ex(int fd)
669{
670 return flock(fd,LOCK_EX);
671}
672
673
674/*** lock_exnb.c ***/
675
676int lock_exnb(int fd)
677{
678 return flock(fd,LOCK_EX | LOCK_NB);
679}
680
681
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000682/*** open_append.c ***/
683
684int open_append(const char *fn)
685{
Denis Vlasenko8a00f442006-11-17 18:58:16 +0000686 return open(fn, O_WRONLY|O_NDELAY|O_APPEND|O_CREAT, 0600);
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000687}
688
689
690/*** open_read.c ***/
691
692int open_read(const char *fn)
693{
Denis Vlasenko8a00f442006-11-17 18:58:16 +0000694 return open(fn, O_RDONLY|O_NDELAY);
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000695}
696
697
698/*** open_trunc.c ***/
699
700int open_trunc(const char *fn)
701{
702 return open(fn,O_WRONLY | O_NDELAY | O_TRUNC | O_CREAT,0644);
703}
704
705
706/*** open_write.c ***/
707
708int open_write(const char *fn)
709{
Denis Vlasenko8a00f442006-11-17 18:58:16 +0000710 return open(fn, O_WRONLY|O_NDELAY);
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000711}
712
713
714/*** openreadclose.c ***/
Denis Vlasenko8a00f442006-11-17 18:58:16 +0000715#if 0
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000716int openreadclose(const char *fn,stralloc *sa,unsigned bufsize)
717{
718 int fd;
719 fd = open_read(fn);
720 if (fd == -1) {
721 if (errno == ENOENT) return 0;
722 return -1;
723 }
724 if (readclose(fd,sa,bufsize) == -1) return -1;
725 return 1;
726}
Denis Vlasenko8a00f442006-11-17 18:58:16 +0000727#endif
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000728
729
730/*** pathexec_env.c ***/
Denis Vlasenko8a00f442006-11-17 18:58:16 +0000731#if 0
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000732static stralloc plus;
733static stralloc tmp;
734
735int pathexec_env(const char *s,const char *t)
736{
737 if (!s) return 1;
738 if (!stralloc_copys(&tmp,s)) return 0;
739 if (t) {
740 if (!stralloc_cats(&tmp,"=")) return 0;
741 if (!stralloc_cats(&tmp,t)) return 0;
742 }
743 if (!stralloc_0(&tmp)) return 0;
744 return stralloc_cat(&plus,&tmp);
745}
746
747void pathexec(char **argv)
748{
749 char **e;
750 unsigned elen;
751 unsigned i;
752 unsigned j;
753 unsigned split;
754 unsigned t;
755
756 if (!stralloc_cats(&plus,"")) return;
757
758 elen = 0;
759 for (i = 0;environ[i];++i)
760 ++elen;
761 for (i = 0;i < plus.len;++i)
762 if (!plus.s[i])
763 ++elen;
764
765 e = malloc((elen + 1) * sizeof(char *));
766 if (!e) return;
767
768 elen = 0;
769 for (i = 0;environ[i];++i)
770 e[elen++] = environ[i];
771
772 j = 0;
773 for (i = 0;i < plus.len;++i)
774 if (!plus.s[i]) {
775 split = str_chr(plus.s + j,'=');
776 for (t = 0;t < elen;++t)
777 if (memcmp(plus.s + j,e[t],split) == 0)
778 if (e[t][split] == '=') {
779 --elen;
780 e[t] = e[elen];
781 break;
782 }
783 if (plus.s[j + split])
784 e[elen++] = plus.s + j;
785 j = i + 1;
786 }
787 e[elen] = 0;
788
789 pathexec_run(*argv,argv,e);
790 free(e);
791}
Denis Vlasenko8a00f442006-11-17 18:58:16 +0000792#endif
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000793
794/*** pathexec_run.c ***/
Denis Vlasenko8a00f442006-11-17 18:58:16 +0000795#if 0
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000796static stralloc tmp;
797
798void pathexec_run(const char *file,char *const *argv,char *const *envp)
799{
800 const char *path;
801 unsigned split;
802 int savederrno;
803
804 if (file[str_chr(file,'/')]) {
805 execve(file,argv,envp);
806 return;
807 }
808
809 path = getenv("PATH");
810 if (!path) path = "/bin:/usr/bin";
811
812 savederrno = 0;
813 for (;;) {
814 split = str_chr(path,':');
815 if (!stralloc_copyb(&tmp,path,split)) return;
816 if (!split)
817 if (!stralloc_cats(&tmp,".")) return;
818 if (!stralloc_cats(&tmp,"/")) return;
819 if (!stralloc_cats(&tmp,file)) return;
820 if (!stralloc_0(&tmp)) return;
821
822 execve(tmp.s,argv,envp);
823 if (errno != ENOENT) {
824 savederrno = errno;
825 if ((errno != EACCES) && (errno != EPERM) && (errno != EISDIR)) return;
826 }
827
828 if (!path[split]) {
829 if (savederrno) errno = savederrno;
830 return;
831 }
832 path += split;
833 path += 1;
834 }
835}
Denis Vlasenko8a00f442006-11-17 18:58:16 +0000836#endif
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000837
838/*** pmatch.c ***/
839
840unsigned pmatch(const char *p, const char *s, unsigned len) {
841 for (;;) {
842 char c = *p++;
843 if (!c) return !len;
844 switch (c) {
845 case '*':
846 if (!(c = *p)) return 1;
847 for (;;) {
848 if (!len) return 0;
849 if (*s == c) break;
850 ++s; --len;
851 }
852 continue;
853 case '+':
854 if ((c = *p++) != *s) return 0;
855 for (;;) {
856 if (!len) return 1;
857 if (*s != c) break;
858 ++s; --len;
859 }
860 continue;
861 /*
862 case '?':
863 if (*p == '?') {
864 if (*s != '?') return 0;
865 ++p;
866 }
867 ++s; --len;
868 continue;
869 */
870 default:
871 if (!len) return 0;
872 if (*s != c) return 0;
873 ++s; --len;
874 continue;
875 }
876 }
877 return 0;
878}
879
880
Denis Vlasenkoe2473f82007-01-27 22:22:17 +0000881#if 0
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000882/*** prot.c ***/
883
884int prot_gid(int gid)
885{
886 gid_t x = gid;
887 if (setgroups(1,&x) == -1) return -1;
888 return setgid(gid); /* _should_ be redundant, but on some systems it isn't */
889}
890
891int prot_uid(int uid)
892{
893 return setuid(uid);
894}
Denis Vlasenkoe2473f82007-01-27 22:22:17 +0000895#endif
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000896
897
898/*** readclose.c ***/
Denis Vlasenko8a00f442006-11-17 18:58:16 +0000899#if 0
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000900int readclose_append(int fd,stralloc *sa,unsigned bufsize)
901{
902 int r;
903 for (;;) {
904 if (!stralloc_readyplus(sa,bufsize)) { close(fd); return -1; }
905 r = read(fd,sa->s + sa->len,bufsize);
906 if (r == -1) if (errno == EINTR) continue;
907 if (r <= 0) { close(fd); return r; }
908 sa->len += r;
909 }
910}
911
912int readclose(int fd,stralloc *sa,unsigned bufsize)
913{
914 if (!stralloc_copys(sa,"")) { close(fd); return -1; }
915 return readclose_append(fd,sa,bufsize);
916}
Denis Vlasenko8a00f442006-11-17 18:58:16 +0000917#endif
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000918
Denis Vlasenkoe2473f82007-01-27 22:22:17 +0000919#if 0
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000920/*** scan_ulong.c ***/
921
922unsigned scan_ulong(const char *s,unsigned long *u)
923{
924 unsigned pos = 0;
925 unsigned long result = 0;
926 unsigned long c;
927 while ((c = (unsigned long) (unsigned char) (s[pos] - '0')) < 10) {
928 result = result * 10 + c;
929 ++pos;
930 }
931 *u = result;
932 return pos;
933}
Denis Vlasenkoe2473f82007-01-27 22:22:17 +0000934#endif
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000935
936
Denis Vlasenko8c783952007-01-27 22:21:52 +0000937#ifdef UNUSED
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000938/*** seek_set.c ***/
939
940int seek_set(int fd,seek_pos pos)
941{
942 if (lseek(fd,(off_t) pos,SEEK_SET) == -1) return -1; return 0;
943}
Denis Vlasenko8c783952007-01-27 22:21:52 +0000944#endif
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000945
946
947/*** sig.c ***/
948
Denis Vlasenko8c783952007-01-27 22:21:52 +0000949//int sig_alarm = SIGALRM;
950//int sig_child = SIGCHLD;
951//int sig_cont = SIGCONT;
952//int sig_hangup = SIGHUP;
953//int sig_int = SIGINT;
954//int sig_pipe = SIGPIPE;
955//int sig_term = SIGTERM;
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000956
Denis Vlasenko8c783952007-01-27 22:21:52 +0000957//void (*sig_defaulthandler)(int) = SIG_DFL;
958//void (*sig_ignorehandler)(int) = SIG_IGN;
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000959
960
961/*** sig_block.c ***/
962
963void sig_block(int sig)
964{
965 sigset_t ss;
966 sigemptyset(&ss);
Denis Vlasenkoe2473f82007-01-27 22:22:17 +0000967 sigaddset(&ss, sig);
968 sigprocmask(SIG_BLOCK, &ss, NULL);
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000969}
970
971void sig_unblock(int sig)
972{
973 sigset_t ss;
974 sigemptyset(&ss);
Denis Vlasenkoe2473f82007-01-27 22:22:17 +0000975 sigaddset(&ss, sig);
976 sigprocmask(SIG_UNBLOCK, &ss, NULL);
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000977}
978
979void sig_blocknone(void)
980{
981 sigset_t ss;
982 sigemptyset(&ss);
Denis Vlasenkoe2473f82007-01-27 22:22:17 +0000983 sigprocmask(SIG_SETMASK, &ss, NULL);
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000984}
985
986
987/*** sig_catch.c ***/
988
989void sig_catch(int sig,void (*f)(int))
990{
991 struct sigaction sa;
992 sa.sa_handler = f;
993 sa.sa_flags = 0;
994 sigemptyset(&sa.sa_mask);
Denis Vlasenkoe2473f82007-01-27 22:22:17 +0000995 sigaction(sig,&sa, NULL);
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000996}
997
998
999/*** sig_pause.c ***/
1000
1001void sig_pause(void)
1002{
1003 sigset_t ss;
1004 sigemptyset(&ss);
1005 sigsuspend(&ss);
1006}
1007
1008
1009/*** str_chr.c ***/
1010
1011unsigned str_chr(const char *s,int c)
1012{
1013 char ch;
1014 const char *t;
1015
1016 ch = c;
1017 t = s;
1018 for (;;) {
Denis Vlasenko8c783952007-01-27 22:21:52 +00001019 if (!*t) break;
1020 if (*t == ch) break;
1021 ++t;
Denis Vlasenko83ea6432006-11-16 02:27:24 +00001022 }
1023 return t - s;
1024}
1025
1026
1027/*** wait_nohang.c ***/
1028
1029int wait_nohang(int *wstat)
1030{
Denis Vlasenko8c783952007-01-27 22:21:52 +00001031 return waitpid(-1, wstat, WNOHANG);
Denis Vlasenko83ea6432006-11-16 02:27:24 +00001032}
1033
1034
1035/*** wait_pid.c ***/
1036
1037int wait_pid(int *wstat, int pid)
1038{
1039 int r;
1040
1041 do
Denis Vlasenko8c783952007-01-27 22:21:52 +00001042 r = waitpid(pid, wstat, 0);
Denis Vlasenko83ea6432006-11-16 02:27:24 +00001043 while ((r == -1) && (errno == EINTR));
1044 return r;
1045}