Magellan Linux

Diff of /trunk/mkinitrd-magellan/busybox/runit/runit_lib.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 532 by niro, Sat Sep 1 22:45:15 2007 UTC revision 816 by niro, Fri Apr 24 18:33:46 2009 UTC
# Line 25  OTHERWISE) ARISING IN ANY WAY OUT OF THE Line 25  OTHERWISE) ARISING IN ANY WAY OUT OF THE
25  ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */  */
27    
28  /* Busyboxed by Denis Vlasenko <vda.linux@googlemail.com> */  /* Busyboxed by Denys Vlasenko <vda.linux@googlemail.com> */
29  /* Collected into one file from runit's many tiny files */  /* Collected into one file from runit's many tiny files */
30  /* TODO: review, eliminate unneeded stuff, move good stuff to libbb */  /* TODO: review, eliminate unneeded stuff, move good stuff to libbb */
31    
# Line 34  ADVISED OF THE POSSIBILITY OF SUCH DAMAG Line 34  ADVISED OF THE POSSIBILITY OF SUCH DAMAG
34  #include "libbb.h"  #include "libbb.h"
35  #include "runit_lib.h"  #include "runit_lib.h"
36    
 /*** buffer.c ***/  
   
 void buffer_init(buffer *s,int (*op)(int fd,char *buf,unsigned len),int fd,char *buf,unsigned len)  
 {  
  s->x = buf;  
  s->fd = fd;  
  s->op = op;  
  s->p = 0;  
  s->n = len;  
 }  
   
   
 /*** buffer_get.c ***/  
   
 static int oneread(int (*op)(int fd,char *buf,unsigned len),int fd,char *buf,unsigned len)  
 {  
  int r;  
   
  for (;;) {  
  r = op(fd,buf,len);  
  if (r == -1) if (errno == EINTR) continue;  
  return r;  
  }  
 }  
   
 static int getthis(buffer *s,char *buf,unsigned len)  
 {  
  if (len > s->p) len = s->p;  
  s->p -= len;  
  memcpy(buf,s->x + s->n,len);  
  s->n += len;  
  return len;  
 }  
   
 int buffer_feed(buffer *s)  
 {  
  int r;  
   
  if (s->p) return s->p;  
  r = oneread(s->op,s->fd,s->x,s->n);  
  if (r <= 0) return r;  
  s->p = r;  
  s->n -= r;  
  if (s->n > 0) memmove(s->x + s->n,s->x,r);  
  return r;  
 }  
   
 int buffer_bget(buffer *s,char *buf,unsigned len)  
 {  
  int r;  
   
  if (s->p > 0) return getthis(s,buf,len);  
  if (s->n <= len) return oneread(s->op,s->fd,buf,s->n);  
  r = buffer_feed(s); if (r <= 0) return r;  
  return getthis(s,buf,len);  
 }  
   
 int buffer_get(buffer *s,char *buf,unsigned len)  
 {  
  int r;  
   
  if (s->p > 0) return getthis(s,buf,len);  
  if (s->n <= len) return oneread(s->op,s->fd,buf,len);  
  r = buffer_feed(s); if (r <= 0) return r;  
  return getthis(s,buf,len);  
 }  
   
 char *buffer_peek(buffer *s)  
 {  
  return s->x + s->n;  
 }  
   
 void buffer_seek(buffer *s,unsigned len)  
 {  
  s->n += len;  
  s->p -= len;  
 }  
   
   
 /*** buffer_put.c ***/  
   
 static int allwrite(int (*op)(int fd,char *buf,unsigned len),int fd,const char *buf,unsigned len)  
 {  
  int w;  
   
  while (len) {  
  w = op(fd,(char*)buf,len);  
  if (w == -1) {  
  if (errno == EINTR) continue;  
  return -1; /* note that some data may have been written */  
  }  
  if (w == 0) ; /* luser's fault */  
  buf += w;  
  len -= w;  
  }  
  return 0;  
 }  
   
 int buffer_flush(buffer *s)  
 {  
  int p;  
   
  p = s->p;  
  if (!p) return 0;  
  s->p = 0;  
  return allwrite(s->op,s->fd,s->x,p);  
 }  
   
 int buffer_putalign(buffer *s,const char *buf,unsigned len)  
 {  
  unsigned n;  
   
  while (len > (n = s->n - s->p)) {  
  memcpy(s->x + s->p,buf,n);  
  s->p += n;  
  buf += n;  
  len -= n;  
  if (buffer_flush(s) == -1) return -1;  
  }  
  /* now len <= s->n - s->p */  
  memcpy(s->x + s->p,buf,len);  
  s->p += len;  
  return 0;  
 }  
   
 int buffer_put(buffer *s,const char *buf,unsigned len)  
 {  
  unsigned n;  
   
  n = s->n;  
  if (len > n - s->p) {  
  if (buffer_flush(s) == -1) return -1;  
  /* now s->p == 0 */  
  if (n < BUFFER_OUTSIZE) n = BUFFER_OUTSIZE;  
  while (len > s->n) {  
  if (n > len) n = len;  
  if (allwrite(s->op,s->fd,buf,n) == -1) return -1;  
  buf += n;  
  len -= n;  
  }  
  }  
  /* now len <= s->n - s->p */  
  memcpy(s->x + s->p,buf,len);  
  s->p += len;  
  return 0;  
 }  
   
 int buffer_putflush(buffer *s,const char *buf,unsigned len)  
 {  
  if (buffer_flush(s) == -1) return -1;  
  return allwrite(s->op,s->fd,buf,len);  
 }  
   
 int buffer_putsalign(buffer *s,const char *buf)  
 {  
  return buffer_putalign(s,buf,strlen(buf));  
 }  
   
 int buffer_puts(buffer *s,const char *buf)  
 {  
  return buffer_put(s,buf,strlen(buf));  
 }  
   
 int buffer_putsflush(buffer *s,const char *buf)  
 {  
  return buffer_putflush(s,buf,strlen(buf));  
 }  
   
   
 /*** buffer_read.c ***/  
   
 int buffer_unixread(int fd,char *buf,unsigned len)  
 {  
  return read(fd,buf,len);  
 }  
   
   
 /*** buffer_write.c ***/  
   
 int buffer_unixwrite(int fd,char *buf,unsigned len)  
 {  
  return write(fd,buf,len);  
 }  
   
   
 /*** byte_chr.c ***/  
   
