Magellan Linux

Contents of /trunk/mkinitrd-magellan/busybox/runit/runit_lib.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 532 - (show annotations) (download)
Sat Sep 1 22:45:15 2007 UTC (16 years, 9 months ago) by niro
File MIME type: text/plain
File size: 17948 byte(s)
-import if magellan mkinitrd; it is a fork of redhats mkinitrd-5.0.8 with all magellan patches and features; deprecates magellan-src/mkinitrd

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