blob: 322bef858c03a4ca89ca23c18287e6f695ffc57a [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
37#ifndef O_NONBLOCK
38#define O_NONBLOCK O_NDELAY
39#endif
40
41/*** buffer.c ***/
42
43void buffer_init(buffer *s,int (*op)(int fd,char *buf,unsigned len),int fd,char *buf,unsigned len)
44{
45 s->x = buf;
46 s->fd = fd;
47 s->op = op;
48 s->p = 0;
49 s->n = len;
50}
51
52
53/*** buffer_get.c ***/
54
55static int oneread(int (*op)(int fd,char *buf,unsigned len),int fd,char *buf,unsigned len)
56{
57 int r;
58
59 for (;;) {
60 r = op(fd,buf,len);
61 if (r == -1) if (errno == EINTR) continue;
62 return r;
63 }
64}
65
66static int getthis(buffer *s,char *buf,unsigned len)
67{
68 if (len > s->p) len = s->p;
69 s->p -= len;
70 memcpy(buf,s->x + s->n,len);
71 s->n += len;
72 return len;
73}
74
75int buffer_feed(buffer *s)
76{
77 int r;
78
79 if (s->p) return s->p;
80 r = oneread(s->op,s->fd,s->x,s->n);
81 if (r <= 0) return r;
82 s->p = r;
83 s->n -= r;
84 if (s->n > 0) memmove(s->x + s->n,s->x,r);
85 return r;
86}
87
88int buffer_bget(buffer *s,char *buf,unsigned len)
89{
90 int r;
91
92 if (s->p > 0) return getthis(s,buf,len);
93 if (s->n <= len) return oneread(s->op,s->fd,buf,s->n);
94 r = buffer_feed(s); if (r <= 0) return r;
95 return getthis(s,buf,len);
96}
97
98int buffer_get(buffer *s,char *buf,unsigned len)
99{
100 int r;
101
102 if (s->p > 0) return getthis(s,buf,len);
103 if (s->n <= len) return oneread(s->op,s->fd,buf,len);
104 r = buffer_feed(s); if (r <= 0) return r;
105 return getthis(s,buf,len);
106}
107
108char *buffer_peek(buffer *s)
109{
110 return s->x + s->n;
111}
112
113void buffer_seek(buffer *s,unsigned len)
114{
115 s->n += len;
116 s->p -= len;
117}
118
119
120/*** buffer_put.c ***/
121
122static int allwrite(int (*op)(int fd,char *buf,unsigned len),int fd,const char *buf,unsigned len)
123{
124 int w;
125
126 while (len) {
127 w = op(fd,(char*)buf,len);
128 if (w == -1) {
129 if (errno == EINTR) continue;
130 return -1; /* note that some data may have been written */
131 }
132 if (w == 0) ; /* luser's fault */
133 buf += w;
134 len -= w;
135 }
136 return 0;
137}
138
139int buffer_flush(buffer *s)
140{
141 int p;
142
143 p = s->p;
144 if (!p) return 0;
145 s->p = 0;
146 return allwrite(s->op,s->fd,s->x,p);
147}
148
149int buffer_putalign(buffer *s,const char *buf,unsigned len)
150{
151 unsigned n;
152
153 while (len > (n = s->n - s->p)) {
154 memcpy(s->x + s->p,buf,n);
155 s->p += n;
156 buf += n;
157 len -= n;
158 if (buffer_flush(s) == -1) return -1;
159 }
160 /* now len <= s->n - s->p */
161 memcpy(s->x + s->p,buf,len);
162 s->p += len;
163 return 0;
164}
165
166int buffer_put(buffer *s,const char *buf,unsigned len)
167{
168 unsigned n;
169
170 n = s->n;
171 if (len > n - s->p) {
172 if (buffer_flush(s) == -1) return -1;
173 /* now s->p == 0 */
174 if (n < BUFFER_OUTSIZE) n = BUFFER_OUTSIZE;
175 while (len > s->n) {
176 if (n > len) n = len;
177 if (allwrite(s->op,s->fd,buf,n) == -1) return -1;
178 buf += n;
179 len -= n;
180 }
181 }
182 /* now len <= s->n - s->p */
183 memcpy(s->x + s->p,buf,len);
184 s->p += len;
185 return 0;
186}
187
188int buffer_putflush(buffer *s,const char *buf,unsigned len)
189{
190 if (buffer_flush(s) == -1) return -1;
191 return allwrite(s->op,s->fd,buf,len);
192}
193
194int buffer_putsalign(buffer *s,const char *buf)
195{
196 return buffer_putalign(s,buf,strlen(buf));
197}
198
199int buffer_puts(buffer *s,const char *buf)
200{
201 return buffer_put(s,buf,strlen(buf));
202}
203
204int buffer_putsflush(buffer *s,const char *buf)
205{
206 return buffer_putflush(s,buf,strlen(buf));
207}
208
209
210/*** buffer_read.c ***/
211
212int buffer_unixread(int fd,char *buf,unsigned len)
213{
214 return read(fd,buf,len);
215}
216
217
218/*** buffer_write.c ***/
219
220int buffer_unixwrite(int fd,char *buf,unsigned len)
221{
222 return write(fd,buf,len);
223}
224
225
226/*** byte_chr.c ***/
227
228unsigned byte_chr(char *s,unsigned n,int c)
229{
230 char ch;
231 char *t;
232
233 ch = c;
234 t = s;
235 for (;;) {
236 if (!n) break; if (*t == ch) break; ++t; --n;
237 if (!n) break; if (*t == ch) break; ++t; --n;
238 if (!n) break; if (*t == ch) break; ++t; --n;
239 if (!n) break; if (*t == ch) break; ++t; --n;
240 }
241 return t - s;
242}
243
244
245/*** coe.c ***/
246
247int coe(int fd)
248{
249 return fcntl(fd,F_SETFD,FD_CLOEXEC);
250}
251
252
253/*** fd_copy.c ***/
254
255int fd_copy(int to,int from)
256{
257 if (to == from) return 0;
258 if (fcntl(from,F_GETFL,0) == -1) return -1;
259 close(to);
260 if (fcntl(from,F_DUPFD,to) == -1) return -1;
261 return 0;
262}
263
264
265/*** fd_move.c ***/
266
267int fd_move(int to,int from)
268{
269 if (to == from) return 0;
270 if (fd_copy(to,from) == -1) return -1;
271 close(from);
272 return 0;
273}
274
275
276/*** fifo.c ***/
277
278int fifo_make(const char *fn,int mode) { return mkfifo(fn,mode); }
279
280
281/*** fmt_ptime.c ***/
282
283unsigned fmt_ptime(char *s, struct taia *ta) {
284 struct tm *t;
285 unsigned long u;
286
287 if (ta->sec.x < 4611686018427387914ULL) return 0; /* impossible? */
288 u = ta->sec.x -4611686018427387914ULL;
289 if (!(t = gmtime((time_t*)&u))) return 0;
290 fmt_ulong(s, 1900 + t->tm_year);
291 s[4] = '-'; fmt_uint0(&s[5], t->tm_mon+1, 2);
292 s[7] = '-'; fmt_uint0(&s[8], t->tm_mday, 2);
293 s[10] = '_'; fmt_uint0(&s[11], t->tm_hour, 2);
294 s[13] = ':'; fmt_uint0(&s[14], t->tm_min, 2);
295 s[16] = ':'; fmt_uint0(&s[17], t->tm_sec, 2);
296 s[19] = '.'; fmt_uint0(&s[20], ta->nano, 9);
297 return 25;
298}
299
300unsigned fmt_taia(char *s, struct taia *t) {
301 static char hex[16] = "0123456789abcdef";
302 static char pack[TAIA_PACK];
303 int i;
304
305 taia_pack(pack, t);
306 s[0] = '@';
307 for (i = 0; i < 12; ++i) {
308 s[i*2+1] = hex[(pack[i] >> 4) &15];
309 s[i*2+2] = hex[pack[i] &15];
310 }
311 return 25;
312}
313
314
315/*** fmt_uint.c ***/
316
317unsigned fmt_uint(char *s,unsigned u)
318{
319 return fmt_ulong(s,u);
320}
321
322
323/*** fmt_uint0.c ***/
324
325unsigned fmt_uint0(char *s,unsigned u,unsigned n)
326{
327 unsigned len;
328 len = fmt_uint(FMT_LEN,u);
329 while (len < n) { if (s) *s++ = '0'; ++len; }
330 if (s) fmt_uint(s,u);
331 return len;
332}
333
334
335/*** fmt_ulong.c ***/
336
337unsigned fmt_ulong(char *s,unsigned long u)
338{
339 unsigned len; unsigned long q;
340 len = 1; q = u;
341 while (q > 9) { ++len; q /= 10; }
342 if (s) {
343 s += len;
344 do { *--s = '0' + (u % 10); u /= 10; } while(u); /* handles u == 0 */
345 }
346 return len;
347}
348
349
350/*** tai_now.c ***/
351
352void tai_now(struct tai *t)
353{
354 tai_unix(t,time((time_t *) 0));
355}
356
357
358/*** tai_pack.c ***/
359
360void tai_pack(char *s,const struct tai *t)
361{
362 uint64_t x;
363
364 x = t->x;
365 s[7] = x & 255; x >>= 8;
366 s[6] = x & 255; x >>= 8;
367 s[5] = x & 255; x >>= 8;
368 s[4] = x & 255; x >>= 8;
369 s[3] = x & 255; x >>= 8;
370 s[2] = x & 255; x >>= 8;
371 s[1] = x & 255; x >>= 8;
372 s[0] = x;
373}
374
375
376/*** tai_sub.c ***/
377
378void tai_sub(struct tai *t,const struct tai *u,const struct tai *v)
379{
380 t->x = u->x - v->x;
381}
382
383
384/*** tai_unpack.c ***/
385
386void tai_unpack(const char *s,struct tai *t)
387{
388 uint64_t x;
389
390 x = (unsigned char) s[0];
391 x <<= 8; x += (unsigned char) s[1];
392 x <<= 8; x += (unsigned char) s[2];
393 x <<= 8; x += (unsigned char) s[3];
394 x <<= 8; x += (unsigned char) s[4];
395 x <<= 8; x += (unsigned char) s[5];
396 x <<= 8; x += (unsigned char) s[6];
397 x <<= 8; x += (unsigned char) s[7];
398 t->x = x;
399}
400
401
402/*** taia_add.c ***/
403
404/* XXX: breaks tai encapsulation */
405
406void taia_add(struct taia *t,const struct taia *u,const struct taia *v)
407{
408 t->sec.x = u->sec.x + v->sec.x;
409 t->nano = u->nano + v->nano;
410 t->atto = u->atto + v->atto;
411 if (t->atto > 999999999UL) {
412 t->atto -= 1000000000UL;
413 ++t->nano;
414 }
415 if (t->nano > 999999999UL) {
416 t->nano -= 1000000000UL;
417 ++t->sec.x;
418 }
419}
420
421
422/*** taia_approx.c ***/
423
424double taia_approx(const struct taia *t)
425{
426 return tai_approx(&t->sec) + taia_frac(t);
427}
428
429
430/*** taia_frac.c ***/
431
432double taia_frac(const struct taia *t)
433{
434 return (t->atto * 0.000000001 + t->nano) * 0.000000001;
435}
436
437
438/*** taia_less.c ***/
439
440/* XXX: breaks tai encapsulation */
441
442int taia_less(const struct taia *t,const struct taia *u)
443{
444 if (t->sec.x < u->sec.x) return 1;
445 if (t->sec.x > u->sec.x) return 0;
446 if (t->nano < u->nano) return 1;
447 if (t->nano > u->nano) return 0;
448 return t->atto < u->atto;
449}
450
451
452/*** taia_now.c ***/
453
454void taia_now(struct taia *t)
455{
456 struct timeval now;
457 gettimeofday(&now,(struct timezone *) 0);
458 tai_unix(&t->sec,now.tv_sec);
459 t->nano = 1000 * now.tv_usec + 500;
460 t->atto = 0;
461}
462
463
464/*** taia_pack.c ***/
465
466void taia_pack(char *s,const struct taia *t)
467{
468 unsigned long x;
469
470 tai_pack(s,&t->sec);
471 s += 8;
472
473 x = t->atto;
474 s[7] = x & 255; x >>= 8;
475 s[6] = x & 255; x >>= 8;
476 s[5] = x & 255; x >>= 8;
477 s[4] = x;
478 x = t->nano;
479 s[3] = x & 255; x >>= 8;
480 s[2] = x & 255; x >>= 8;
481 s[1] = x & 255; x >>= 8;
482 s[0] = x;
483}
484
485
486/*** taia_sub.c ***/
487
488/* XXX: breaks tai encapsulation */
489
490void taia_sub(struct taia *t,const struct taia *u,const struct taia *v)
491{
492 unsigned long unano = u->nano;
493 unsigned long uatto = u->atto;
494
495 t->sec.x = u->sec.x - v->sec.x;
496 t->nano = unano - v->nano;
497 t->atto = uatto - v->atto;
498 if (t->atto > uatto) {
499 t->atto += 1000000000UL;
500 --t->nano;
501 }
502 if (t->nano > unano) {
503 t->nano += 1000000000UL;
504 --t->sec.x;
505 }
506}
507
508
509/*** taia_uint.c ***/
510
511/* XXX: breaks tai encapsulation */
512
513void taia_uint(struct taia *t,unsigned s)
514{
515 t->sec.x = s;
516 t->nano = 0;
517 t->atto = 0;
518}
519
520
521/*** stralloc_cat.c ***/
522
523int stralloc_cat(stralloc *sato,const stralloc *safrom)
524{
525 return stralloc_catb(sato,safrom->s,safrom->len);
526}
527
528
529/*** stralloc_catb.c ***/
530
531int stralloc_catb(stralloc *sa,const char *s,unsigned n)
532{
533 if (!sa->s) return stralloc_copyb(sa,s,n);
534 if (!stralloc_readyplus(sa,n + 1)) return 0;
535 memcpy(sa->s + sa->len,s,n);
536 sa->len += n;
537 sa->s[sa->len] = 'Z'; /* ``offensive programming'' */
538 return 1;
539}
540
541
542/*** stralloc_cats.c ***/
543
544int stralloc_cats(stralloc *sa,const char *s)
545{
546 return stralloc_catb(sa,s,strlen(s));
547}
548
549
550/*** stralloc_eady.c ***/
551
552GEN_ALLOC_ready(stralloc,char,s,len,a,i,n,x,30,stralloc_ready)
553GEN_ALLOC_readyplus(stralloc,char,s,len,a,i,n,x,30,stralloc_readyplus)
554
555
556/*** stralloc_opyb.c ***/
557
558int stralloc_copyb(stralloc *sa,const char *s,unsigned n)
559{
560 if (!stralloc_ready(sa,n + 1)) return 0;
561 memcpy(sa->s,s,n);
562 sa->len = n;
563 sa->s[n] = 'Z'; /* ``offensive programming'' */
564 return 1;
565}
566
567
568/*** stralloc_opys.c ***/
569
570int stralloc_copys(stralloc *sa,const char *s)
571{
572 return stralloc_copyb(sa,s,strlen(s));
573}
574
575
576/*** stralloc_pend.c ***/
577
578GEN_ALLOC_append(stralloc,char,s,len,a,i,n,x,30,stralloc_readyplus,stralloc_append)
579
580
581/*** iopause.c ***/
582
583void iopause(iopause_fd *x,unsigned len,struct taia *deadline,struct taia *stamp)
584{
585 struct taia t;
586 int millisecs;
587 double d;
588 int i;
589
590 if (taia_less(deadline,stamp))
591 millisecs = 0;
592 else {
593 t = *stamp;
594 taia_sub(&t,deadline,&t);
595 d = taia_approx(&t);
596 if (d > 1000.0) d = 1000.0;
597 millisecs = d * 1000.0 + 20.0;
598 }
599
600 for (i = 0;i < len;++i)
601 x[i].revents = 0;
602
603 poll(x,len,millisecs);
604 /* XXX: some kernels apparently need x[0] even if len is 0 */
605 /* XXX: how to handle EAGAIN? are kernels really this dumb? */
606 /* XXX: how to handle EINVAL? when exactly can this happen? */
607}
608
609
610/*** lock_ex.c ***/
611
612int lock_ex(int fd)
613{
614 return flock(fd,LOCK_EX);
615}
616
617
618/*** lock_exnb.c ***/
619
620int lock_exnb(int fd)
621{
622 return flock(fd,LOCK_EX | LOCK_NB);
623}
624
625
626/*** ndelay_off.c ***/
627
628int ndelay_off(int fd)
629{
630 return fcntl(fd,F_SETFL,fcntl(fd,F_GETFL,0) & ~O_NONBLOCK);
631}
632
633
634/*** ndelay_on.c ***/
635
636int ndelay_on(int fd)
637{
638 return fcntl(fd,F_SETFL,fcntl(fd,F_GETFL,0) | O_NONBLOCK);
639}
640
641
642/*** open_append.c ***/
643
644int open_append(const char *fn)
645{
646 return open(fn,O_WRONLY | O_NDELAY | O_APPEND | O_CREAT,0600);
647}
648
649
650/*** open_read.c ***/
651
652int open_read(const char *fn)
653{
654 return open(fn,O_RDONLY | O_NDELAY);
655}
656
657
658/*** open_trunc.c ***/
659
660int open_trunc(const char *fn)
661{
662 return open(fn,O_WRONLY | O_NDELAY | O_TRUNC | O_CREAT,0644);
663}
664
665
666/*** open_write.c ***/
667
668int open_write(const char *fn)
669{
670 return open(fn,O_WRONLY | O_NDELAY);
671}
672
673
674/*** openreadclose.c ***/
675
676int openreadclose(const char *fn,stralloc *sa,unsigned bufsize)
677{
678 int fd;
679 fd = open_read(fn);
680 if (fd == -1) {
681 if (errno == ENOENT) return 0;
682 return -1;
683 }
684 if (readclose(fd,sa,bufsize) == -1) return -1;
685 return 1;
686}
687
688
689/*** pathexec_env.c ***/
690
691static stralloc plus;
692static stralloc tmp;
693
694int pathexec_env(const char *s,const char *t)
695{
696 if (!s) return 1;
697 if (!stralloc_copys(&tmp,s)) return 0;
698 if (t) {
699 if (!stralloc_cats(&tmp,"=")) return 0;
700 if (!stralloc_cats(&tmp,t)) return 0;
701 }
702 if (!stralloc_0(&tmp)) return 0;
703 return stralloc_cat(&plus,&tmp);
704}
705
706void pathexec(char **argv)
707{
708 char **e;
709 unsigned elen;
710 unsigned i;
711 unsigned j;
712 unsigned split;
713 unsigned t;
714
715 if (!stralloc_cats(&plus,"")) return;
716
717 elen = 0;
718 for (i = 0;environ[i];++i)
719 ++elen;
720 for (i = 0;i < plus.len;++i)
721 if (!plus.s[i])
722 ++elen;
723
724 e = malloc((elen + 1) * sizeof(char *));
725 if (!e) return;
726
727 elen = 0;
728 for (i = 0;environ[i];++i)
729 e[elen++] = environ[i];
730
731 j = 0;
732 for (i = 0;i < plus.len;++i)
733 if (!plus.s[i]) {
734 split = str_chr(plus.s + j,'=');
735 for (t = 0;t < elen;++t)
736 if (memcmp(plus.s + j,e[t],split) == 0)
737 if (e[t][split] == '=') {
738 --elen;
739 e[t] = e[elen];
740 break;
741 }
742 if (plus.s[j + split])
743 e[elen++] = plus.s + j;
744 j = i + 1;
745 }
746 e[elen] = 0;
747
748 pathexec_run(*argv,argv,e);
749 free(e);
750}
751
752
753/*** pathexec_run.c ***/
754
755static stralloc tmp;
756
757void pathexec_run(const char *file,char *const *argv,char *const *envp)
758{
759 const char *path;
760 unsigned split;
761 int savederrno;
762
763 if (file[str_chr(file,'/')]) {
764 execve(file,argv,envp);
765 return;
766 }
767
768 path = getenv("PATH");
769 if (!path) path = "/bin:/usr/bin";
770
771 savederrno = 0;
772 for (;;) {
773 split = str_chr(path,':');
774 if (!stralloc_copyb(&tmp,path,split)) return;
775 if (!split)
776 if (!stralloc_cats(&tmp,".")) return;
777 if (!stralloc_cats(&tmp,"/")) return;
778 if (!stralloc_cats(&tmp,file)) return;
779 if (!stralloc_0(&tmp)) return;
780
781 execve(tmp.s,argv,envp);
782 if (errno != ENOENT) {
783 savederrno = errno;
784 if ((errno != EACCES) && (errno != EPERM) && (errno != EISDIR)) return;
785 }
786
787 if (!path[split]) {
788 if (savederrno) errno = savederrno;
789 return;
790 }
791 path += split;
792 path += 1;
793 }
794}
795
796
797/*** pmatch.c ***/
798
799unsigned pmatch(const char *p, const char *s, unsigned len) {
800 for (;;) {
801 char c = *p++;
802 if (!c) return !len;
803 switch (c) {
804 case '*':
805 if (!(c = *p)) return 1;
806 for (;;) {
807 if (!len) return 0;
808 if (*s == c) break;
809 ++s; --len;
810 }
811 continue;
812 case '+':
813 if ((c = *p++) != *s) return 0;
814 for (;;) {
815 if (!len) return 1;
816 if (*s != c) break;
817 ++s; --len;
818 }
819 continue;
820 /*
821 case '?':
822 if (*p == '?') {
823 if (*s != '?') return 0;
824 ++p;
825 }
826 ++s; --len;
827 continue;
828 */
829 default:
830 if (!len) return 0;
831 if (*s != c) return 0;
832 ++s; --len;
833 continue;
834 }
835 }
836 return 0;
837}
838
839
840/*** prot.c ***/
841
842int prot_gid(int gid)
843{
844 gid_t x = gid;
845 if (setgroups(1,&x) == -1) return -1;
846 return setgid(gid); /* _should_ be redundant, but on some systems it isn't */
847}
848
849int prot_uid(int uid)
850{
851 return setuid(uid);
852}
853
854
855/*** readclose.c ***/
856
857int readclose_append(int fd,stralloc *sa,unsigned bufsize)
858{
859 int r;
860 for (;;) {
861 if (!stralloc_readyplus(sa,bufsize)) { close(fd); return -1; }
862 r = read(fd,sa->s + sa->len,bufsize);
863 if (r == -1) if (errno == EINTR) continue;
864 if (r <= 0) { close(fd); return r; }
865 sa->len += r;
866 }
867}
868
869int readclose(int fd,stralloc *sa,unsigned bufsize)
870{
871 if (!stralloc_copys(sa,"")) { close(fd); return -1; }
872 return readclose_append(fd,sa,bufsize);
873}
874
875
876/*** scan_ulong.c ***/
877
878unsigned scan_ulong(const char *s,unsigned long *u)
879{
880 unsigned pos = 0;
881 unsigned long result = 0;
882 unsigned long c;
883 while ((c = (unsigned long) (unsigned char) (s[pos] - '0')) < 10) {
884 result = result * 10 + c;
885 ++pos;
886 }
887 *u = result;
888 return pos;
889}
890
891
892/*** seek_set.c ***/
893
894int seek_set(int fd,seek_pos pos)
895{
896 if (lseek(fd,(off_t) pos,SEEK_SET) == -1) return -1; return 0;
897}
898
899
900/*** sig.c ***/
901
902int sig_alarm = SIGALRM;
903int sig_child = SIGCHLD;
904int sig_cont = SIGCONT;
905int sig_hangup = SIGHUP;
906int sig_int = SIGINT;
907int sig_pipe = SIGPIPE;
908int sig_term = SIGTERM;
909
910void (*sig_defaulthandler)(int) = SIG_DFL;
911void (*sig_ignorehandler)(int) = SIG_IGN;
912
913
914/*** sig_block.c ***/
915
916void sig_block(int sig)
917{
918 sigset_t ss;
919 sigemptyset(&ss);
920 sigaddset(&ss,sig);
921 sigprocmask(SIG_BLOCK,&ss,(sigset_t *) 0);
922}
923
924void sig_unblock(int sig)
925{
926 sigset_t ss;
927 sigemptyset(&ss);
928 sigaddset(&ss,sig);
929 sigprocmask(SIG_UNBLOCK,&ss,(sigset_t *) 0);
930}
931
932void sig_blocknone(void)
933{
934 sigset_t ss;
935 sigemptyset(&ss);
936 sigprocmask(SIG_SETMASK,&ss,(sigset_t *) 0);
937}
938
939
940/*** sig_catch.c ***/
941
942void sig_catch(int sig,void (*f)(int))
943{
944 struct sigaction sa;
945 sa.sa_handler = f;
946 sa.sa_flags = 0;
947 sigemptyset(&sa.sa_mask);
948 sigaction(sig,&sa,(struct sigaction *) 0);
949}
950
951
952/*** sig_pause.c ***/
953
954void sig_pause(void)
955{
956 sigset_t ss;
957 sigemptyset(&ss);
958 sigsuspend(&ss);
959}
960
961
962/*** str_chr.c ***/
963
964unsigned str_chr(const char *s,int c)
965{
966 char ch;
967 const char *t;
968
969 ch = c;
970 t = s;
971 for (;;) {
972 if (!*t) break; if (*t == ch) break; ++t;
973 if (!*t) break; if (*t == ch) break; ++t;
974 if (!*t) break; if (*t == ch) break; ++t;
975 if (!*t) break; if (*t == ch) break; ++t;
976 }
977 return t - s;
978}
979
980
981/*** wait_nohang.c ***/
982
983int wait_nohang(int *wstat)
984{
985 return waitpid(-1,wstat,WNOHANG);
986}
987
988
989/*** wait_pid.c ***/
990
991int wait_pid(int *wstat, int pid)
992{
993 int r;
994
995 do
996 r = waitpid(pid,wstat,0);
997 while ((r == -1) && (errno == EINTR));
998 return r;
999}