37  unsigned byte_chr(char *s,unsigned n,int c)  unsigned byte_chr(char *s,unsigned n,int c)
38  {  {
39   char ch;   char ch;
# Line 229  unsigned byte_chr(char *s,unsigned n,int Line 42  unsigned byte_chr(char *s,unsigned n,int
42   ch = c;   ch = c;
43   t = s;   t = s;
44   for (;;) {   for (;;) {
45   if (!n) break; if (*t == ch) break; ++t; --n;   if (!n) break;
46   if (!n) break; if (*t == ch) break; ++t; --n;   if (*t == ch) break;
47   if (!n) break; if (*t == ch) break; ++t; --n;   ++t;
48   if (!n) break; if (*t == ch) break; ++t; --n;   --n;
49   }   }
50   return t - s;   return t - s;
51  }  }
52    
53    #ifdef UNUSED
54  /*** coe.c ***/  static /* as it isn't used anywhere else */
55    void tai_pack(char *s, const struct tai *t)
 int coe(int fd)  
 {  
  return fcntl(fd,F_SETFD,FD_CLOEXEC);  
 }  
   
   
 /*** fd_copy.c ***/  
   
 int fd_copy(int to,int from)  
 {  
  if (to == from) return 0;  
  if (fcntl(from,F_GETFL,0) == -1) return -1;  
  close(to);  
  if (fcntl(from,F_DUPFD,to) == -1) return -1;  
  return 0;  
 }  
   
   
 /*** fd_move.c ***/  
   
 int fd_move(int to,int from)  
 {  
  if (to == from) return 0;  
  if (fd_copy(to,from) == -1) return -1;  
  close(from);  
  return 0;  
 }  
   
   
 /*** fifo.c ***/  
   
 int fifo_make(const char *fn,int mode) { return mkfifo(fn,mode); }  
   
   
 /*** fmt_ptime.c ***/  
   
 unsigned fmt_ptime(char *s, struct taia *ta) {  
  struct tm *t;  
  unsigned long u;  
   
  if (ta->sec.x < 4611686018427387914ULL) return 0; /* impossible? */  
  u = ta->sec.x -4611686018427387914ULL;  
  if (!(t = gmtime((time_t*)&u))) return 0;  
  fmt_ulong(s, 1900 + t->tm_year);  
  s[4] = '-'; fmt_uint0(&s[5], t->tm_mon+1, 2);  
  s[7] = '-'; fmt_uint0(&s[8], t->tm_mday, 2);  
  s[10] = '_'; fmt_uint0(&s[11], t->tm_hour, 2);  
  s[13] = ':'; fmt_uint0(&s[14], t->tm_min, 2);  
  s[16] = ':'; fmt_uint0(&s[17], t->tm_sec, 2);  
  s[19] = '.'; fmt_uint0(&s[20], ta->nano, 9);  
  return 25;  
 }  
   
 unsigned fmt_taia(char *s, struct taia *t) {  
  static char pack[TAIA_PACK];  
   
  taia_pack(pack, t);  
  *s++ = '@';  
  bin2hex(s, pack, 12);  
  return 25;  
 }  
   
   
 /*** fmt_uint.c ***/  
   
 unsigned fmt_uint(char *s,unsigned u)  
 {  
  return fmt_ulong(s,u);  
 }  
   
   
 /*** fmt_uint0.c ***/  
   
 unsigned fmt_uint0(char *s,unsigned u,unsigned n)  
 {  
  unsigned len;  
  len = fmt_uint(FMT_LEN,u);  
  while (len < n) { if (s) *s++ = '0'; ++len; }  
  if (s) fmt_uint(s,u);  
  return len;  
 }  
   
   
 /*** fmt_ulong.c ***/  
   
 unsigned fmt_ulong(char *s,unsigned long u)  
 {  
  unsigned len; unsigned long q;  
  len = 1; q = u;  
  while (q > 9) { ++len; q /= 10; }  
  if (s) {  
  s += len;  
  do { *--s = '0' + (u % 10); u /= 10; } while (u); /* handles u == 0 */  
  }  
  return len;  
 }  
   
   
 /*** tai_now.c ***/  
   
 void tai_now(struct tai *t)  
 {  
  tai_unix(t,time((time_t *) 0));  
 }  
   
   
 /*** tai_pack.c ***/  
   
 void tai_pack(char *s,const struct tai *t)  
