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"
38 #define O_NONBLOCK O_NDELAY
43 void buffer_init(buffer *s,int (*op)(int fd,char *buf,unsigned len),int fd,char *buf,unsigned len)
53 /*** buffer_get.c ***/
55 static int oneread(int (*op)(int fd,char *buf,unsigned len),int fd,char *buf,unsigned len)
61 if (r == -1) if (errno == EINTR) continue;
66 static int getthis(buffer *s,char *buf,unsigned len)
68 if (len > s->p) len = s->p;
70 memcpy(buf,s->x + s->n,len);
75 int buffer_feed(buffer *s)
79 if (s->p) return s->p;
80 r = oneread(s->op,s->fd,s->x,s->n);
84 if (s->n > 0) memmove(s->x + s->n,s->x,r);
88 int buffer_bget(buffer *s,char *buf,unsigned len)
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);
98 int buffer_get(buffer *s,char *buf,unsigned len)
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);
108 char *buffer_peek(buffer *s)
113 void buffer_seek(buffer *s,unsigned len)
120 /*** buffer_put.c ***/
122 static int allwrite(int (*op)(int fd,char *buf,unsigned len),int fd,const char *buf,unsigned len)
127 w = op(fd,(char*)buf,len);
129 if (errno == EINTR) continue;
130 return -1; /* note that some data may have been written */
132 if (w == 0) ; /* luser's fault */
139 int buffer_flush(buffer *s)
146 return allwrite(s->op,s->fd,s->x,p);
149 int buffer_putalign(buffer *s,const char *buf,unsigned len)
153 while (len > (n = s->n - s->p)) {
154 memcpy(s->x + s->p,buf,n);
158 if (buffer_flush(s) == -1) return -1;
160 /* now len <= s->n - s->p */
161 memcpy(s->x + s->p,buf,len);
166 int buffer_put(buffer *s,const char *buf,unsigned len)
171 if (len > n - s->p) {
172 if (buffer_flush(s) == -1) return -1;
174 if (n < BUFFER_OUTSIZE) n = BUFFER_OUTSIZE;
176 if (n > len) n = len;
177 if (allwrite(s->op,s->fd,buf,n) == -1) return -1;
182 /* now len <= s->n - s->p */
183 memcpy(s->x + s->p,buf,len);
188 int buffer_putflush(buffer *s,const char *buf,unsigned len)
190 if (buffer_flush(s) == -1) return -1;
191 return allwrite(s->op,s->fd,buf,len);
194 int buffer_putsalign(buffer *s,const char *buf)
196 return buffer_putalign(s,buf,strlen(buf));
199 int buffer_puts(buffer *s,const char *buf)
201 return buffer_put(s,buf,strlen(buf));
204 int buffer_putsflush(buffer *s,const char *buf)
206 return buffer_putflush(s,buf,strlen(buf));
210 /*** buffer_read.c ***/
212 int buffer_unixread(int fd,char *buf,unsigned len)
214 return read(fd,buf,len);
218 /*** buffer_write.c ***/
220 int buffer_unixwrite(int fd,char *buf,unsigned len)
222 return write(fd,buf,len);
228 unsigned byte_chr(char *s,unsigned n,int c)
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;
249 return fcntl(fd,F_SETFD,FD_CLOEXEC);
255 int fd_copy(int to,int from)
257 if (to == from) return 0;
258 if (fcntl(from,F_GETFL,0) == -1) return -1;
260 if (fcntl(from,F_DUPFD,to) == -1) return -1;
267 int fd_move(int to,int from)
269 if (to == from) return 0;
270 if (fd_copy(to,from) == -1) return -1;
278 int fifo_make(const char *fn,int mode) { return mkfifo(fn,mode); }
281 /*** fmt_ptime.c ***/
283 unsigned fmt_ptime(char *s, struct taia *ta) {
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);
300 unsigned fmt_taia(char *s, struct taia *t) {
301 static char hex[16] = "0123456789abcdef";
302 static char pack[TAIA_PACK];
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];
317 unsigned fmt_uint(char *s,unsigned u)
319 return fmt_ulong(s,u);
323 /*** fmt_uint0.c ***/
325 unsigned fmt_uint0(char *s,unsigned u,unsigned n)
328 len = fmt_uint(FMT_LEN,u);
329 while (len < n) { if (s) *s++ = '0'; ++len; }
330 if (s) fmt_uint(s,u);
335 /*** fmt_ulong.c ***/
337 unsigned fmt_ulong(char *s,unsigned long u)
339 unsigned len; unsigned long q;
341 while (q > 9) { ++len; q /= 10; }
344 do { *--s = '0' + (u % 10); u /= 10; } while(u); /* handles u == 0 */
352 void tai_now(struct tai *t)
354 tai_unix(t,time((time_t *) 0));
360 void tai_pack(char *s,const struct tai *t)
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;
378 void tai_sub(struct tai *t,const struct tai *u,const struct tai *v)
384 /*** tai_unpack.c ***/
386 void tai_unpack(const char *s,struct tai *t)
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];
404 /* XXX: breaks tai encapsulation */
406 void taia_add(struct taia *t,const struct taia *u,const struct taia *v)
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;
415 if (t->nano > 999999999UL) {
416 t->nano -= 1000000000UL;
422 /*** taia_approx.c ***/
424 double taia_approx(const struct taia *t)
426 return tai_approx(&t->sec) + taia_frac(t);
430 /*** taia_frac.c ***/
432 double taia_frac(const struct taia *t)
434 return (t->atto * 0.000000001 + t->nano) * 0.000000001;
438 /*** taia_less.c ***/
440 /* XXX: breaks tai encapsulation */
442 int taia_less(const struct taia *t,const struct taia *u)
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;
454 void taia_now(struct taia *t)
457 gettimeofday(&now,(struct timezone *) 0);
458 tai_unix(&t->sec,now.tv_sec);
459 t->nano = 1000 * now.tv_usec + 500;
464 /*** taia_pack.c ***/
466 void taia_pack(char *s,const struct taia *t)
474 s[7] = x & 255; x >>= 8;
475 s[6] = x & 255; x >>= 8;
476 s[5] = x & 255; x >>= 8;
479 s[3] = x & 255; x >>= 8;
480 s[2] = x & 255; x >>= 8;
481 s[1] = x & 255; x >>= 8;
488 /* XXX: breaks tai encapsulation */
490 void taia_sub(struct taia *t,const struct taia *u,const struct taia *v)
492 unsigned long unano = u->nano;
493 unsigned long uatto = u->atto;
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;
502 if (t->nano > unano) {
503 t->nano += 1000000000UL;
509 /*** taia_uint.c ***/
511 /* XXX: breaks tai encapsulation */
513 void taia_uint(struct taia *t,unsigned s)
521 /*** stralloc_cat.c ***/
524 int stralloc_cat(stralloc *sato,const stralloc *safrom)
526 return stralloc_catb(sato,safrom->s,safrom->len);
530 /*** stralloc_catb.c ***/
532 int stralloc_catb(stralloc *sa,const char *s,unsigned n)
534 if (!sa->s) return stralloc_copyb(sa,s,n);
535 if (!stralloc_readyplus(sa,n + 1)) return 0;
536 memcpy(sa->s + sa->len,s,n);
538 sa->s[sa->len] = 'Z'; /* ``offensive programming'' */
543 /*** stralloc_cats.c ***/
545 int stralloc_cats(stralloc *sa,const char *s)
547 return stralloc_catb(sa,s,strlen(s));
551 /*** stralloc_eady.c ***/
553 GEN_ALLOC_ready(stralloc,char,s,len,a,i,n,x,30,stralloc_ready)
554 GEN_ALLOC_readyplus(stralloc,char,s,len,a,i,n,x,30,stralloc_readyplus)
557 /*** stralloc_opyb.c ***/
559 int stralloc_copyb(stralloc *sa,const char *s,unsigned n)
561 if (!stralloc_ready(sa,n + 1)) return 0;
564 sa->s[n] = 'Z'; /* ``offensive programming'' */
569 /*** stralloc_opys.c ***/
571 int stralloc_copys(stralloc *sa,const char *s)
573 return stralloc_copyb(sa,s,strlen(s));
577 /*** stralloc_pend.c ***/
579 GEN_ALLOC_append(stralloc,char,s,len,a,i,n,x,30,stralloc_readyplus,stralloc_append)
581 #endif /* stralloc */
585 void iopause(iopause_fd *x,unsigned len,struct taia *deadline,struct taia *stamp)
592 if (taia_less(deadline,stamp))
596 taia_sub(&t,deadline,&t);
598 if (d > 1000.0) d = 1000.0;
599 millisecs = d * 1000.0 + 20.0;
602 for (i = 0;i < len;++i)
605 poll(x,len,millisecs);
606 /* XXX: some kernels apparently need x[0] even if len is 0 */
607 /* XXX: how to handle EAGAIN? are kernels really this dumb? */
608 /* XXX: how to handle EINVAL? when exactly can this happen? */
616 return flock(fd,LOCK_EX);
620 /*** lock_exnb.c ***/
622 int lock_exnb(int fd)
624 return flock(fd,LOCK_EX | LOCK_NB);
628 /*** ndelay_off.c ***/
630 int ndelay_off(int fd)
632 return fcntl(fd,F_SETFL,fcntl(fd,F_GETFL,0) & ~O_NONBLOCK);
636 /*** ndelay_on.c ***/
638 int ndelay_on(int fd)
640 return fcntl(fd,F_SETFL,fcntl(fd,F_GETFL,0) | O_NONBLOCK);
644 /*** open_append.c ***/
646 int open_append(const char *fn)
648 return open(fn, O_WRONLY|O_NDELAY|O_APPEND|O_CREAT, 0600);
652 /*** open_read.c ***/
654 int open_read(const char *fn)
656 return open(fn, O_RDONLY|O_NDELAY);
660 /*** open_trunc.c ***/
662 int open_trunc(const char *fn)
664 return open(fn,O_WRONLY | O_NDELAY | O_TRUNC | O_CREAT,0644);
668 /*** open_write.c ***/
670 int open_write(const char *fn)
672 return open(fn, O_WRONLY|O_NDELAY);
676 /*** openreadclose.c ***/
678 int openreadclose(const char *fn,stralloc *sa,unsigned bufsize)
683 if (errno == ENOENT) return 0;
686 if (readclose(fd,sa,bufsize) == -1) return -1;
692 /*** pathexec_env.c ***/
694 static stralloc plus;
697 int pathexec_env(const char *s,const char *t)
700 if (!stralloc_copys(&tmp,s)) return 0;
702 if (!stralloc_cats(&tmp,"=")) return 0;
703 if (!stralloc_cats(&tmp,t)) return 0;
705 if (!stralloc_0(&tmp)) return 0;
706 return stralloc_cat(&plus,&tmp);
709 void pathexec(char **argv)
718 if (!stralloc_cats(&plus,"")) return;
721 for (i = 0;environ[i];++i)
723 for (i = 0;i < plus.len;++i)
727 e = malloc((elen + 1) * sizeof(char *));
731 for (i = 0;environ[i];++i)
732 e[elen++] = environ[i];
735 for (i = 0;i < plus.len;++i)
737 split = str_chr(plus.s + j,'=');
738 for (t = 0;t < elen;++t)
739 if (memcmp(plus.s + j,e[t],split) == 0)
740 if (e[t][split] == '=') {
745 if (plus.s[j + split])
746 e[elen++] = plus.s + j;
751 pathexec_run(*argv,argv,e);
756 /*** pathexec_run.c ***/
760 void pathexec_run(const char *file,char *const *argv,char *const *envp)
766 if (file[str_chr(file,'/')]) {
767 execve(file,argv,envp);
771 path = getenv("PATH");
772 if (!path) path = "/bin:/usr/bin";
776 split = str_chr(path,':');
777 if (!stralloc_copyb(&tmp,path,split)) return;
779 if (!stralloc_cats(&tmp,".")) return;
780 if (!stralloc_cats(&tmp,"/")) return;
781 if (!stralloc_cats(&tmp,file)) return;
782 if (!stralloc_0(&tmp)) return;
784 execve(tmp.s,argv,envp);
785 if (errno != ENOENT) {
787 if ((errno != EACCES) && (errno != EPERM) && (errno != EISDIR)) return;
791 if (savederrno) errno = savederrno;
802 unsigned pmatch(const char *p, const char *s, unsigned len) {
808 if (!(c = *p)) return 1;
816 if ((c = *p++) != *s) return 0;
826 if (*s != '?') return 0;
834 if (*s != c) return 0;
845 int prot_gid(int gid)
848 if (setgroups(1,&x) == -1) return -1;
849 return setgid(gid); /* _should_ be redundant, but on some systems it isn't */
852 int prot_uid(int uid)
858 /*** readclose.c ***/
860 int readclose_append(int fd,stralloc *sa,unsigned bufsize)
864 if (!stralloc_readyplus(sa,bufsize)) { close(fd); return -1; }
865 r = read(fd,sa->s + sa->len,bufsize);
866 if (r == -1) if (errno == EINTR) continue;
867 if (r <= 0) { close(fd); return r; }
872 int readclose(int fd,stralloc *sa,unsigned bufsize)
874 if (!stralloc_copys(sa,"")) { close(fd); return -1; }
875 return readclose_append(fd,sa,bufsize);
879 /*** scan_ulong.c ***/
881 unsigned scan_ulong(const char *s,unsigned long *u)
884 unsigned long result = 0;
886 while ((c = (unsigned long) (unsigned char) (s[pos] - '0')) < 10) {
887 result = result * 10 + c;
897 int seek_set(int fd,seek_pos pos)
899 if (lseek(fd,(off_t) pos,SEEK_SET) == -1) return -1; return 0;
905 int sig_alarm = SIGALRM;
906 int sig_child = SIGCHLD;
907 int sig_cont = SIGCONT;
908 int sig_hangup = SIGHUP;
909 int sig_int = SIGINT;
910 int sig_pipe = SIGPIPE;
911 int sig_term = SIGTERM;
913 void (*sig_defaulthandler)(int) = SIG_DFL;
914 void (*sig_ignorehandler)(int) = SIG_IGN;
917 /*** sig_block.c ***/
919 void sig_block(int sig)
924 sigprocmask(SIG_BLOCK,&ss,(sigset_t *) 0);
927 void sig_unblock(int sig)
932 sigprocmask(SIG_UNBLOCK,&ss,(sigset_t *) 0);
935 void sig_blocknone(void)
939 sigprocmask(SIG_SETMASK,&ss,(sigset_t *) 0);
943 /*** sig_catch.c ***/
945 void sig_catch(int sig,void (*f)(int))
950 sigemptyset(&sa.sa_mask);
951 sigaction(sig,&sa,(struct sigaction *) 0);
955 /*** sig_pause.c ***/
967 unsigned str_chr(const char *s,int c)
975 if (!*t) break; if (*t == ch) break; ++t;
976 if (!*t) break; if (*t == ch) break; ++t;
977 if (!*t) break; if (*t == ch) break; ++t;
978 if (!*t) break; if (*t == ch) break; ++t;
984 /*** wait_nohang.c ***/
986 int wait_nohang(int *wstat)
988 return waitpid(-1,wstat,WNOHANG);
994 int wait_pid(int *wstat, int pid)
999 r = waitpid(pid,wstat,0);
1000 while ((r == -1) && (errno == EINTR));