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 hex[16] = "0123456789abcdef";
298 static char pack[TAIA_PACK];
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];
313 unsigned fmt_uint(char *s,unsigned u)
315 return fmt_ulong(s,u);
319 /*** fmt_uint0.c ***/
321 unsigned fmt_uint0(char *s,unsigned u,unsigned n)
324 len = fmt_uint(FMT_LEN,u);
325 while (len < n) { if (s) *s++ = '0'; ++len; }
326 if (s) fmt_uint(s,u);
331 /*** fmt_ulong.c ***/
333 unsigned fmt_ulong(char *s,unsigned long u)
335 unsigned len; unsigned long q;
337 while (q > 9) { ++len; q /= 10; }
340 do { *--s = '0' + (u % 10); u /= 10; } while(u); /* handles u == 0 */
348 void tai_now(struct tai *t)
350 tai_unix(t,time((time_t *) 0));
356 void tai_pack(char *s,const struct tai *t)
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;
374 void tai_sub(struct tai *t,const struct tai *u,const struct tai *v)
380 /*** tai_unpack.c ***/
382 void tai_unpack(const char *s,struct tai *t)
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];
400 /* XXX: breaks tai encapsulation */
402 void taia_add(struct taia *t,const struct taia *u,const struct taia *v)
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;
411 if (t->nano > 999999999UL) {
412 t->nano -= 1000000000UL;
418 /*** taia_approx.c ***/
420 double taia_approx(const struct taia *t)
422 return tai_approx(&t->sec) + taia_frac(t);
426 /*** taia_frac.c ***/
428 double taia_frac(const struct taia *t)
430 return (t->atto * 0.000000001 + t->nano) * 0.000000001;
434 /*** taia_less.c ***/
436 /* XXX: breaks tai encapsulation */
438 int taia_less(const struct taia *t,const struct taia *u)
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;
450 void taia_now(struct taia *t)
453 gettimeofday(&now,(struct timezone *) 0);
454 tai_unix(&t->sec,now.tv_sec);
455 t->nano = 1000 * now.tv_usec + 500;
460 /*** taia_pack.c ***/
462 void taia_pack(char *s,const struct taia *t)
470 s[7] = x & 255; x >>= 8;
471 s[6] = x & 255; x >>= 8;
472 s[5] = x & 255; x >>= 8;
475 s[3] = x & 255; x >>= 8;
476 s[2] = x & 255; x >>= 8;
477 s[1] = x & 255; x >>= 8;
484 /* XXX: breaks tai encapsulation */
486 void taia_sub(struct taia *t,const struct taia *u,const struct taia *v)
488 unsigned long unano = u->nano;
489 unsigned long uatto = u->atto;
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;
498 if (t->nano > unano) {
499 t->nano += 1000000000UL;
505 /*** taia_uint.c ***/
507 /* XXX: breaks tai encapsulation */
509 void taia_uint(struct taia *t,unsigned s)
517 /*** stralloc_cat.c ***/
520 int stralloc_cat(stralloc *sato,const stralloc *safrom)
522 return stralloc_catb(sato,safrom->s,safrom->len);
526 /*** stralloc_catb.c ***/
528 int stralloc_catb(stralloc *sa,const char *s,unsigned n)
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);
534 sa->s[sa->len] = 'Z'; /* ``offensive programming'' */
539 /*** stralloc_cats.c ***/
541 int stralloc_cats(stralloc *sa,const char *s)
543 return stralloc_catb(sa,s,strlen(s));
547 /*** stralloc_eady.c ***/
549 GEN_ALLOC_ready(stralloc,char,s,len,a,i,n,x,30,stralloc_ready)
550 GEN_ALLOC_readyplus(stralloc,char,s,len,a,i,n,x,30,stralloc_readyplus)
553 /*** stralloc_opyb.c ***/
555 int stralloc_copyb(stralloc *sa,const char *s,unsigned n)
557 if (!stralloc_ready(sa,n + 1)) return 0;
560 sa->s[n] = 'Z'; /* ``offensive programming'' */
565 /*** stralloc_opys.c ***/
567 int stralloc_copys(stralloc *sa,const char *s)
569 return stralloc_copyb(sa,s,strlen(s));
573 /*** stralloc_pend.c ***/
575 GEN_ALLOC_append(stralloc,char,s,len,a,i,n,x,30,stralloc_readyplus,stralloc_append)
577 #endif /* stralloc */
581 void iopause(iopause_fd *x,unsigned len,struct taia *deadline,struct taia *stamp)
588 if (taia_less(deadline,stamp))
592 taia_sub(&t,deadline,&t);
594 if (d > 1000.0) d = 1000.0;
595 millisecs = d * 1000.0 + 20.0;
598 for (i = 0;i < len;++i)
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? */
612 return flock(fd,LOCK_EX);
616 /*** lock_exnb.c ***/
618 int lock_exnb(int fd)
620 return flock(fd,LOCK_EX | LOCK_NB);
624 /*** open_append.c ***/
626 int open_append(const char *fn)
628 return open(fn, O_WRONLY|O_NDELAY|O_APPEND|O_CREAT, 0600);
632 /*** open_read.c ***/
634 int open_read(const char *fn)
636 return open(fn, O_RDONLY|O_NDELAY);
640 /*** open_trunc.c ***/
642 int open_trunc(const char *fn)
644 return open(fn,O_WRONLY | O_NDELAY | O_TRUNC | O_CREAT,0644);
648 /*** open_write.c ***/
650 int open_write(const char *fn)
652 return open(fn, O_WRONLY|O_NDELAY);
656 /*** openreadclose.c ***/
658 int openreadclose(const char *fn,stralloc *sa,unsigned bufsize)
663 if (errno == ENOENT) return 0;
666 if (readclose(fd,sa,bufsize) == -1) return -1;
672 /*** pathexec_env.c ***/
674 static stralloc plus;
677 int pathexec_env(const char *s,const char *t)
680 if (!stralloc_copys(&tmp,s)) return 0;
682 if (!stralloc_cats(&tmp,"=")) return 0;
683 if (!stralloc_cats(&tmp,t)) return 0;
685 if (!stralloc_0(&tmp)) return 0;
686 return stralloc_cat(&plus,&tmp);
689 void pathexec(char **argv)
698 if (!stralloc_cats(&plus,"")) return;
701 for (i = 0;environ[i];++i)
703 for (i = 0;i < plus.len;++i)
707 e = malloc((elen + 1) * sizeof(char *));
711 for (i = 0;environ[i];++i)
712 e[elen++] = environ[i];
715 for (i = 0;i < plus.len;++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] == '=') {
725 if (plus.s[j + split])
726 e[elen++] = plus.s + j;
731 pathexec_run(*argv,argv,e);
736 /*** pathexec_run.c ***/
740 void pathexec_run(const char *file,char *const *argv,char *const *envp)
746 if (file[str_chr(file,'/')]) {
747 execve(file,argv,envp);
751 path = getenv("PATH");
752 if (!path) path = "/bin:/usr/bin";
756 split = str_chr(path,':');
757 if (!stralloc_copyb(&tmp,path,split)) return;
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;
764 execve(tmp.s,argv,envp);
765 if (errno != ENOENT) {
767 if ((errno != EACCES) && (errno != EPERM) && (errno != EISDIR)) return;
771 if (savederrno) errno = savederrno;
782 unsigned pmatch(const char *p, const char *s, unsigned len) {
788 if (!(c = *p)) return 1;
796 if ((c = *p++) != *s) return 0;
806 if (*s != '?') return 0;
814 if (*s != c) return 0;
825 int prot_gid(int gid)
828 if (setgroups(1,&x) == -1) return -1;
829 return setgid(gid); /* _should_ be redundant, but on some systems it isn't */
832 int prot_uid(int uid)
838 /*** readclose.c ***/
840 int readclose_append(int fd,stralloc *sa,unsigned bufsize)
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; }
852 int readclose(int fd,stralloc *sa,unsigned bufsize)
854 if (!stralloc_copys(sa,"")) { close(fd); return -1; }
855 return readclose_append(fd,sa,bufsize);
859 /*** scan_ulong.c ***/
861 unsigned scan_ulong(const char *s,unsigned long *u)
864 unsigned long result = 0;
866 while ((c = (unsigned long) (unsigned char) (s[pos] - '0')) < 10) {
867 result = result * 10 + c;
877 int seek_set(int fd,seek_pos pos)
879 if (lseek(fd,(off_t) pos,SEEK_SET) == -1) return -1; return 0;
885 int sig_alarm = SIGALRM;
886 int sig_child = SIGCHLD;
887 int sig_cont = SIGCONT;
888 int sig_hangup = SIGHUP;
889 int sig_int = SIGINT;
890 int sig_pipe = SIGPIPE;
891 int sig_term = SIGTERM;
893 void (*sig_defaulthandler)(int) = SIG_DFL;
894 void (*sig_ignorehandler)(int) = SIG_IGN;
897 /*** sig_block.c ***/
899 void sig_block(int sig)
904 sigprocmask(SIG_BLOCK,&ss,(sigset_t *) 0);
907 void sig_unblock(int sig)
912 sigprocmask(SIG_UNBLOCK,&ss,(sigset_t *) 0);
915 void sig_blocknone(void)
919 sigprocmask(SIG_SETMASK,&ss,(sigset_t *) 0);
923 /*** sig_catch.c ***/
925 void sig_catch(int sig,void (*f)(int))
930 sigemptyset(&sa.sa_mask);
931 sigaction(sig,&sa,(struct sigaction *) 0);
935 /*** sig_pause.c ***/
947 unsigned str_chr(const char *s,int c)
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;
964 /*** wait_nohang.c ***/
966 int wait_nohang(int *wstat)
968 return waitpid(-1,wstat,WNOHANG);
974 int wait_pid(int *wstat, int pid)
979 r = waitpid(pid,wstat,0);
980 while ((r == -1) && (errno == EINTR));