56  {  {
57   uint64_t x;   uint64_t x;
58    
# Line 363  void tai_pack(char *s,const struct tai * Line 67  void tai_pack(char *s,const struct tai *
67   s[0] = x;   s[0] = x;
68  }  }
69    
   
 /*** tai_sub.c ***/  
   
 void tai_sub(struct tai *t,const struct tai *u,const struct tai *v)  
 {  
  t->x = u->x - v->x;  
 }  
   
   
 /*** tai_unpack.c ***/  
   
70  void tai_unpack(const char *s,struct tai *t)  void tai_unpack(const char *s,struct tai *t)
71  {  {
72   uint64_t x;   uint64_t x;
# Line 390  void tai_unpack(const char *s,struct tai Line 83  void tai_unpack(const char *s,struct tai
83  }  }
84    
85    
 /*** taia_add.c ***/  
   
 /* XXX: breaks tai encapsulation */  
   
86  void taia_add(struct taia *t,const struct taia *u,const struct taia *v)  void taia_add(struct taia *t,const struct taia *u,const struct taia *v)
87  {  {
88   t->sec.x = u->sec.x + v->sec.x;   t->sec.x = u->sec.x + v->sec.x;
# Line 409  void taia_add(struct taia *t,const struc Line 98  void taia_add(struct taia *t,const struc
98   }   }
99  }  }
100    
101    int taia_less(const struct taia *t, const struct taia *u)
 /*** taia_approx.c ***/  
   
 double taia_approx(const struct taia *t)  
 {  
  return tai_approx(&t->sec) + taia_frac(t);  
 }  
   
   
 /*** taia_frac.c ***/  
   
 double taia_frac(const struct taia *t)  
 {  
  return (t->atto * 0.000000001 + t->nano) * 0.000000001;  
 }  
   
   
 /*** taia_less.c ***/  
   
 /* XXX: breaks tai encapsulation */  
   
 int taia_less(const struct taia *t,const struct taia *u)  
102  {  {
103   if (t->sec.x < u->sec.x) return 1;   if (t->sec.x < u->sec.x) return 1;
104   if (t->sec.x > u->sec.x) return 0;   if (t->sec.x > u->sec.x) return 0;
# Line 439  int taia_less(const struct taia *t,const Line 107  int taia_less(const struct taia *t,const
107   return t->atto < u->atto;   return t->atto < u->atto;
108  }  }
109    
   
 /*** taia_now.c ***/  
   
