int dns_ip6_qualify_rules(stralloc *out,stralloc *fqdn,const stralloc *in,const stralloc *rules) { unsigned int i; unsigned int j; unsigned int plus; unsigned int fqdnlen; if (!stralloc_copy(fqdn,in)) return -1; for (j = i = 0;j < rules->len;++j) if (!rules->s[j]) { if (!doit(fqdn,rules->s + i)) return -1; i = j + 1; } fqdnlen = fqdn->len; plus = byte_chr(fqdn->s,fqdnlen,'+'); if (plus >= fqdnlen) return dns_ip6(out,fqdn); i = plus + 1; for (;;) { j = byte_chr(fqdn->s + i,fqdnlen - i,'+'); byte_copy(fqdn->s + plus,j,fqdn->s + i); fqdn->len = plus + j; if (dns_ip6(out,fqdn) == -1) return -1; if (out->len) return 0; i += j; if (i >= fqdnlen) return 0; ++i; } }
static int doit(stralloc *work,const char *rule) { char ch; unsigned int colon; unsigned int prefixlen; ch = *rule++; if ((ch != '?') && (ch != '=') && (ch != '*') && (ch != '-')) return 1; colon = str_chr(rule,':'); if (!rule[colon]) return 1; if (work->len < colon) return 1; prefixlen = work->len - colon; if ((ch == '=') && prefixlen) return 1; if (case_diffb(rule,colon,work->s + prefixlen)) return 1; if (ch == '?') { if (byte_chr(work->s,prefixlen,'.') < prefixlen) return 1; if (byte_chr(work->s,prefixlen,':') < prefixlen) return 1; if (byte_chr(work->s,prefixlen,'[') < prefixlen) return 1; if (byte_chr(work->s,prefixlen,']') < prefixlen) return 1; } work->len = prefixlen; if (ch == '-') work->len = 0; return stralloc_cats(work,rule + colon + 1); }
ssize_t buffer_get_token(buffer* b,char* x,size_t len,const char* charset,size_t setlen) { size_t blen; if ((ssize_t)len<0) len=(ssize_t)(((size_t)-1)>>1); if (setlen==1) { for (blen=0; blen<len; ) { ssize_t n=buffer_feed(b); char* d; if (n<=0) return blen; if (n>(ssize_t)(len-blen)) n=len-blen; if ((d=memccpy(x+blen,b->x+b->p,(unsigned char)charset[0],n))) { /* memccpy returns a pointer to the next char after matching * char or NULL if it copied all bytes it was asked for */ b->p+=(d-(x+blen)); return d-x-1; } blen+=n; b->p+=n; } } else { for (blen=0;blen<len;++blen) { register ssize_t r; if ((r=buffer_getc(b,x))<0) return r; if (r==0) { *x=0; break; } if (byte_chr(charset,setlen,*x)<setlen) break; ++x; } } return (ssize_t)blen; }
int s6rc_read_uint (char const *file, unsigned int *u) { char buf[UINT_FMT + 1] ; register int r = openreadnclose(file, buf, UINT_FMT) ; if (r < 0) return (errno == ENOENT) ? 0 : -1 ; buf[byte_chr(buf, r, '\n')] = 0 ; if (!uint0_scan(buf, u)) return (errno = EINVAL, -1) ; return 1 ; }
unsigned int byte_in (char const *s, register unsigned int n, register char const *sep, register unsigned int len) { register char const *t = s ; while (n--) { if (byte_chr(sep, len, *t) < len) break ; ++t ; } return t - s ; }
static int is_whitespace(const char* x, size_t n) { size_t i; for(i = 0; i < n; ++i) { if(!byte_chr(" \t\v\r\n\0", 5, x[i])) return 0; } return 1; }
/* skips bytes in buffer until a char in charset occurs, the char itself will be skipped also */ int buffer_skip_until(buffer* b, const char* charset, unsigned long int setlen) { int r; int n = 0; for (;;) { if(b->p == b->n) if((r = buffer_feed(b)) <= 0) return r; n++; if(byte_chr(charset, setlen, b->x[b->p++]) < setlen) break; } return n; }
unsigned int siovec_bytechr (siovec_t const *v, unsigned int n, char c) { unsigned int w = 0 ; unsigned int i = 0 ; for (; i < n ; i++) { register unsigned int pos = byte_chr(v[i].s, v[i].len, c) ; w += pos ; if (pos < v[i].len) break ; } return w ; }
unsigned int ip4_scanlist (char *out, unsigned int max, char const *s, unsigned int *num) { unsigned int n = 0, w = 0 ; for (; s[w] && (n < max) ; n++) { register unsigned int i = ip4_scan(s + w, out + (n << 2)) ; if (!i) break ; w += i ; while (byte_chr(",:; \t\r\n", 7, s[w]) < 7) w++ ; } *num = n ; return w ; }
ssize_t buffer_get_token(buffer* b,char* x,size_t len,const char* charset,size_t setlen) { size_t blen; if ((ssize_t)len<0) len=(ssize_t)(((size_t)-1)>>1); for (blen=0;blen<len;++blen) { register ssize_t r; if ((r=buffer_getc(b,x))<0) return r; if (r==0) { *x=0; break; } if (byte_chr(charset,setlen,*x)<setlen) break; ++x; } return (ssize_t)blen; }
int main(int argc,const char *const *argv) { int opt; int fd; const char *dir; sig_ignore(sig_pipe); while ((opt = getopt(argc,argv,"?vudopchaitkx")) != opteof) if (opt == 'v'){ puts("version: 0.76d"); exit(0); } else if (opt == '?') strerr_die1x(100,"svc options: u up, d down, o once, x exit, p pause, c continue, h hup, a alarm, i interrupt, t term, k kill"); else if (datalen < sizeof data) if (byte_chr(data,datalen,opt) == datalen) data[datalen++] = opt; argv += optind; fdorigdir = open_read("."); if (fdorigdir == -1) strerr_die2sys(111,FATAL,"unable to open current directory: "); while (dir = *argv++) { if (chdir(dir) == -1) strerr_warn4(WARNING,"unable to chdir to ",dir,": ",&strerr_sys); else { fd = open_write("supervise/control"); if (fd == -1) if (errno == error_nodevice) strerr_warn4(WARNING,"unable to control ",dir,": supervise not running",0); else strerr_warn4(WARNING,"unable to control ",dir,": ",&strerr_sys); else { ndelay_off(fd); buffer_init(&b,buffer_unixwrite,fd,bspace,sizeof bspace); if (buffer_putflush(&b,data,datalen) == -1) strerr_warn4(WARNING,"error writing commands to ",dir,": ",&strerr_sys); close(fd); } } if (fchdir(fdorigdir) == -1) strerr_die2sys(111,FATAL,"unable to set directory: "); } _exit(0); }
static void handle_control (int fd) { for (;;) { char c ; register int r = sanitize_read(fd_read(fd, &c, 1)) ; if (r < 0) strerr_diefu1sys(111, "read " S6_SUPERVISE_CTLDIR "/control") ; else if (!r) break ; else { register unsigned int pos = byte_chr("abqhkti12fFpcoduxO", 18, c) ; if (pos < 18) (*actions[state][V_a + pos])() ; } } }
unsigned int ip6_scanlist (char *out, unsigned int max, char const *s, unsigned int *num) { unsigned int n = 0, w = 0 ; for (; s[w] && (n < max) ; n++) { char ip[16] ; register unsigned int i = ip6_scan(s + w, ip) ; if (!i) break ; byte_copy(out + (n << 4), 16, ip) ; w += i ; while (byte_chr(",; \t\r\n", 6, s[w]) < 6) w++ ; } *num = n ; return w ; }
static int execute_file(const char *fn,stralloc *file) { unsigned int start; unsigned int end; unsigned int len; int code; for (start = 0; start < file->len; start = end + 1) { len = byte_chr(file->s+start,file->len-start,'\n'); end = start + len; file->s[end] = 0; if ((code = execute_line(fn,file->s+start)) != 0) return code; } return 0; }
int64 strlist_indexofb(strlist* sl, const char* x, size_t n) { size_t p; const char* s = sl->sa.s; for(p = 0; p < sl->sa.len;) { size_t l = byte_chr(&sl->sa.s[p], sl->sa.len - p, sl->sep); if((l == 0 && p + 1 == sl->sa.len)) break; if((n == l && byte_equal(&sl->sa.s[p], l, x))) return p; p += l + 1; } return -1; }
int buffer_get_token_sa(buffer* b,stralloc* sa, const char* charset, size_t setlen) { for (;;) { char x; if (!stralloc_readyplus(sa,1)) goto nomem; switch (buffer_getc(b,&x)) { case -1: return -1; case 0: return 0; } stralloc_append(sa,&x); if (byte_chr(charset,setlen,x)<setlen) break; } return 1; nomem: errno=ENOMEM; return -1; }
int readme (stralloc *sa) { int fddir; fddir = open_read("."); if (fddir == -1) STRERR_SYS(0, readme_err, "unable to switch to current directory: ") if (chdir(auto_qmail) == -1) STRERR_SYS3(0, readme_err, "unable to switch to ", auto_qmail, ": ") if (openreadclose("control/me", sa, 64) != 1) STRERR_SYS3(0, readme_err, "unable to read ", auto_qmail, "/control/me: ") sa->len = byte_chr(sa->s, sa->len, '\n'); if (!stralloc_0(sa)) STRERR(0, readme_err, "out of memory") if (fchdir(fddir) == -1) STRERR_SYS(0, readme_err, "unable to switch to starting directory: ") close(fddir); return 1; }
void maketo(void) /* expects line to be a return-path line. If it is and the format is valid */ /* to is set to to the sender. Otherwise, to is left untouched. Assuming */ /* to is empty to start with, it will remain empty if no sender is found. */ { unsigned int x, y; if (case_startb(line.s,line.len,"return-path:")) { x = 12 + byte_chr(line.s + 12,line.len-12,'<'); if (x != line.len) { y = byte_rchr(line.s + x,line.len-x,'>'); if (y + x != line.len) { if (!stralloc_copyb(&to,line.s+x+1,y-1)) die_nomem(); if (!stralloc_0(&to)) die_nomem(); } /* no return path-> no addressee. A NUL in the sender */ } /* is no worse than a faked sender, so no problem */ } }
void edir(const char *dirname) { int wdir; DIR *dir; direntry *d; int i; if ((wdir =open_read(".")) == -1) fatal("unable to open current working directory"); if (chdir(dirname)) fatal2("unable to switch to directory", dirname); if (! (dir =opendir("."))) fatal2("unable to open directory", dirname); for (;;) { errno =0; d =readdir(dir); if (! d) { if (errno) fatal2("unable to read directory", dirname); break; } if (d->d_name[0] == '.') continue; if (openreadclose(d->d_name, &sa, 256) == -1) { if ((errno == error_isdir) && env_dir) { if (verbose) strerr_warn6(WARNING, "unable to read ", dirname, "/", d->d_name, ": ", &strerr_sys); continue; } else strerr_die6sys(111, FATAL, "unable to read ", dirname, "/", d->d_name, ": "); } if (sa.len) { sa.len =byte_chr(sa.s, sa.len, '\n'); while (sa.len && (sa.s[sa.len -1] == ' ' || sa.s[sa.len -1] == '\t')) --sa.len; for (i =0; i < sa.len; ++i) if (! sa.s[i]) sa.s[i] ='\n'; if (! stralloc_0(&sa)) die_nomem(); if (! pathexec_env(d->d_name, sa.s)) die_nomem(); } else if (! pathexec_env(d->d_name, 0)) die_nomem(); } closedir(dir); if (fchdir(wdir) == -1) fatal("unable to switch to starting directory"); close(wdir); }
void load_config(const char *dir) { load_flags(dir); switch(slurp("key",&key,512)) { case -1: strerr_die4sys(111,FATAL,ERR_READ,dir,"/key: "); case 0: strerr_die4x(100,FATAL,dir,"/key",ERR_NOEXIST); } /* There are problems with using getconf_line to fetch the ezmlmrc * pointer, since the alt location for "ezmlmrc" turns out to be the * whole ezmlmrc file itself. */ switch (slurp("ezmlmrc",&ezmlmrc,64)) { case -1: strerr_die4sys(111,FATAL,ERR_READ,dir,"/ezmlmrc: "); case 0: ezmlmrc.len = 0; } ezmlmrc.len = byte_chr(ezmlmrc.s,ezmlmrc.len,'\n'); getconf_line(&outhost,"outhost",1,dir); getconf_line(&outlocal,"outlocal",1,dir); if (!stralloc_copy(&local,&outlocal)) die_nomem(); getconf_line(&listid,"listid",0,dir); if (getconf_line(&charset,"charset",0,dir)) { if (charset.len >= 2 && charset.s[charset.len - 2] == ':') { if (charset.s[charset.len - 1] == 'B' || charset.s[charset.len - 1] == 'Q') { flagcd = charset.s[charset.len - 1]; charset.s[charset.len - 2] = '\0'; } } } else if (!stralloc_copys(&charset,TXT_DEF_CHARSET)) die_nomem(); if (!stralloc_0(&charset)) die_nomem(); // FIXME: need to handle escapes in mailinglist getconf_line(&mailinglist,"mailinglist",1,dir); }
int buffer_copyline(buffer *out,buffer *in,char eol) { int n; char *x; int i; for (;;) { n = buffer_feed(in); if (n < 0) return -2; if (!n) break; x = buffer_PEEK(in); i = byte_chr(x,n,eol); if (buffer_put(out,x,i) < 0) return -3; buffer_SEEK(in,i); if (i < in->p) { buffer_PUTC(out,eol); buffer_SEEK(in,1); break; } } return 0; }
int getln2(buffer *ss,stralloc *sa,char **cont,unsigned int *clen,int sep) { register char *x; register unsigned int i; int n; if (!stralloc_ready(sa,0)) return -1; sa->len = 0; for (;;) { n = buffer_feed(ss); if (n < 0) return -1; if (n == 0) { *clen = 0; return 0; } x = buffer_PEEK(ss); i = byte_chr(x,n,sep); if (i < n) { buffer_SEEK(ss,*clen = i + 1); *cont = x; return 0; } if (!stralloc_readyplus(sa,n)) return -1; i = sa->len; sa->len = i + buffer_get(ss,sa->s + i,n); } }
void found(char *data,unsigned int datalen) { unsigned int next0; unsigned int split; while ((next0 = byte_chr(data,datalen,0)) < datalen) { switch(data[0]) { case 'D': flagdeny = 1; break; case '+': split = str_chr(data + 1,'='); if (data[1 + split] == '=') { data[1 + split] = 0; env(data + 1,data + 1 + split + 1); } break; } ++next0; data += next0; datalen -= next0; } }
static void load_config(void) { load_flags(); key.len = 0; switch(slurp("key",&key,512)) { case -1: strerr_die2sys(111,FATAL,MSG1(ERR_READ,"key")); case 0: strerr_die4x(100,FATAL,listdir,"/key",MSG(ERR_NOEXIST)); } /* There are problems with using getconf_line to fetch the ezmlmrc * pointer, since the alt location for "ezmlmrc" turns out to be the * whole ezmlmrc file itself. */ switch (slurp("ezmlmrc",&ezmlmrc,64)) { case -1: strerr_die2sys(111,FATAL,MSG1(ERR_READ,"ezmlmrc")); case 0: ezmlmrc.len = 0; } ezmlmrc.len = byte_chr(ezmlmrc.s,ezmlmrc.len,'\n'); getconf_line(&outhost,"outhost",1); getconf_line(&outlocal,"outlocal",1); if (!stralloc_copy(&local,&outlocal)) die_nomem(); getconf_line(&listid,"listid",0); if (getconf_line(&charset,"charset",0)) { if (charset.len >= 2 && charset.s[charset.len - 2] == ':') { if (charset.s[charset.len - 1] == 'B' || charset.s[charset.len - 1] == 'Q') { flagcd = charset.s[charset.len - 1]; charset.s[charset.len - 2] = '\0'; } } } else if (!stralloc_copys(&charset,TXT_DEF_CHARSET)) die_nomem(); if (!stralloc_0(&charset)) die_nomem(); }
int getln2(buffer *buf,stralloc *sa, /*@out@*/char **cont,/*@out@*/unsigned int *clen,int sep) { char *x; unsigned int i; int n; if (!stralloc_ready(sa,0)) return -1; sa->len = 0; for (;;) { n = buffer_feed(buf); if (n < 0) return -1; if (n == 0) { *clen = 0; return 0; } x = buffer_PEEK(buf); i = byte_chr(x,n,sep); if (i < n) { buffer_SEEK(buf,*clen = i + 1); *cont = x; return 0; } if (!stralloc_readyplus(sa,n)) return -1; i = sa->len; sa->len = i + buffer_get(buf,sa->s + i,n); } }
int netstring_get (buffer_ref b, stralloc *sa, unsigned int *unread) { unsigned int written ; int ok = 1 ; int r ; if (!sa->s || (!sa->len && !*unread)) { char *x ; unsigned int n ; unsigned int len ; for (;;) { x = buffer_PEEK(b) ; n = byte_chr(x, buffer_len(b), ':') ; /* XXX: accepts :, as a valid netstring */ if (n >= ULONG_FMT) return (errno = EINVAL, -1) ; /* XXX: breaks on too many leading '0's */ if (n < buffer_len(b)) break ; r = buffer_fill(b) ; if (r == -1) return -1 ; if (!r) return (buffer_isempty(b) ? 0 : (errno = EPIPE, -1)) ; ok = 2 ; } if (n != uint_scan(x, &len)) return (errno = EINVAL, -1) ; if (!stralloc_readyplus(sa, len+1)) return -1 ; buffer_SEEK(b, n+1) ; *unread = len + 1 ; } written = sa->len ; r = buffer_getall(b, sa->s + sa->len, sa->len + *unread, &written) ; if (r <= 0) { *unread -= written - sa->len ; sa->len = written ; return r ? r : (errno = EINVAL, -1) ; } if (r == 2) ok = 2 ; sa->len += *unread ; *unread = 0 ; return (sa->s[--sa->len] == ',') ? ok : (errno = EINVAL, -1) ; }
int getto(const stralloc *sa) /* find list address in line. If found, return 1, else return 0. */ { unsigned int pos = 0; unsigned int pos1; if (!sa->len) return 0; /* no To: or Cc: line */ while ((pos += 1 + byte_chr(sa->s+pos+1,sa->len-pos-1,'@')) != sa->len) { pos1 = findhost(sa,pos); if (pos1 == pos) break; if (pos1 + outhost.len <= sa->len) if (!case_diffb(sa->s+pos1,outhost.len,outhost.s)) { /* got host */ pos1 = findlocal(sa,pos); if (pos1 == pos) break; ++pos1; /* avoids 1 x 2 below */ if (pos1 >= outlocal.len) if (!case_diffb(sa->s+pos1-outlocal.len,outlocal.len,outlocal.s)) return 1; /* got local as well */ } } return 0; }
int skagetln (buffer_ref b, stralloc *sa, int sep) { unsigned int start = sa->len ; int ok = 1 ; for (;;) { char *s = buffer_PEEK(b) ; unsigned int pos = byte_chr(s, buffer_len(b), sep) ; int r = (pos < buffer_len(b)) ; if (!stralloc_catb(sa, s, pos)) return -1 ; buffer_SEEK(b, pos) ; if (r) { if (!stralloc_catb(sa, buffer_PEEK(b), 1)) return -1 ; buffer_SEEK(b, 1) ; return ok ; } r = buffer_fill(b) ; if (r == -1) return -1 ; if (!r) return (sa->s && (sa->len > start)) ? (errno = EPIPE, -1) : 0 ; ok = 2 ; } }
int timed_getln (buffer_ref b, stralloc *sa, int sep, struct taia const *deadline, struct taia *stamp) { unsigned int len = sa->len ; int ok = 1 ; for (;;) { char *s = buffer_PEEK(b) ; unsigned int pos = byte_chr(s, buffer_len(b), sep) ; int r = (pos < buffer_len(b)) ; if (!stralloc_catb(sa, s, pos)) return -1 ; buffer_SEEK(b, pos) ; if (r) { if (!stralloc_catb(sa, buffer_PEEK(b), 1)) return -1 ; buffer_SEEK(b, 1) ; return ok ; } r = timed_buffer_fill(b, deadline, stamp) ; if (r == -1) return -1 ; if (!r) return (sa->len > len) ? (errno = EPIPE, -1) : 0 ; ok = 2 ; } }
void record(char *buf,int len,char *direction) /* 1 <= len <= 256 */ { int i; while (len) { buffer_puts(&ssrecord,pid); buffer_puts(&ssrecord,direction); i = byte_chr(buf,len,'\n'); buffer_put(&ssrecord,buf,i); if (i == len) { buffer_puts(&ssrecord,"+\n"); buffer_flush(&ssrecord); return; } buffer_puts(&ssrecord," \n"); buffer_flush(&ssrecord); buf += i + 1; len -= i + 1; } }