blob: 8612a1b94c404904197e16464dd37d6ae19daa6f [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 Vlasenko83ea6432006-11-16 02:27:24 +000037/*** buffer.c ***/
38
39void 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
51static 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
62static 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
71int 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
84int 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
94int 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
104char *buffer_peek(buffer *s)
105{
106 return s->x + s->n;
107}
108
109void buffer_seek(buffer *s,unsigned len)
110{
111 s->n += len;
112 s->p -= len;
113}
114
115
116/*** buffer_put.c ***/
117
118static 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
135int 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
145int 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
162int 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
184int 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
190int buffer_putsalign(buffer *s,const char *buf)
191{
192 return buffer_putalign(s,buf,strlen(buf));
193}
194
195int buffer_puts(buffer *s,const char *buf)
196{
197 return buffer_put(s,buf,strlen(buf));
198}
199
200int buffer_putsflush(buffer *s,const char *buf)
201{
202 return buffer_putflush(s,buf,strlen(buf));
203}
204
205
206/*** buffer_read.c ***/
207
208int buffer_unixread(int fd,char *buf,unsigned len)
209{
210 return read(fd,buf,len);
211}
212
213
214/*** buffer_write.c ***/
215
216int buffer_unixwrite(int fd,char *buf,unsigned len)
217{
218 return write(fd,buf,len);
219}
220
221
222/*** byte_chr.c ***/
223
224unsigned 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
243int coe(int fd)
244{
245 return fcntl(fd,F_SETFD,FD_CLOEXEC);
246}
247
248
249/*** fd_copy.c ***/
250
251int 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
263int 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
274int fifo_make(const char *fn,int mode) { return mkfifo(fn,mode); }
275
276
277/*** fmt_ptime.c ***/
278
279unsigned 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
296unsigned fmt_taia(char *s, struct taia *t) {
297 static char hex[16] = "0123456789abcdef";
298 static char pack[TAIA_PACK];
299 int i;
300
301 taia_pack(pack, t);
302 s[0] = '@';
303 for (i = 0; i < 12; ++i) {
304 s[i*2+1] = hex[(pack[i] >> 4) &15];
305 s[i*2+2] = hex[pack[i] &15];
306 }
307 return 25;
308}
309
310
311/*** fmt_uint.c ***/
312
313unsigned fmt_uint(char *s,unsigned u)
314{
315 return fmt_ulong(s,u);
316}
317
318
319/*** fmt_uint0.c ***/
320
321unsigned fmt_uint0(char *s,unsigned u,unsigned n)
322{
323 unsigned len;
324 len = fmt_uint(FMT_LEN,u);
325 while (len < n) { if (s) *s++ = '0'; ++len; }
326 if (s) fmt_uint(s,u);
327 return len;
328}
329
330
331/*** fmt_ulong.c ***/
332
333unsigned fmt_ulong(char *s,unsigned long u)
334{
335 unsigned len; unsigned long q;
336 len = 1; q = u;
337 while (q > 9) { ++len; q /= 10; }
338 if (s) {
339 s += len;
Denis Vlasenkobf0a2012006-12-26 10:42:51 +0000340 do { *--s = '0' + (u % 10); u /= 10; } while (u); /* handles u == 0 */
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000341 }
342 return len;
343}
344
345
346/*** tai_now.c ***/
347
348void tai_now(struct tai *t)
349{
350 tai_unix(t,time((time_t *) 0));
351}
352
353
354/*** tai_pack.c ***/
355
356void tai_pack(char *s,const struct tai *t)
357{
358 uint64_t x;
359
360 x = t->x;
361 s[7] = x & 255; x >>= 8;
362 s[6] = x & 255; x >>= 8;
363 s[5] = x & 255; x >>= 8;
364 s[4] = x & 255; x >>= 8;
365 s[3] = x & 255; x >>= 8;
366 s[2] = x & 255; x >>= 8;
367 s[1] = x & 255; x >>= 8;
368 s[0] = x;
369}
370
371
372/*** tai_sub.c ***/
373
374void tai_sub(struct tai *t,const struct tai *u,const struct tai *v)
375{
376 t->x = u->x - v->x;
377}
378
379
380/*** tai_unpack.c ***/
381
382void tai_unpack(const char *s,struct tai *t)
383{
384 uint64_t x;
385
386 x = (unsigned char) s[0];
387 x <<= 8; x += (unsigned char) s[1];
388 x <<= 8; x += (unsigned char) s[2];
389 x <<= 8; x += (unsigned char) s[3];
390 x <<= 8; x += (unsigned char) s[4];
391 x <<= 8; x += (unsigned char) s[5];
392 x <<= 8; x += (unsigned char) s[6];
393 x <<= 8; x += (unsigned char) s[7];
394 t->x = x;
395}
396
397
398/*** taia_add.c ***/
399
400/* XXX: breaks tai encapsulation */
401
402void taia_add(struct taia *t,const struct taia *u,const struct taia *v)
403{
404 t->sec.x = u->sec.x + v->sec.x;
405 t->nano = u->nano + v->nano;
406 t->atto = u->atto + v->atto;
407 if (t->atto > 999999999UL) {
408 t->atto -= 1000000000UL;
409 ++t->nano;
410 }
411 if (t->nano > 999999999UL) {
412 t->nano -= 1000000000UL;
413 ++t->sec.x;
414 }
415}
416
417
418/*** taia_approx.c ***/
419
420double taia_approx(const struct taia *t)
421{
422 return tai_approx(&t->sec) + taia_frac(t);
423}
424
425
426/*** taia_frac.c ***/
427
428double taia_frac(const struct taia *t)
429{
430 return (t->atto * 0.000000001 + t->nano) * 0.000000001;
431}
432
433
434/*** taia_less.c ***/
435
436/* XXX: breaks tai encapsulation */
437
438int taia_less(const struct taia *t,const struct taia *u)
439{
440 if (t->sec.x < u->sec.x) return 1;
441 if (t->sec.x > u->sec.x) return 0;
442 if (t->nano < u->nano) return 1;
443 if (t->nano > u->nano) return 0;
444 return t->atto < u->atto;
445}
446
447
448/*** taia_now.c ***/
449
450void taia_now(struct taia *t)
451{
452 struct timeval now;
453 gettimeofday(&now,(struct timezone *) 0);
454 tai_unix(&t->sec,now.tv_sec);
455 t->nano = 1000 * now.tv_usec + 500;
456 t->atto = 0;
457}
458
459
460/*** taia_pack.c ***/
461
462void taia_pack(char *s,const struct taia *t)
463{
464 unsigned long x;
465
466 tai_pack(s,&t->sec);
467 s += 8;
468
469 x = t->atto;
470 s[7] = x & 255; x >>= 8;
471 s[6] = x & 255; x >>= 8;
472 s[5] = x & 255; x >>= 8;
473 s[4] = x;
474 x = t->nano;
475 s[3] = x & 255; x >>= 8;
476 s[2] = x & 255; x >>= 8;
477 s[1] = x & 255; x >>= 8;
478 s[0] = x;
479}
480
481
482/*** taia_sub.c ***/
483
484/* XXX: breaks tai encapsulation */
485
486void taia_sub(struct taia *t,const struct taia *u,const struct taia *v)
487{
488 unsigned long unano = u->nano;
489 unsigned long uatto = u->atto;
490
491 t->sec.x = u->sec.x - v->sec.x;
492 t->nano = unano - v->nano;
493 t->atto = uatto - v->atto;
494 if (t->atto > uatto) {
495 t->atto += 1000000000UL;
496 --t->nano;
497 }
498 if (t->nano > unano) {
499 t->nano += 1000000000UL;
500 --t->sec.x;
501 }
502}
503
504
505/*** taia_uint.c ***/
506
507/* XXX: breaks tai encapsulation */
508
509void taia_uint(struct taia *t,unsigned s)
510{
511 t->sec.x = s;
512 t->nano = 0;
513 t->atto = 0;
514}
515
516
517/*** stralloc_cat.c ***/
Denis Vlasenko8a00f442006-11-17 18:58:16 +0000518#if 0
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000519
520int stralloc_cat(stralloc *sato,const stralloc *safrom)
521{
522 return stralloc_catb(sato,safrom->s,safrom->len);
523}
524
525
526/*** stralloc_catb.c ***/
527
528int stralloc_catb(stralloc *sa,const char *s,unsigned n)
529{
530 if (!sa->s) return stralloc_copyb(sa,s,n);
531 if (!stralloc_readyplus(sa,n + 1)) return 0;
532 memcpy(sa->s + sa->len,s,n);
533 sa->len += n;
534 sa->s[sa->len] = 'Z'; /* ``offensive programming'' */
535 return 1;
536}
537
538
539/*** stralloc_cats.c ***/
540
541int stralloc_cats(stralloc *sa,const char *s)
542{
543 return stralloc_catb(sa,s,strlen(s));
544}
545
546
547/*** stralloc_eady.c ***/
548
549GEN_ALLOC_ready(stralloc,char,s,len,a,i,n,x,30,stralloc_ready)
550GEN_ALLOC_readyplus(stralloc,char,s,len,a,i,n,x,30,stralloc_readyplus)
551
552
553/*** stralloc_opyb.c ***/
554
555int stralloc_copyb(stralloc *sa,const char *s,unsigned n)
556{
557 if (!stralloc_ready(sa,n + 1)) return 0;
558 memcpy(sa->s,s,n);
559 sa->len = n;
560 sa->s[n] = 'Z'; /* ``offensive programming'' */
561 return 1;
562}
563
564
565/*** stralloc_opys.c ***/
566
567int stralloc_copys(stralloc *sa,const char *s)
568{
569 return stralloc_copyb(sa,s,strlen(s));
570}
571
572
573/*** stralloc_pend.c ***/
574
575GEN_ALLOC_append(stralloc,char,s,len,a,i,n,x,30,stralloc_readyplus,stralloc_append)
576
Denis Vlasenko8a00f442006-11-17 18:58:16 +0000577#endif /* stralloc */
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000578
579/*** iopause.c ***/
580
581void iopause(iopause_fd *x,unsigned len,struct taia *deadline,struct taia *stamp)
582{
583 struct taia t;
584 int millisecs;
585 double d;
586 int i;
587
588 if (taia_less(deadline,stamp))
589 millisecs = 0;
590 else {
591 t = *stamp;
592 taia_sub(&t,deadline,&t);
593 d = taia_approx(&t);
594 if (d > 1000.0) d = 1000.0;
595 millisecs = d * 1000.0 + 20.0;
596 }
597
598 for (i = 0;i < len;++i)
599 x[i].revents = 0;
600
601 poll(x,len,millisecs);
602 /* XXX: some kernels apparently need x[0] even if len is 0 */
603 /* XXX: how to handle EAGAIN? are kernels really this dumb? */
604 /* XXX: how to handle EINVAL? when exactly can this happen? */
605}
606
607
608/*** lock_ex.c ***/
609
610int lock_ex(int fd)
611{
612 return flock(fd,LOCK_EX);
613}
614
615
616/*** lock_exnb.c ***/
617
618int lock_exnb(int fd)
619{
620 return flock(fd,LOCK_EX | LOCK_NB);
621}
622
623
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000624/*** open_append.c ***/
625
626int open_append(const char *fn)
627{
Denis Vlasenko8a00f442006-11-17 18:58:16 +0000628 return open(fn, O_WRONLY|O_NDELAY|O_APPEND|O_CREAT, 0600);
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000629}
630
631
632/*** open_read.c ***/
633
634int open_read(const char *fn)
635{
Denis Vlasenko8a00f442006-11-17 18:58:16 +0000636 return open(fn, O_RDONLY|O_NDELAY);
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000637}
638
639
640/*** open_trunc.c ***/
641
642int open_trunc(const char *fn)
643{
644 return open(fn,O_WRONLY | O_NDELAY | O_TRUNC | O_CREAT,0644);
645}
646
647
648/*** open_write.c ***/
649
650int open_write(const char *fn)
651{
Denis Vlasenko8a00f442006-11-17 18:58:16 +0000652 return open(fn, O_WRONLY|O_NDELAY);
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000653}
654
655
656/*** openreadclose.c ***/
Denis Vlasenko8a00f442006-11-17 18:58:16 +0000657#if 0
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000658int openreadclose(const char *fn,stralloc *sa,unsigned bufsize)
659{
660 int fd;
661 fd = open_read(fn);
662 if (fd == -1) {
663 if (errno == ENOENT) return 0;
664 return -1;
665 }
666 if (readclose(fd,sa,bufsize) == -1) return -1;
667 return 1;
668}
Denis Vlasenko8a00f442006-11-17 18:58:16 +0000669#endif
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000670
671
672/*** pathexec_env.c ***/
Denis Vlasenko8a00f442006-11-17 18:58:16 +0000673#if 0
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000674static stralloc plus;
675static stralloc tmp;
676
677int pathexec_env(const char *s,const char *t)
678{
679 if (!s) return 1;
680 if (!stralloc_copys(&tmp,s)) return 0;
681 if (t) {
682 if (!stralloc_cats(&tmp,"=")) return 0;
683 if (!stralloc_cats(&tmp,t)) return 0;
684 }
685 if (!stralloc_0(&tmp)) return 0;
686 return stralloc_cat(&plus,&tmp);
687}
688
689void pathexec(char **argv)
690{
691 char **e;
692 unsigned elen;
693 unsigned i;
694 unsigned j;
695 unsigned split;
696 unsigned t;
697
698 if (!stralloc_cats(&plus,"")) return;
699
700 elen = 0;
701 for (i = 0;environ[i];++i)
702 ++elen;
703 for (i = 0;i < plus.len;++i)
704 if (!plus.s[i])
705 ++elen;
706
707 e = malloc((elen + 1) * sizeof(char *));
708 if (!e) return;
709
710 elen = 0;
711 for (i = 0;environ[i];++i)
712 e[elen++] = environ[i];
713
714 j = 0;
715 for (i = 0;i < plus.len;++i)
716 if (!plus.s[i]) {
717 split = str_chr(plus.s + j,'=');
718 for (t = 0;t < elen;++t)
719 if (memcmp(plus.s + j,e[t],split) == 0)
720 if (e[t][split] == '=') {
721 --elen;
722 e[t] = e[elen];
723 break;
724 }
725 if (plus.s[j + split])
726 e[elen++] = plus.s + j;
727 j = i + 1;
728 }
729 e[elen] = 0;
730
731 pathexec_run(*argv,argv,e);
732 free(e);
733}
Denis Vlasenko8a00f442006-11-17 18:58:16 +0000734#endif
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000735
736/*** pathexec_run.c ***/
Denis Vlasenko8a00f442006-11-17 18:58:16 +0000737#if 0
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000738static stralloc tmp;
739
740void pathexec_run(const char *file,char *const *argv,char *const *envp)
741{
742 const char *path;
743 unsigned split;
744 int savederrno;
745
746 if (file[str_chr(file,'/')]) {
747 execve(file,argv,envp);
748 return;
749 }
750
751 path = getenv("PATH");
752 if (!path) path = "/bin:/usr/bin";
753
754 savederrno = 0;
755 for (;;) {
756 split = str_chr(path,':');
757 if (!stralloc_copyb(&tmp,path,split)) return;
758 if (!split)
759 if (!stralloc_cats(&tmp,".")) return;
760 if (!stralloc_cats(&tmp,"/")) return;
761 if (!stralloc_cats(&tmp,file)) return;
762 if (!stralloc_0(&tmp)) return;
763
764 execve(tmp.s,argv,envp);
765 if (errno != ENOENT) {
766 savederrno = errno;
767 if ((errno != EACCES) && (errno != EPERM) && (errno != EISDIR)) return;
768 }
769
770 if (!path[split]) {
771 if (savederrno) errno = savederrno;
772 return;
773 }
774 path += split;
775 path += 1;
776 }
777}
Denis Vlasenko8a00f442006-11-17 18:58:16 +0000778#endif
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000779
780/*** pmatch.c ***/
781
782unsigned pmatch(const char *p, const char *s, unsigned len) {
783 for (;;) {
784 char c = *p++;
785 if (!c) return !len;
786 switch (c) {
787 case '*':
788 if (!(c = *p)) return 1;
789 for (;;) {
790 if (!len) return 0;
791 if (*s == c) break;
792 ++s; --len;
793 }
794 continue;
795 case '+':
796 if ((c = *p++) != *s) return 0;
797 for (;;) {
798 if (!len) return 1;
799 if (*s != c) break;
800 ++s; --len;
801 }
802 continue;
803 /*
804 case '?':
805 if (*p == '?') {
806 if (*s != '?') return 0;
807 ++p;
808 }
809 ++s; --len;
810 continue;
811 */
812 default:
813 if (!len) return 0;
814 if (*s != c) return 0;
815 ++s; --len;
816 continue;
817 }
818 }
819 return 0;
820}
821
822
823/*** prot.c ***/
824
825int prot_gid(int gid)
826{
827 gid_t x = gid;
828 if (setgroups(1,&x) == -1) return -1;
829 return setgid(gid); /* _should_ be redundant, but on some systems it isn't */
830}
831
832int prot_uid(int uid)
833{
834 return setuid(uid);
835}
836
837
838/*** readclose.c ***/
Denis Vlasenko8a00f442006-11-17 18:58:16 +0000839#if 0
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000840int readclose_append(int fd,stralloc *sa,unsigned bufsize)
841{
842 int r;
843 for (;;) {
844 if (!stralloc_readyplus(sa,bufsize)) { close(fd); return -1; }
845 r = read(fd,sa->s + sa->len,bufsize);
846 if (r == -1) if (errno == EINTR) continue;
847 if (r <= 0) { close(fd); return r; }
848 sa->len += r;
849 }
850}
851
852int readclose(int fd,stralloc *sa,unsigned bufsize)
853{
854 if (!stralloc_copys(sa,"")) { close(fd); return -1; }
855 return readclose_append(fd,sa,bufsize);
856}
Denis Vlasenko8a00f442006-11-17 18:58:16 +0000857#endif
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000858
859/*** scan_ulong.c ***/
860
861unsigned scan_ulong(const char *s,unsigned long *u)
862{
863 unsigned pos = 0;
864 unsigned long result = 0;
865 unsigned long c;
866 while ((c = (unsigned long) (unsigned char) (s[pos] - '0')) < 10) {
867 result = result * 10 + c;
868 ++pos;
869 }
870 *u = result;
871 return pos;
872}
873
874
875/*** seek_set.c ***/
876
877int seek_set(int fd,seek_pos pos)
878{
879 if (lseek(fd,(off_t) pos,SEEK_SET) == -1) return -1; return 0;
880}
881
882
883/*** sig.c ***/
884
885int sig_alarm = SIGALRM;
886int sig_child = SIGCHLD;
887int sig_cont = SIGCONT;
888int sig_hangup = SIGHUP;
889int sig_int = SIGINT;
890int sig_pipe = SIGPIPE;
891int sig_term = SIGTERM;
892
893void (*sig_defaulthandler)(int) = SIG_DFL;
894void (*sig_ignorehandler)(int) = SIG_IGN;
895
896
897/*** sig_block.c ***/
898
899void sig_block(int sig)
900{
901 sigset_t ss;
902 sigemptyset(&ss);
903 sigaddset(&ss,sig);
904 sigprocmask(SIG_BLOCK,&ss,(sigset_t *) 0);
905}
906
907void sig_unblock(int sig)
908{
909 sigset_t ss;
910 sigemptyset(&ss);
911 sigaddset(&ss,sig);
912 sigprocmask(SIG_UNBLOCK,&ss,(sigset_t *) 0);
913}
914
915void sig_blocknone(void)
916{
917 sigset_t ss;
918 sigemptyset(&ss);
919 sigprocmask(SIG_SETMASK,&ss,(sigset_t *) 0);
920}
921
922
923/*** sig_catch.c ***/
924
925void sig_catch(int sig,void (*f)(int))
926{
927 struct sigaction sa;
928 sa.sa_handler = f;
929 sa.sa_flags = 0;
930 sigemptyset(&sa.sa_mask);
931 sigaction(sig,&sa,(struct sigaction *) 0);
932}
933
934
935/*** sig_pause.c ***/
936
937void sig_pause(void)
938{
939 sigset_t ss;
940 sigemptyset(&ss);
941 sigsuspend(&ss);
942}
943
944
945/*** str_chr.c ***/
946
947unsigned str_chr(const char *s,int c)
948{
949 char ch;
950 const char *t;
951
952 ch = c;
953 t = s;
954 for (;;) {
955 if (!*t) break; if (*t == ch) break; ++t;
956 if (!*t) break; if (*t == ch) break; ++t;
957 if (!*t) break; if (*t == ch) break; ++t;
958 if (!*t) break; if (*t == ch) break; ++t;
959 }
960 return t - s;
961}
962
963
964/*** wait_nohang.c ***/
965
966int wait_nohang(int *wstat)
967{
968 return waitpid(-1,wstat,WNOHANG);
969}
970
971
972/*** wait_pid.c ***/
973
974int wait_pid(int *wstat, int pid)
975{
976 int r;
977
978 do
979 r = waitpid(pid,wstat,0);
980 while ((r == -1) && (errno == EINTR));
981 return r;
982}