110  void taia_now(struct taia *t)  void taia_now(struct taia *t)
111  {  {
112   struct timeval now;   struct timeval now;
113   gettimeofday(&now,(struct timezone *) 0);   gettimeofday(&now, NULL);
114   tai_unix(&t->sec,now.tv_sec);   tai_unix(&t->sec, now.tv_sec);
115   t->nano = 1000 * now.tv_usec + 500;   t->nano = 1000 * now.tv_usec + 500;
116   t->atto = 0;   t->atto = 0;
117  }  }
118    
119    /* UNUSED
120  /*** taia_pack.c ***/  void taia_pack(char *s, const struct taia *t)
   
 void taia_pack(char *s,const struct taia *t)  
121  {  {
122   unsigned long x;   unsigned long x;
123    
124   tai_pack(s,&t->sec);   tai_pack(s, &t->sec);
125   s += 8;   s += 8;
126    
127   x = t->atto;   x = t->atto;
# Line 472  void taia_pack(char *s,const struct taia Line 135  void taia_pack(char *s,const struct taia
135   s[1] = x & 255; x >>= 8;   s[1] = x & 255; x >>= 8;
136   s[0] = x;   s[0] = x;
137  }  }
138    */
139    
140    void taia_sub(struct taia *t, const struct taia *u, const struct taia *v)
 /*** taia_sub.c ***/  
   
 /* XXX: breaks tai encapsulation */  
   
 void taia_sub(struct taia *t,const struct taia *u,const struct taia *v)  
141  {  {
142   unsigned long unano = u->nano;   unsigned long unano = u->nano;
143   unsigned long uatto = u->atto;   unsigned long uatto = u->atto;
# Line 496  void taia_sub(struct taia *t,const struc Line 155  void taia_sub(struct taia *t,const struc
155   }   }
156  }  }
157    
   
 /*** taia_uint.c ***/  
   
158  /* XXX: breaks tai encapsulation */  /* XXX: breaks tai encapsulation */
159    void taia_uint(struct taia *t, unsigned s)
 void taia_uint(struct taia *t,unsigned s)  
160  {  {
161   t->sec.x = s;   t->sec.x = s;
162   t->nano = 0;   t->nano = 0;
163   t->atto = 0;   t->atto = 0;
164  }  }
165    
166    static
167  /*** stralloc_cat.c ***/  uint64_t taia2millisec(const struct taia *t)
 #if 0  
   
 int stralloc_cat(stralloc *sato,const stralloc *safrom)  
 {  
  return stralloc_catb(sato,safrom->s,safrom->len);  
 }  
   
   
 /*** stralloc_catb.c ***/  
   
 int stralloc_catb(stralloc *sa,const char *s,unsigned n)  
 {  
  if (!sa->s) return stralloc_copyb(sa,s,n);  
  if (!stralloc_readyplus(sa,n + 1)) return 0;  
  memcpy(sa->s + sa->len,s,n);  
  sa->len += n;  
  sa->s[sa->len] = 'Z'; /* ``offensive programming'' */  
  return 1;  
 }  
   
   
 /*** stralloc_cats.c ***/  
   
 int stralloc_cats(stralloc *sa,const char *s)  
 {  
  return stralloc_catb(sa,s,strlen(s));  
 }  
   
   
 /*** stralloc_eady.c ***/  
   
 GEN_ALLOC_ready(stralloc,char,s,len,a,i,n,x,30,stralloc_ready)  
 GEN_ALLOC_readyplus(stralloc,char,s,len,a,i,n,x,30,stralloc_readyplus)  
   
   
 /*** stralloc_opyb.c ***/  
   
 int stralloc_copyb(stralloc *sa,const char *s,unsigned n)  
168  {  {
169   if (!stralloc_ready(sa,n + 1)) return 0;   return (t->sec.x * 1000) + (t->nano / 1000000);
  memcpy(sa->s,s,n);  
  sa->len = n;  
  sa->s[n] = 'Z'; /* ``offensive programming'' */  
  return 1;  
170  }  }
171    
172    void iopause(iopause_fd *x, unsigned len, struct taia *deadline, struct taia *stamp)
 /*** stralloc_opys.c ***/  
   
 int stralloc_copys(stralloc *sa,const char *s)  
