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 ***/
523 int stralloc_cat(stralloc *sato,const stralloc *safrom)
525 return stralloc_catb(sato,safrom->s,safrom->len);
529 /*** stralloc_catb.c ***/
531 int stralloc_catb(stralloc *sa,const char *s,unsigned n)
533 if (!sa->s) return stralloc_copyb(sa,s,n);
534 if (!stralloc_readyplus(sa,n + 1)) return 0;
535 memcpy(sa->s + sa->len,s,n);
537 sa->s[sa->len] = 'Z'; /* ``offensive programming'' */
542 /*** stralloc_cats.c ***/
544 int stralloc_cats(stralloc *sa,const char *s)
546 return stralloc_catb(sa,s,strlen(s));
550 /*** stralloc_eady.c ***/
552 GEN_ALLOC_ready(stralloc,char,s,len,a,i,n,x,30,stralloc_ready)
553 GEN_ALLOC_readyplus(stralloc,char,s,len,a,i,n,x,30,stralloc_readyplus)
556 /*** stralloc_opyb.c ***/
558 int stralloc_copyb(stralloc *sa,const char *s,unsigned n)
560 if (!stralloc_ready(sa,n + 1)) return 0;
563 sa->s[n] = 'Z'; /* ``offensive programming'' */
568 /*** stralloc_opys.c ***/
570 int stralloc_copys(stralloc *sa,const char *s)
572 return stralloc_copyb(sa,s,strlen(s));
576 /*** stralloc_pend.c ***/
578 GEN_ALLOC_append(stralloc,char,s,len,a,i,n,x,30,stralloc_readyplus,stralloc_append)
583 void iopause(iopause_fd *x,unsigned len,struct taia *deadline,struct taia *stamp)
590 if (taia_less(deadline,stamp))
594 taia_sub(&t,deadline,&t);
596 if (d > 1000.0) d = 1000.0;
597 millisecs = d * 1000.0 + 20.0;
600 for (i = 0;i < len;++i)
603 poll(x,len,millisecs);
604 /* XXX: some kernels apparently need x[0] even if len is 0 */
605 /* XXX: how to handle EAGAIN? are kernels really this dumb? */
606 /* XXX: how to handle EINVAL? when exactly can this happen? */
614 return flock(fd,LOCK_EX);
618 /*** lock_exnb.c ***/
620 int lock_exnb(int fd)
622 return flock(fd,LOCK_EX | LOCK_NB);
626 /*** ndelay_off.c ***/
628 int ndelay_off(int fd)
630 return fcntl(fd,F_SETFL,fcntl(fd,F_GETFL,0) & ~O_NONBLOCK);
634 /*** ndelay_on.c ***/
636 int ndelay_on(int fd)
638 return fcntl(fd,F_SETFL,fcntl(fd,F_GETFL,0) | O_NONBLOCK);
642 /*** open_append.c ***/
644 int open_append(const char *fn)
646 return open(fn,O_WRONLY | O_NDELAY | O_APPEND | O_CREAT,0600);
650 /*** open_read.c ***/
652 int open_read(const char *fn)
654 return open(fn,O_RDONLY | O_NDELAY);
658 /*** open_trunc.c ***/
660 int open_trunc(const char *fn)
662 return open(fn,O_WRONLY | O_NDELAY | O_TRUNC | O_CREAT,0644);
666 /*** open_write.c ***/
668 int open_write(const char *fn)
670 return open(fn,O_WRONLY | O_NDELAY);
674 /*** openreadclose.c ***/
676 int openreadclose(const char *fn,stralloc *sa,unsigned bufsize)
681 if (errno == ENOENT) return 0;
684 if (readclose(fd,sa,bufsize) == -1) return -1;
689 /*** pathexec_env.c ***/
691 static stralloc plus;
694 int pathexec_env(const char *s,const char *t)
697 if (!stralloc_copys(&tmp,s)) return 0;
699 if (!stralloc_cats(&tmp,"=")) return 0;
700 if (!stralloc_cats(&tmp,t)) return 0;
702 if (!stralloc_0(&tmp)) return 0;
703 return stralloc_cat(&plus,&tmp);
706 void pathexec(char **argv)
715 if (!stralloc_cats(&plus,"")) return;
718 for (i = 0;environ[i];++i)
720 for (i = 0;i < plus.len;++i)
724 e = malloc((elen + 1) * sizeof(char *));
728 for (i = 0;environ[i];++i)
729 e[elen++] = environ[i];
732 for (i = 0;i < plus.len;++i)
734 split = str_chr(plus.s + j,'=');
735 for (t = 0;t < elen;++t)
736 if (memcmp(plus.s + j,e[t],split) == 0)
737 if (e[t][split] == '=') {
742 if (plus.s[j + split])
743 e[elen++] = plus.s + j;
748 pathexec_run(*argv,argv,e);
753 /*** pathexec_run.c ***/
757 void pathexec_run(const char *file,char *const *argv,char *const *envp)
763 if (file[str_chr(file,'/')]) {
764 execve(file,argv,envp);
768 path = getenv("PATH");
769 if (!path) path = "/bin:/usr/bin";
773 split = str_chr(path,':');
774 if (!stralloc_copyb(&tmp,path,split)) return;
776 if (!stralloc_cats(&tmp,".")) return;
777 if (!stralloc_cats(&tmp,"/")) return;
778 if (!stralloc_cats(&tmp,file)) return;
779 if (!stralloc_0(&tmp)) return;
781 execve(tmp.s,argv,envp);
782 if (errno != ENOENT) {
784 if ((errno != EACCES) && (errno != EPERM) && (errno != EISDIR)) return;
788 if (savederrno) errno = savederrno;
799 unsigned pmatch(const char *p, const char *s, unsigned len) {
805 if (!(c = *p)) return 1;
813 if ((c = *p++) != *s) return 0;
823 if (*s != '?') return 0;
831 if (*s != c) return 0;
842 int prot_gid(int gid)
845 if (setgroups(1,&x) == -1) return -1;
846 return setgid(gid); /* _should_ be redundant, but on some systems it isn't */
849 int prot_uid(int uid)
855 /*** readclose.c ***/
857 int readclose_append(int fd,stralloc *sa,unsigned bufsize)
861 if (!stralloc_readyplus(sa,bufsize)) { close(fd); return -1; }
862 r = read(fd,sa->s + sa->len,bufsize);
863 if (r == -1) if (errno == EINTR) continue;
864 if (r <= 0) { close(fd); return r; }
869 int readclose(int fd,stralloc *sa,unsigned bufsize)
871 if (!stralloc_copys(sa,"")) { close(fd); return -1; }
872 return readclose_append(fd,sa,bufsize);
876 /*** scan_ulong.c ***/
878 unsigned scan_ulong(const char *s,unsigned long *u)
881 unsigned long result = 0;
883 while ((c = (unsigned long) (unsigned char) (s[pos] - '0')) < 10) {
884 result = result * 10 + c;
894 int seek_set(int fd,seek_pos pos)
896 if (lseek(fd,(off_t) pos,SEEK_SET) == -1) return -1; return 0;
902 int sig_alarm = SIGALRM;
903 int sig_child = SIGCHLD;
904 int sig_cont = SIGCONT;
905 int sig_hangup = SIGHUP;
906 int sig_int = SIGINT;
907 int sig_pipe = SIGPIPE;
908 int sig_term = SIGTERM;
910 void (*sig_defaulthandler)(int) = SIG_DFL;
911 void (*sig_ignorehandler)(int) = SIG_IGN;
914 /*** sig_block.c ***/
916 void sig_block(int sig)
921 sigprocmask(SIG_BLOCK,&ss,(sigset_t *) 0);
924 void sig_unblock(int sig)
929 sigprocmask(SIG_UNBLOCK,&ss,(sigset_t *) 0);
932 void sig_blocknone(void)
936 sigprocmask(SIG_SETMASK,&ss,(sigset_t *) 0);
940 /*** sig_catch.c ***/
942 void sig_catch(int sig,void (*f)(int))
947 sigemptyset(&sa.sa_mask);
948 sigaction(sig,&sa,(struct sigaction *) 0);
952 /*** sig_pause.c ***/
964 unsigned str_chr(const char *s,int c)
972 if (!*t) break; if (*t == ch) break; ++t;
973 if (!*t) break; if (*t == ch) break; ++t;
974 if (!*t) break; if (*t == ch) break; ++t;
975 if (!*t) break; if (*t == ch) break; ++t;
981 /*** wait_nohang.c ***/
983 int wait_nohang(int *wstat)
985 return waitpid(-1,wstat,WNOHANG);
991 int wait_pid(int *wstat, int pid)
996 r = waitpid(pid,wstat,0);
997 while ((r == -1) && (errno == EINTR));