blob: 2953235f023541fe27313a2d2c0e727e3824e3e1 [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;
Denis Vlasenkof7996f32007-01-11 17:20:00 +000087
Denis Vlasenko83ea6432006-11-16 02:27:24 +000088 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;
Denis Vlasenkof7996f32007-01-11 17:20:00 +000097
Denis Vlasenko83ea6432006-11-16 02:27:24 +000098 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;
Denis Vlasenkof7996f32007-01-11 17:20:00 +0000138
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000139 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;
Denis Vlasenkof7996f32007-01-11 17:20:00 +0000148
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000149 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;
Denis Vlasenkof7996f32007-01-11 17:20:00 +0000165
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000166 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) {
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000297 static char pack[TAIA_PACK];
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000298
299 taia_pack(pack, t);
Denis Vlasenko3a34d0c2007-01-12 22:10:34 +0000300 *s++ = '@';
301 bin2hex(s, pack, 12);
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000302 return 25;
303}
304
305
306/*** fmt_uint.c ***/
307
308unsigned fmt_uint(char *s,unsigned u)
309{
310 return fmt_ulong(s,u);
311}
312
313
314/*** fmt_uint0.c ***/
315
316unsigned 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
328unsigned 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;
Denis Vlasenkobf0a2012006-12-26 10:42:51 +0000335 do { *--s = '0' + (u % 10); u /= 10; } while (u); /* handles u == 0 */
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000336 }
337 return len;
338}
339
340
341/*** tai_now.c ***/
342
343void tai_now(struct tai *t)
344{
345 tai_unix(t,time((time_t *) 0));
346}
347
348
349/*** tai_pack.c ***/
350
351void 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
369void 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
377void 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
397void 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
415double taia_approx(const struct taia *t)
416{
417 return tai_approx(&t->sec) + taia_frac(t);
418}
419
420
421/*** taia_frac.c ***/
422
423double 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
433int 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
445void 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
457void 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
481void 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;
Denis Vlasenkof7996f32007-01-11 17:20:00 +0000485
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000486 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
504void 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 ***/
Denis Vlasenko8a00f442006-11-17 18:58:16 +0000513#if 0
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000514
515int 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
523int 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
536int stralloc_cats(stralloc *sa,const char *s)
537{
538 return stralloc_catb(sa,s,strlen(s));
539}
540
541
542/*** stralloc_eady.c ***/
543
544GEN_ALLOC_ready(stralloc,char,s,len,a,i,n,x,30,stralloc_ready)
545GEN_ALLOC_readyplus(stralloc,char,s,len,a,i,n,x,30,stralloc_readyplus)
546
547
548/*** stralloc_opyb.c ***/
549
550int 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
562int stralloc_copys(stralloc *sa,const char *s)
563{
564 return stralloc_copyb(sa,s,strlen(s));
565}
566
567
568/*** stralloc_pend.c ***/
569
570GEN_ALLOC_append(stralloc,char,s,len,a,i,n,x,30,stralloc_readyplus,stralloc_append)
571
Denis Vlasenko8a00f442006-11-17 18:58:16 +0000572#endif /* stralloc */
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000573
574/*** iopause.c ***/
575
576void 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
605int lock_ex(int fd)
606{
607 return flock(fd,LOCK_EX);
608}
609
610
611/*** lock_exnb.c ***/
612
613int lock_exnb(int fd)
614{
615 return flock(fd,LOCK_EX | LOCK_NB);
616}
617
618
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000619/*** open_append.c ***/
620
621int open_append(const char *fn)
622{
Denis Vlasenko8a00f442006-11-17 18:58:16 +0000623 return open(fn, O_WRONLY|O_NDELAY|O_APPEND|O_CREAT, 0600);
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000624}
625
626
627/*** open_read.c ***/
628
629int open_read(const char *fn)
630{
Denis Vlasenko8a00f442006-11-17 18:58:16 +0000631 return open(fn, O_RDONLY|O_NDELAY);
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000632}
633
634
635/*** open_trunc.c ***/
636
637int 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
645int open_write(const char *fn)
646{
Denis Vlasenko8a00f442006-11-17 18:58:16 +0000647 return open(fn, O_WRONLY|O_NDELAY);
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000648}
649
650
651/*** openreadclose.c ***/
Denis Vlasenko8a00f442006-11-17 18:58:16 +0000652#if 0
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000653int 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}
Denis Vlasenko8a00f442006-11-17 18:58:16 +0000664#endif
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000665
666
667/*** pathexec_env.c ***/
Denis Vlasenko8a00f442006-11-17 18:58:16 +0000668#if 0
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000669static stralloc plus;
670static stralloc tmp;
671
672int 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
684void 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}
Denis Vlasenko8a00f442006-11-17 18:58:16 +0000729#endif
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000730
731/*** pathexec_run.c ***/
Denis Vlasenko8a00f442006-11-17 18:58:16 +0000732#if 0
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000733static stralloc tmp;
734
735void 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}
Denis Vlasenko8a00f442006-11-17 18:58:16 +0000773#endif
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000774
775/*** pmatch.c ***/
776
777unsigned 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
820int 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
827int prot_uid(int uid)
828{
829 return setuid(uid);
830}
831
832
833/*** readclose.c ***/
Denis Vlasenko8a00f442006-11-17 18:58:16 +0000834#if 0
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000835int 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
847int 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}
Denis Vlasenko8a00f442006-11-17 18:58:16 +0000852#endif
Denis Vlasenko83ea6432006-11-16 02:27:24 +0000853
854/*** scan_ulong.c ***/
855
856unsigned 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
872int 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
880int sig_alarm = SIGALRM;
881int sig_child = SIGCHLD;
882int sig_cont = SIGCONT;
883int sig_hangup = SIGHUP;
884int sig_int = SIGINT;
885int sig_pipe = SIGPIPE;
886int sig_term = SIGTERM;
887
888void (*sig_defaulthandler)(int) = SIG_DFL;
889void (*sig_ignorehandler)(int) = SIG_IGN;
890
891
892/*** sig_block.c ***/
893
894void 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
902void 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
910void 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
920void 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
932void sig_pause(void)
933{
934 sigset_t ss;
935 sigemptyset(&ss);
936 sigsuspend(&ss);
937}
938
939
940/*** str_chr.c ***/
941
942unsigned 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
961int wait_nohang(int *wstat)
962{
963 return waitpid(-1,wstat,WNOHANG);
964}
965
966
967/*** wait_pid.c ***/
968
969int 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}