173  {  {
  return stralloc_copyb(sa,s,strlen(s));  
 }  
   
   
 /*** stralloc_pend.c ***/  
   
 GEN_ALLOC_append(stralloc,char,s,len,a,i,n,x,30,stralloc_readyplus,stralloc_append)  
   
 #endif /* stralloc */  
   
 /*** iopause.c ***/  
   
 void iopause(iopause_fd *x,unsigned len,struct taia *deadline,struct taia *stamp)  
 {  
  struct taia t;  
174   int millisecs;   int millisecs;
  double d;  
175   int i;   int i;
176    
177   if (taia_less(deadline,stamp))   if (taia_less(deadline, stamp))
178   millisecs = 0;   millisecs = 0;
179   else {   else {
180     uint64_t m;
181     struct taia t;
182   t = *stamp;   t = *stamp;
183   taia_sub(&t,deadline,&t);   taia_sub(&t, deadline, &t);
184   d = taia_approx(&t);   millisecs = m = taia2millisec(&t);
185   if (d > 1000.0) d = 1000.0;   if (m > 1000) millisecs = 1000;
186   millisecs = d * 1000.0 + 20.0;   millisecs += 20;
187   }   }
188    
189   for (i = 0;i < len;++i)   for (i = 0; i < len; ++i)
190   x[i].revents = 0;   x[i].revents = 0;
191    
192   poll(x,len,millisecs);   poll(x, len, millisecs);
193   /* XXX: some kernels apparently need x[0] even if len is 0 */   /* XXX: some kernels apparently need x[0] even if len is 0 */
194   /* XXX: how to handle EAGAIN? are kernels really this dumb? */   /* XXX: how to handle EAGAIN? are kernels really this dumb? */
195   /* XXX: how to handle EINVAL? when exactly can this happen? */   /* XXX: how to handle EINVAL? when exactly can this happen? */
196  }  }
197    #endif
   
 /*** lock_ex.c ***/  
198    
199  int lock_ex(int fd)  int lock_ex(int fd)
200  {  {
201   return flock(fd,LOCK_EX);   return flock(fd,LOCK_EX);
202  }  }
203    
   
 /*** lock_exnb.c ***/  
   
204  int lock_exnb(int fd)  int lock_exnb(int fd)
205  {  {
206   return flock(fd,LOCK_EX | LOCK_NB);   return flock(fd,LOCK_EX | LOCK_NB);
207  }  }
208    
   
 /*** open_append.c ***/  
   
209  int open_append(const char *fn)  int open_append(const char *fn)
210  {  {
211   return open(fn, O_WRONLY|O_NDELAY|O_APPEND|O_CREAT, 0600);   return open(fn, O_WRONLY|O_NDELAY|O_APPEND|O_CREAT, 0600);
212  }  }
213    
   
 /*** open_read.c ***/  
   
214  int open_read(const char *fn)  int open_read(const char *fn)
215  {  {
216   return open(fn, O_RDONLY|O_NDELAY);   return open(fn, O_RDONLY|O_NDELAY);
217  }  }
218    
   
 /*** open_trunc.c ***/  
   
219  int open_trunc(const char *fn)  int open_trunc(const char *fn)
220  {  {
221   return open(fn,O_WRONLY | O_NDELAY | O_TRUNC | O_CREAT,0644);   return open(fn,O_WRONLY | O_NDELAY | O_TRUNC | O_CREAT,0644);
222  }  }
223    
   
 /*** open_write.c ***/  
   
224  int open_write(const char *fn)  int open_write(const char *fn)
225  {  {
226   return open(fn, O_WRONLY|O_NDELAY);   return open(fn, O_WRONLY|O_NDELAY);
227  }  }
228    
229    unsigned pmatch(const char *p, const char *s, unsigned len)
 /*** openreadclose.c ***/  
 #if 0  
 int openreadclose(const char *fn,stralloc *sa,unsigned bufsize)  
 {  
  int fd;  
  fd = open_read(fn);  
  if (fd == -1) {  
  if (errno == ENOENT) return 0;  
  return -1;  
  }  
  if (readclose(fd,sa,bufsize) == -1) return -1;  
  return 1;  
 }  
 #endif  
   
   
 /*** pathexec_env.c ***/  
 #if 0  
 static stralloc plus;  
 static stralloc tmp;  
   
 int pathexec_env(const char *s,const char *t)  
 {  
  if (!s) return 1;  
  if (!stralloc_copys(&tmp,s)) return 0;  
  if (t) {  
  if (!stralloc_cats(&tmp,"=")) return 0;  
  if (!stralloc_cats(&tmp,t)) return 0;  
  }  
  if (!stralloc_0(&tmp)) return 0;  
  return stralloc_cat(&plus,&tmp);  
 }  
   
 void pathexec(char **argv)  
