322bef858c03a4ca89ca23c18287e6f695ffc57a
[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 #ifndef O_NONBLOCK
38 #define O_NONBLOCK O_NDELAY
39 #endif
40
41 /*** buffer.c ***/
42
43 void 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
55 static 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
66 static 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
75 int 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
88 int 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
98 int 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
108 char *buffer_peek(buffer *s)
109 {
110         return s->x + s->n;
111 }
112
113 void buffer_seek(buffer *s,unsigned len)
114 {
115         s->n += len;
116         s->p -= len;
117 }
118
119
120 /*** buffer_put.c ***/
121
122 static 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
139 int 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
149 int 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
166 int 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
188 int 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
194 int buffer_putsalign(buffer *s,const char *buf)
195 {
196         return buffer_putalign(s,buf,strlen(buf));
197 }
198
199 int buffer_puts(buffer *s,const char *buf)
200 {
201         return buffer_put(s,buf,strlen(buf));
202 }
203
204 int buffer_putsflush(buffer *s,const char *buf)
205 {
206         return buffer_putflush(s,buf,strlen(buf));
207 }
208
209
210 /*** buffer_read.c ***/
211
212 int buffer_unixread(int fd,char *buf,unsigned len)
213 {
214         return read(fd,buf,len);
215 }
216
217
218 /*** buffer_write.c ***/
219
220 int buffer_unixwrite(int fd,char *buf,unsigned len)
221 {
222         return write(fd,buf,len);
223 }
224
225
226 /*** byte_chr.c ***/
227
228 unsigned 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
247 int coe(int fd)
248 {
249         return fcntl(fd,F_SETFD,FD_CLOEXEC);
250 }
251
252
253 /*** fd_copy.c ***/
254
255 int 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
267 int 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
278 int fifo_make(const char *fn,int mode) { return mkfifo(fn,mode); }
279
280
281 /*** fmt_ptime.c ***/
282
283 unsigned 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
300 unsigned 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
317 unsigned fmt_uint(char *s,unsigned u)
318 {
319         return fmt_ulong(s,u);
320 }
321
322
323 /*** fmt_uint0.c ***/
324
325 unsigned 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
337 unsigned 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
352 void tai_now(struct tai *t)
353 {
354         tai_unix(t,time((time_t *) 0));
355 }
356
357
358 /*** tai_pack.c ***/
359
360 void 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
378 void 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
386 void 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
406 void 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
424 double taia_approx(const struct taia *t)
425 {
426         return tai_approx(&t->sec) + taia_frac(t);
427 }
428
429
430 /*** taia_frac.c ***/
431
432 double 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
442 int 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
454 void 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
466 void 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
490 void 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
513 void 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
523 int 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
531 int 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
544 int stralloc_cats(stralloc *sa,const char *s)
545 {
546         return stralloc_catb(sa,s,strlen(s));
547 }
548
549
550 /*** stralloc_eady.c ***/
551
552 GEN_ALLOC_ready(stralloc,char,s,len,a,i,n,x,30,stralloc_ready)
553 GEN_ALLOC_readyplus(stralloc,char,s,len,a,i,n,x,30,stralloc_readyplus)
554
555
556 /*** stralloc_opyb.c ***/
557
558 int 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
570 int stralloc_copys(stralloc *sa,const char *s)
571 {
572         return stralloc_copyb(sa,s,strlen(s));
573 }
574
575
576 /*** stralloc_pend.c ***/
577
578 GEN_ALLOC_append(stralloc,char,s,len,a,i,n,x,30,stralloc_readyplus,stralloc_append)
579
580
581 /*** iopause.c ***/
582
583 void 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
612 int lock_ex(int fd)
613 {
614         return flock(fd,LOCK_EX);
615 }
616
617
618 /*** lock_exnb.c ***/
619
620 int lock_exnb(int fd)
621 {
622         return flock(fd,LOCK_EX | LOCK_NB);
623 }
624
625
626 /*** ndelay_off.c ***/
627
628 int 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
636 int 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
644 int 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
652 int open_read(const char *fn)
653 {
654         return open(fn,O_RDONLY | O_NDELAY);
655 }
656
657
658 /*** open_trunc.c ***/
659
660 int 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
668 int open_write(const char *fn)
669 {
670         return open(fn,O_WRONLY | O_NDELAY);
671 }
672
673
674 /*** openreadclose.c ***/
675
676 int 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
691 static stralloc plus;
692 static stralloc tmp;
693
694 int 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
706 void 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
755 static stralloc tmp;
756
757 void 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
799 unsigned 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
842 int 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
849 int prot_uid(int uid)
850 {
851         return setuid(uid);
852 }
853
854
855 /*** readclose.c ***/
856
857 int 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
869 int 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
878 unsigned 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
894 int 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
902 int sig_alarm = SIGALRM;
903 int sig_child = SIGCHLD;
904 int sig_cont = SIGCONT;
905 int sig_hangup = SIGHUP;
906 int sig_int = SIGINT;
907 int sig_pipe = SIGPIPE;
908 int sig_term = SIGTERM;
909
910 void (*sig_defaulthandler)(int) = SIG_DFL;
911 void (*sig_ignorehandler)(int) = SIG_IGN;
912
913
914 /*** sig_block.c ***/
915
916 void 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
924 void 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
932 void 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
942 void 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
954 void sig_pause(void)
955 {
956         sigset_t ss;
957         sigemptyset(&ss);
958         sigsuspend(&ss);
959 }
960
961
962 /*** str_chr.c ***/
963
964 unsigned 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
983 int wait_nohang(int *wstat)
984 {
985         return waitpid(-1,wstat,WNOHANG);
986 }
987
988
989 /*** wait_pid.c ***/
990
991 int 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 }