2 Copyright (c) 2001-2006, Gerrit Pape
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
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.
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.
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 */
35 #include "runit_lib.h"
39 void buffer_init(buffer *s,int (*op)(int fd,char *buf,unsigned len),int fd,char *buf,unsigned len)
49 /*** buffer_get.c ***/
51 static int oneread(int (*op)(int fd,char *buf,unsigned len),int fd,char *buf,unsigned len)
57 if (r == -1) if (errno == EINTR) continue;
62 static int getthis(buffer *s,char *buf,unsigned len)
64 if (len > s->p) len = s->p;
66 memcpy(buf,s->x + s->n,len);
71 int buffer_feed(buffer *s)
75 if (s->p) return s->p;
76 r = oneread(s->op,s->fd,s->x,s->n);
80 if (s->n > 0) memmove(s->x + s->n,s->x,r);
84 int buffer_bget(buffer *s,char *buf,unsigned len)
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);
94 int buffer_get(buffer *s,char *buf,unsigned len)
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);
104 char *buffer_peek(buffer *s)
109 void buffer_seek(buffer *s,unsigned len)
116 /*** buffer_put.c ***/
118 static int allwrite(int (*op)(int fd,char *buf,unsigned len),int fd,const char *buf,unsigned len)
123 w = op(fd,(char*)buf,len);
125 if (errno == EINTR) continue;
126 return -1; /* note that some data may have been written */
128 if (w == 0) ; /* luser's fault */
135 int buffer_flush(buffer *s)
142 return allwrite(s->op,s->fd,s->x,p);
145 int buffer_putalign(buffer *s,const char *buf,unsigned len)
149 while (len > (n = s->n - s->p)) {
150 memcpy(s->x + s->p,buf,n);
154 if (buffer_flush(s) == -1) return -1;
156 /* now len <= s->n - s->p */
157 memcpy(s->x + s->p,buf,len);
162 int buffer_put(buffer *s,const char *buf,unsigned len)
167 if (len > n - s->p) {
168 if (buffer_flush(s) == -1) return -1;
170 if (n < BUFFER_OUTSIZE) n = BUFFER_OUTSIZE;
172 if (n > len) n = len;
173 if (allwrite(s->op,s->fd,buf,n) == -1) return -1;
178 /* now len <= s->n - s->p */
179 memcpy(s->x + s->p,buf,len);
184 int buffer_putflush(buffer *s,const char *buf,unsigned len)
186 if (buffer_flush(s) == -1) return -1;
187 return allwrite(s->op,s->fd,buf,len);
190 int buffer_putsalign(buffer *s,const char *buf)
192 return buffer_putalign(s,buf,strlen(buf));
195 int buffer_puts(buffer *s,const char *buf)
197 return buffer_put(s,buf,strlen(buf));
200 int buffer_putsflush(buffer *s,const char *buf)
202 return buffer_putflush(s,buf,strlen(buf));
206 /*** buffer_read.c ***/
208 int buffer_unixread(int fd,char *buf,unsigned len)
210 return read(fd,buf,len);
214 /*** buffer_write.c ***/
216 int buffer_unixwrite(int fd,char *buf,unsigned len)
218 return write(fd,buf,len);
224 unsigned byte_chr(char *s,unsigned n,int c)
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;
245 return fcntl(fd,F_SETFD,FD_CLOEXEC);
251 int fd_copy(int to,int from)
253 if (to == from) return 0;
254 if (fcntl(from,F_GETFL,0) == -1) return -1;
256 if (fcntl(from,F_DUPFD,to) == -1) return -1;
263 int fd_move(int to,int from)
265 if (to == from) return 0;
266 if (fd_copy(to,from) == -1) return -1;
274 int fifo_make(const char *fn,int mode) { return mkfifo(fn,mode); }
277 /*** fmt_ptime.c ***/
279 unsigned fmt_ptime(char *s, struct taia *ta) {
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);
296 unsigned fmt_taia(char *s, struct taia *t) {
297 static char pack[TAIA_PACK];
301 bin2hex(s, pack, 12);
308 unsigned fmt_uint(char *s,unsigned u)
310 return fmt_ulong(s,u);
314 /*** fmt_uint0.c ***/
316 unsigned fmt_uint0(char *s,unsigned u,unsigned n)
319 len = fmt_uint(FMT_LEN,u);
320 while (len < n) { if (s) *s++ = '0'; ++len; }
321 if (s) fmt_uint(s,u);
326 /*** fmt_ulong.c ***/
328 unsigned fmt_ulong(char *s,unsigned long u)
330 unsigned len; unsigned long q;
332 while (q > 9) { ++len; q /= 10; }
335 do { *--s = '0' + (u % 10); u /= 10; } while (u); /* handles u == 0 */
343 void tai_now(struct tai *t)
345 tai_unix(t,time((time_t *) 0));
351 void tai_pack(char *s,const struct tai *t)
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;
369 void tai_sub(struct tai *t,const struct tai *u,const struct tai *v)
375 /*** tai_unpack.c ***/
377 void tai_unpack(const char *s,struct tai *t)
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];
395 /* XXX: breaks tai encapsulation */
397 void taia_add(struct taia *t,const struct taia *u,const struct taia *v)
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;
406 if (t->nano > 999999999UL) {
407 t->nano -= 1000000000UL;
413 /*** taia_approx.c ***/
415 double taia_approx(const struct taia *t)
417 return tai_approx(&t->sec) + taia_frac(t);
421 /*** taia_frac.c ***/
423 double taia_frac(const struct taia *t)
425 return (t->atto * 0.000000001 + t->nano) * 0.000000001;
429 /*** taia_less.c ***/
431 /* XXX: breaks tai encapsulation */
433 int taia_less(const struct taia *t,const struct taia *u)
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;
445 void taia_now(struct taia *t)
448 gettimeofday(&now,(struct timezone *) 0);
449 tai_unix(&t->sec,now.tv_sec);
450 t->nano = 1000 * now.tv_usec + 500;
455 /*** taia_pack.c ***/
457 void taia_pack(char *s,const struct taia *t)
465 s[7] = x & 255; x >>= 8;
466 s[6] = x & 255; x >>= 8;
467 s[5] = x & 255; x >>= 8;
470 s[3] = x & 255; x >>= 8;
471 s[2] = x & 255; x >>= 8;
472 s[1] = x & 255; x >>= 8;
479 /* XXX: breaks tai encapsulation */
481 void taia_sub(struct taia *t,const struct taia *u,const struct taia *v)
483 unsigned long unano = u->nano;
484 unsigned long uatto = u->atto;
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;
493 if (t->nano > unano) {
494 t->nano += 1000000000UL;
500 /*** taia_uint.c ***/
502 /* XXX: breaks tai encapsulation */
504 void taia_uint(struct taia *t,unsigned s)
512 /*** stralloc_cat.c ***/
515 int stralloc_cat(stralloc *sato,const stralloc *safrom)
517 return stralloc_catb(sato,safrom->s,safrom->len);
521 /*** stralloc_catb.c ***/
523 int stralloc_catb(stralloc *sa,const char *s,unsigned n)
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);
529 sa->s[sa->len] = 'Z'; /* ``offensive programming'' */
534 /*** stralloc_cats.c ***/
536 int stralloc_cats(stralloc *sa,const char *s)
538 return stralloc_catb(sa,s,strlen(s));
542 /*** stralloc_eady.c ***/
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)
548 /*** stralloc_opyb.c ***/
550 int stralloc_copyb(stralloc *sa,const char *s,unsigned n)
552 if (!stralloc_ready(sa,n + 1)) return 0;
555 sa->s[n] = 'Z'; /* ``offensive programming'' */
560 /*** stralloc_opys.c ***/
562 int stralloc_copys(stralloc *sa,const char *s)
564 return stralloc_copyb(sa,s,strlen(s));
568 /*** stralloc_pend.c ***/
570 GEN_ALLOC_append(stralloc,char,s,len,a,i,n,x,30,stralloc_readyplus,stralloc_append)
572 #endif /* stralloc */
576 void iopause(iopause_fd *x,unsigned len,struct taia *deadline,struct taia *stamp)
583 if (taia_less(deadline,stamp))
587 taia_sub(&t,deadline,&t);
589 if (d > 1000.0) d = 1000.0;
590 millisecs = d * 1000.0 + 20.0;
593 for (i = 0;i < len;++i)
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? */
607 return flock(fd,LOCK_EX);
611 /*** lock_exnb.c ***/
613 int lock_exnb(int fd)
615 return flock(fd,LOCK_EX | LOCK_NB);
619 /*** open_append.c ***/
621 int open_append(const char *fn)
623 return open(fn, O_WRONLY|O_NDELAY|O_APPEND|O_CREAT, 0600);
627 /*** open_read.c ***/
629 int open_read(const char *fn)
631 return open(fn, O_RDONLY|O_NDELAY);
635 /*** open_trunc.c ***/
637 int open_trunc(const char *fn)
639 return open(fn,O_WRONLY | O_NDELAY | O_TRUNC | O_CREAT,0644);
643 /*** open_write.c ***/
645 int open_write(const char *fn)
647 return open(fn, O_WRONLY|O_NDELAY);
651 /*** openreadclose.c ***/
653 int openreadclose(const char *fn,stralloc *sa,unsigned bufsize)
658 if (errno == ENOENT) return 0;
661 if (readclose(fd,sa,bufsize) == -1) return -1;
667 /*** pathexec_env.c ***/
669 static stralloc plus;
672 int pathexec_env(const char *s,const char *t)
675 if (!stralloc_copys(&tmp,s)) return 0;
677 if (!stralloc_cats(&tmp,"=")) return 0;
678 if (!stralloc_cats(&tmp,t)) return 0;
680 if (!stralloc_0(&tmp)) return 0;
681 return stralloc_cat(&plus,&tmp);
684 void pathexec(char **argv)
693 if (!stralloc_cats(&plus,"")) return;
696 for (i = 0;environ[i];++i)
698 for (i = 0;i < plus.len;++i)
702 e = malloc((elen + 1) * sizeof(char *));
706 for (i = 0;environ[i];++i)
707 e[elen++] = environ[i];
710 for (i = 0;i < plus.len;++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] == '=') {
720 if (plus.s[j + split])
721 e[elen++] = plus.s + j;
726 pathexec_run(*argv,argv,e);
731 /*** pathexec_run.c ***/
735 void pathexec_run(const char *file,char *const *argv,char *const *envp)
741 if (file[str_chr(file,'/')]) {
742 execve(file,argv,envp);
746 path = getenv("PATH");
747 if (!path) path = "/bin:/usr/bin";
751 split = str_chr(path,':');
752 if (!stralloc_copyb(&tmp,path,split)) return;
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;
759 execve(tmp.s,argv,envp);
760 if (errno != ENOENT) {
762 if ((errno != EACCES) && (errno != EPERM) && (errno != EISDIR)) return;
766 if (savederrno) errno = savederrno;
777 unsigned pmatch(const char *p, const char *s, unsigned len) {
783 if (!(c = *p)) return 1;
791 if ((c = *p++) != *s) return 0;
801 if (*s != '?') return 0;
809 if (*s != c) return 0;
820 int prot_gid(int gid)
823 if (setgroups(1,&x) == -1) return -1;
824 return setgid(gid); /* _should_ be redundant, but on some systems it isn't */
827 int prot_uid(int uid)
833 /*** readclose.c ***/
835 int readclose_append(int fd,stralloc *sa,unsigned bufsize)
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; }
847 int readclose(int fd,stralloc *sa,unsigned bufsize)
849 if (!stralloc_copys(sa,"")) { close(fd); return -1; }
850 return readclose_append(fd,sa,bufsize);
854 /*** scan_ulong.c ***/
856 unsigned scan_ulong(const char *s,unsigned long *u)
859 unsigned long result = 0;
861 while ((c = (unsigned long) (unsigned char) (s[pos] - '0')) < 10) {
862 result = result * 10 + c;
872 int seek_set(int fd,seek_pos pos)
874 if (lseek(fd,(off_t) pos,SEEK_SET) == -1) return -1; return 0;
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;
888 void (*sig_defaulthandler)(int) = SIG_DFL;
889 void (*sig_ignorehandler)(int) = SIG_IGN;
892 /*** sig_block.c ***/
894 void sig_block(int sig)
899 sigprocmask(SIG_BLOCK,&ss,(sigset_t *) 0);
902 void sig_unblock(int sig)
907 sigprocmask(SIG_UNBLOCK,&ss,(sigset_t *) 0);
910 void sig_blocknone(void)
914 sigprocmask(SIG_SETMASK,&ss,(sigset_t *) 0);
918 /*** sig_catch.c ***/
920 void sig_catch(int sig,void (*f)(int))
925 sigemptyset(&sa.sa_mask);
926 sigaction(sig,&sa,(struct sigaction *) 0);
930 /*** sig_pause.c ***/
942 unsigned str_chr(const char *s,int c)
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;
959 /*** wait_nohang.c ***/
961 int wait_nohang(int *wstat)
963 return waitpid(-1,wstat,WNOHANG);
969 int wait_pid(int *wstat, int pid)
974 r = waitpid(pid,wstat,0);
975 while ((r == -1) && (errno == EINTR));