230  {  {
  char **e;  
  unsigned elen;  
  unsigned i;  
  unsigned j;  
  unsigned split;  
  unsigned t;  
   
  if (!stralloc_cats(&plus,"")) return;  
   
  elen = 0;  
  for (i = 0;environ[i];++i)  
  ++elen;  
  for (i = 0;i < plus.len;++i)  
  if (!plus.s[i])  
  ++elen;  
   
  e = malloc((elen + 1) * sizeof(char *));  
  if (!e) return;  
   
  elen = 0;  
  for (i = 0;environ[i];++i)  
  e[elen++] = environ[i];  
   
  j = 0;  
  for (i = 0;i < plus.len;++i)  
  if (!plus.s[i]) {  
  split = str_chr(plus.s + j,'=');  
  for (t = 0;t < elen;++t)  
  if (memcmp(plus.s + j,e[t],split) == 0)  
  if (e[t][split] == '=') {  
  --elen;  
  e[t] = e[elen];  
  break;  
  }  
  if (plus.s[j + split])  
  e[elen++] = plus.s + j;  
  j = i + 1;  
  }  
  e[elen] = 0;  
   
  pathexec_run(*argv,argv,e);  
  free(e);  
 }  
 #endif  
   
 /*** pathexec_run.c ***/  
 #if 0  
 static stralloc tmp;  
   
 void pathexec_run(const char *file,char *const *argv,char *const *envp)  
 {  
  const char *path;  
  unsigned split;  
  int savederrno;  
   
  if (file[str_chr(file,'/')]) {  
  execve(file,argv,envp);  
  return;  
  }  
   
  path = getenv("PATH");  
  if (!path) path = "/bin:/usr/bin";  
   
  savederrno = 0;  
  for (;;) {  
  split = str_chr(path,':');  
  if (!stralloc_copyb(&tmp,path,split)) return;  
  if (!split)  
  if (!stralloc_cats(&tmp,".")) return;  
  if (!stralloc_cats(&tmp,"/"))  return;  
  if (!stralloc_cats(&tmp,file)) return;  
  if (!stralloc_0(&tmp)) return;  
   
  execve(tmp.s,argv,envp);  
  if (errno != ENOENT) {  
  savederrno = errno;  
  if ((errno != EACCES) && (errno != EPERM) && (errno != EISDIR)) return;  
  }  
   
  if (!path[split]) {  
  if (savederrno) errno = savederrno;  
  return;  
  }  
  path += split;  
  path += 1;  
  }  
 }  
 #endif  
   
 /*** pmatch.c ***/  
   
 unsigned pmatch(const char *p, const char *s, unsigned len) {  
231   for (;;) {   for (;;) {
232   char c = *p++;   char c = *p++;
233   if (!c) return !len;   if (!c) return !len;
234   switch (c) {   switch (c) {
235   case '*':   case '*':
236   if (!(c = *p)) return 1;   c = *p;
237     if (!c) return 1;
238   for (;;) {   for (;;) {
239   if (!len) return 0;   if (!len) return 0;
240   if (*s == c) break;   if (*s == c) break;
241   ++s; --len;   ++s;
242     --len;
243   }   }
244   continue;   continue;
245   case '+':   case '+':
246   if ((c = *p++) != *s) return 0;   c = *p++;
247     if (c != *s) return 0;
248   for (;;) {   for (;;) {
249   if (!len) return 1;   if (!len) return 1;
250   if (*s != c) break;   if (*s != c) break;
251   ++s; --len;   ++s;
252     --len;
253   }   }
254   continue;   continue;
255   /*   /*
# Line 807  unsigned pmatch(const char *p, const cha Line 264  unsigned pmatch(const char *p, const cha
264   default:   default:
265   if (!len) return 0;   if (!len) return 0;
266   if (*s != c) return 0;   if (*s != c) return 0;
267   ++s; --len;   ++s;
268     --len;
269   continue;   continue;
270   }   }
271   }   }
272   return 0;   return 0;
273  }  }
   
   
 /*** prot.c ***/  
   
 int prot_gid(int gid)  
 {  
  gid_t x = gid;  
  if (setgroups(1,&x) == -1) return -1;  
  return setgid(gid); /* _should_ be redundant, but on some systems it isn't */  
 }  
   
 int prot_uid(int uid)  
 {  
  return setuid(uid);  
 }  
   
   
 /*** readclose.c ***/  
 #if 0  
 int readclose_append(int fd,stralloc *sa,unsigned bufsize)  
 {  
  int r;  
  for (;;) {  
  if (!stralloc_readyplus(sa,bufsize)) { close(fd); return -1; }  
  r = read(fd,sa->s + sa->len,bufsize);  
  if (r == -1) if (errno == EINTR) continue;  
  if (r <= 0) { close(fd); return r; }  
  sa->len += r;  
  }  
 }  
   
 int readclose(int fd,stralloc *sa,unsigned bufsize)  
 {  
  if (!stralloc_copys(sa,"")) { close(fd); return -1; }  
  return readclose_append(fd,sa,bufsize);  
 }  
 #endif  
   
 /*** scan_ulong.c ***/  
   
 unsigned scan_ulong(const char *s,unsigned long *u)  
 {  
  unsigned pos = 0;  
  unsigned long result = 0;  
  unsigned long c;  
  while ((c = (unsigned long) (unsigned char) (s[pos] - '0')) < 10) {  
  result = result * 10 + c;  
  ++pos;  
  }  
  *u = result;  
  return pos;  
 }  
   
   
 /*** seek_set.c ***/  
   
 int seek_set(int fd,seek_pos pos)  
 {  
  if (lseek(fd,(off_t) pos,SEEK_SET) == -1) return -1; return 0;  
 }  
   
   
 /*** sig.c ***/  
   
 int sig_alarm = SIGALRM;  
 int sig_child = SIGCHLD;  
 int sig_cont = SIGCONT;  
 int sig_hangup = SIGHUP;  
 int sig_int = SIGINT;  
 int sig_pipe = SIGPIPE;  
 int sig_term = SIGTERM;  
   
 void (*sig_defaulthandler)(int) = SIG_DFL;  
 void (*sig_ignorehandler)(int) = SIG_IGN;  
   
   
 /*** sig_block.c ***/  
   
 void sig_block(int sig)  
 {  
  sigset_t ss;  
  sigemptyset(&ss);  
  sigaddset(&ss,sig);  
  sigprocmask(SIG_BLOCK,&ss,(sigset_t *) 0);  
 }  
   
 void sig_unblock(int sig)  
 {  
  sigset_t ss;  
  sigemptyset(&ss);  
  sigaddset(&ss,sig);  
  sigprocmask(SIG_UNBLOCK,&ss,(sigset_t *) 0);  
 }  
   
 void sig_blocknone(void)  
 {  
  sigset_t ss;  
  sigemptyset(&ss);  
  sigprocmask(SIG_SETMASK,&ss,(sigset_t *) 0);  
 }  
   
   
 /*** sig_catch.c ***/  
   
 void sig_catch(int sig,void (*f)(int))  
 {  
  struct sigaction sa;  
  sa.sa_handler = f;  
  sa.sa_flags = 0;  
  sigemptyset(&sa.sa_mask);  
  sigaction(sig,&sa,(struct sigaction *) 0);  
 }  
   
   
 /*** sig_pause.c ***/  
   
 void sig_pause(void)  
 {  
  sigset_t ss;  
  sigemptyset(&ss);  
  sigsuspend(&ss);  
 }  
   
   
 /*** str_chr.c ***/  
   
 unsigned str_chr(const char *s,int c)  
 {  
  char ch;  
  const char *t;  
   
  ch = c;  
  t = s;  
  for (;;) {  
  if (!*t) break; if (*t == ch) break; ++t;  
  if (!*t) break; if (*t == ch) break; ++t;  
  if (!*t) break; if (*t == ch) break; ++t;  
  if (!*t) break; if (*t == ch) break; ++t;  
  }  
  return t - s;  
 }  
   
   
 /*** wait_nohang.c ***/  
   
 int wait_nohang(int *wstat)  
 {  
  return waitpid(-1,wstat,WNOHANG);  
 }  
   
   
 /*** wait_pid.c ***/  
   
 int wait_pid(int *wstat, int pid)  
 {  
  int r;  
   
  do  
  r = waitpid(pid,wstat,0);  
  while ((r == -1) && (errno == EINTR));  
  return r;  
 }  

Legend:
Removed from v.532  
changed lines
  Added in v.816