void logaddr(const char *subdir,const char *event, const char *addr,const char *comment) { char ch; int fd; stralloc_copyb(&line,num,fmt_ulong(num,(unsigned long) now())); stralloc_cats(&line," "); stralloc_cats(&line,event); stralloc_cats(&line," "); while ((ch = *addr++) != 0) { if ((ch < 33) || (ch > 126)) ch = '?'; stralloc_append(&line,ch); } if (comment && *comment) { stralloc_cats(&line," "); while ((ch = *comment++) != 0) { if (ch == '\t') ch = ' '; else if ((ch < 32) || (ch > 126)) ch = '?'; stralloc_append(&line,ch); } } stralloc_cats(&line,"\n"); makepath(&fn,subdir,"/Log",0); fd = open_append(fn.s); if (fd == -1) return; substdio_fdbuf(&ss,write,fd,NULL,0); substdio_putflush(&ss,line.s,line.len); close(fd); return; }
static char *set_workdir(char *action) { if (case_starts(action,"digest")) { /* digest */ action += 6; stralloc_cats(&outlocal,"-digest"); workdir = "digest"; flagdig = FLD_DIGEST; } else if (case_starts(action,ACTION_ALLOW)) { /* allow */ action += str_len(ACTION_ALLOW); stralloc_append(&outlocal,'-'); stralloc_cats(&outlocal,ACTION_ALLOW); workdir = "allow"; flagdig = FLD_ALLOW; } else if (case_starts(action,ACTION_DENY)) { /* deny */ action += str_len(ACTION_DENY); stralloc_append(&outlocal,'-'); stralloc_cats(&outlocal,ACTION_DENY); workdir = "deny"; flagdig = FLD_DENY; } else { workdir = "."; flagdig = 0; } if (flagdig) /* zap '-' after db specifier */ if (*(action++) != '-') die_badaddr(); return action; }
int dns_domain_todot_cat(stralloc *out,const char *d) { char ch; char ch2; unsigned char ch3; char buf[4]; if (!*d) return stralloc_append(out,"."); for (;;) { ch = *d++; while (ch--) { ch2 = *d++; if ((ch2 >= 'A') && (ch2 <= 'Z')) ch2 = (char)(ch2 + 32); if (((ch2 >= 'a') && (ch2 <= 'z')) || ((ch2 >= '0') && (ch2 <= '9')) || (ch2 == '-') || (ch2 == '_')) { if (!stralloc_append(out,&ch2)) return 0; } else { ch3 = (unsigned char)ch2; buf[3] = (char)('0' + (ch3 & 7)); ch3 >>= 3; buf[2] = (char)('0' + (ch3 & 7)); ch3 >>= 3; buf[1] = (char)('0' + (ch3 & 7)); buf[0] = '\\'; if (!stralloc_catb(out,buf,4)) return 0; } } if (!*d) return 1; if (!stralloc_append(out,".")) return 0; } }
void keyadd(unsigned long u) { char ch; ch = (char) u; stralloc_append(&key,ch); u >>= 8; ch = (char) u; stralloc_append(&key,ch); u >>= 8; ch = (char) u; stralloc_append(&key,ch); u >>= 8; ch = (char) u; stralloc_append(&key,ch); }
/* usage: rellink "http://www.nytimes.com/2005/10/06/international/middleeast/06cnd-prexy.html?ex=1129262400&en=30e300dafe83d0fc&ei=5065&partner=MYWAY" downloaded-data.html */ int main(int argc,char* argv[]) { char* baseurl; char* map,* max,* x; struct stat ss; static stralloc sa; if (argc!=3) die(0,"usage: rellink http://base/url downloaded-data.html"); errmsg_iam("rellink"); baseurl=argv[1]; map=mmap_read_stat(argv[2],&ss); if (map==0) diesys(111,"open \"",argv[2],"\" failed"); max=map+ss.st_size; for (x=map; x<max; ) { stralloc tag; /* copy non-tag */ for (; x<max && *x!='<'; ++x) if (stralloc_append(&sa,x)==0) nomem: die(111,"out of memory"); if (x>=max) break; stralloc_copys(&tag,""); { int indq,insq,ok; indq=insq=ok=0; for (; x<max; ++x) { if (*x == '\'') insq^=1; else if (*x == '"') indq^=1; if (stralloc_append(&tag,x)==0) goto nomem; if (*x == '>' && !insq && !indq) { ok=1; ++x; break; } } if (ok) if (mangleurl(&tag,baseurl)==-1) goto nomem; } if (stralloc_cat(&sa,&tag)==0) goto nomem; } if (sa.len == ss.st_size && byte_equal(sa.s,ss.st_size,map)) return 0; munmap(map,ss.st_size); { struct utimbuf utb; int fd=open(argv[2],O_WRONLY|O_TRUNC,0600); if (fd==-1) die(111,"open(\"",argv[2],"\")"); write(fd,sa.s,sa.len); close(fd); utb.actime=ss.st_atime; utb.modtime=ss.st_mtime; utime(argv[2],&utb); } return 0; }
void store_from(stralloc *frl, /* from line */ const char *adr) /* rewrites the from file removing all that is older than 1000000 secs */ /* and add the curent from line (frl). Forget it if there is none there.*/ /* NOTE: This is used only for subscribes to moderated lists! */ { int fdin; int fdout; unsigned long linetime; if (!flagstorefrom || !frl->len) return; /* nothing to store */ lock(); if ((fdout = open_trunc("fromn")) == -1) strerr_die2sys(111,FATAL,MSG1(ERR_OPEN,"fromn")); substdio_fdbuf(&ssfrom,write,fdout,frombuf,(int) sizeof(frombuf)); if ((fdin = open_read("from")) == -1) { if (errno != error_noent) strerr_die2sys(111,FATAL,MSG1(ERR_OPEN,"from")); } else { substdio_fdbuf(&sstext,read,fdin,textbuf,(int) sizeof(textbuf)); for (;;) { if (getln(&sstext,&line,&match,'\n') == -1) strerr_die2sys(111,FATAL,MSG1(ERR_READ,"from")); if (!match) break; (void) scan_ulong(line.s,&linetime); if (linetime + 1000000 > (unsigned long) when && linetime <= (unsigned long) when) if (substdio_bput(&ssfrom,line.s,line.len)) strerr_die2sys(111,FATAL,MSG1(ERR_WRITE,"fromn")); } close(fdin); } /* build new entry */ stralloc_copyb(&line,strnum,fmt_ulong(strnum,when)); stralloc_append(&line,' '); stralloc_cats(&line,adr); stralloc_0(&line); stralloc_catb(&line,frl->s,frl->len); stralloc_append(&line,'\n'); if (substdio_bput(&ssfrom,line.s,line.len) == -1) strerr_die2sys(111,FATAL,MSG1(ERR_WRITE,"fromn")); if (substdio_flush(&ssfrom) == -1) strerr_die2sys(111,FATAL,MSG1(ERR_WRITE,"fromn")); if (fsync(fdout) == -1) strerr_die2sys(111,FATAL,MSG1(ERR_SYNC,"fromn")); if (close(fdout) == -1) strerr_die2sys(111,FATAL,MSG1(ERR_CLOSE,"fromn")); wrap_rename("fromn","from"); unlock(); }
int absolutepath (stralloc *sa, const char *path) { int r = 1 ; if (!path) r = stralloc_copys(sa, "/") ; else if (path[0] == '/') r = stralloc_copys(sa, path) ; else { unsigned int n = 0 ; for (;;) { n += 1024 ; if (!stralloc_ready(sa, n)) { r = 0 ; break ; } if (getcwd(sa->s, n)) break ; if (errno != ENOMEM) { r = 0 ; break ; } } sa->len = str_len(sa->s) ; if (r) r = stralloc_append(sa, "/") && stralloc_cats(sa, path) ; if (!r) stralloc_free(sa) ; } return r ? stralloc_0(sa) : 0 ; }
char *get_name(FILE *f) { int c; stralloc name = {0}; char *strp; char d; /* consume leading whitespace */ do { c = fgetc(f); } while(isspace(c)); ungetc(c, f); /* append non-whitespace chars */ while (1) { c = fgetc(f); if (c < 0 || isspace(c)) { stralloc_0(&name); strp = strdup(name.s); stralloc_free(&name); return strp; } d = c; stralloc_append(&name, &d); } }
int tdlookup_init(void) { char *x; char ch; int i; int j; int k; x = env_get("LAME_A"); if (x) if (!ip4_scan(x,lameip)) byte_zero(lameip,4); x = env_get("LAME_MX"); if (x) if (!dns_domain_fromdot(&lamemx,x,str_len(x))) return 0; x = env_get("LAME_TXT"); if (x) { i = 0; j = str_len(x); while (i < j) { k = j - i; if (k > 255) k = 255; ch = k; if (!stralloc_append(&lametxt,&ch)) return 0; if (!stralloc_catb(&lametxt,x + i,k)) return 0; i += k; } } return 1; }
static int doit(stralloc *out,int s,char ipremote[16],uint16 portremote,char iplocal[16],uint16 portlocal,unsigned int timeout,uint32 netif) { buffer b; char bspace[128]; char strnum[FMT_ULONG]; int numcolons; char ch; if (socket_bind6(s,iplocal,0,netif) == -1) return -1; if (timeoutconn6(s,ipremote,113,timeout,netif) == -1) return -1; buffer_init(&b,mywrite,s,bspace,sizeof bspace); buffer_put(&b,strnum,fmt_ulong(strnum,portremote)); buffer_put(&b," , ",3); buffer_put(&b,strnum,fmt_ulong(strnum,portlocal)); buffer_put(&b,"\r\n",2); if (buffer_flush(&b) == -1) return -1; buffer_init(&b,myread,s,bspace,sizeof bspace); numcolons = 0; for (;;) { if (buffer_get(&b,&ch,1) != 1) return -1; if ((ch == ' ') || (ch == '\t') || (ch == '\r')) continue; if (ch == '\n') return 0; if (numcolons < 3) { if (ch == ':') ++numcolons; } else { if (!stralloc_append(out,&ch)) return -1; if (out->len > 256) return 0; } } }
static void dispatch(const char *dir,const char *def) /* Hand off control to one of the command files in the list directory. */ { if (!is_dir(dir)) return; if (!stralloc_append(&basedir,"/")) die_nomem(); if (!stralloc_cats(&basedir,dir)) die_nomem(); /* FIXME: set up $EXT $EXT2 $EXT3 $EXT4 ? Is it feasable? */ if (def == 0 || *def == 0) execute("editor",0); else if (str_diff(def,"owner") == 0) execute("owner",0); else if (str_diff(def,"digest-owner") == 0) execute("owner",0); else { try_dispatch(def,"digest-return-",14,"digest/bouncer"); try_dispatch(def,"return-",7,"bouncer"); try_dispatch(def,"confirm-",8,"confirmer"); try_dispatch(def,"discard-",8,"confirmer"); try_dispatch(def,"accept-",7,"moderator"); try_dispatch(def,"reject-",7,"moderator"); /* If nothing else matches, call the manager. */ execute("manager",def); } }
static int decode_srs(const char *s) { /* Format: [email protected] */ /* Format: [email protected] */ char sep; int at; int sep1; int sep2; if ((sep = *s++) == 0) return 0; if (s[at = str_rchr(s,'@')] == 0) return 0; for (sep2 = at - 1; sep2 > 1 && s[sep2] != '='; sep2--) ; /* s+sep2 = "=USER@..." */ for (sep1 = sep2 - 1; sep1 > 1 && s[sep1] != '='; sep1--) ; /* s+sep1 = "=DOMAIN=USER@..." */ if (sep2 <= 0) return 0; ++sep1; ++sep2; if (!stralloc_copyb(&realsender,s+sep2,at-sep2)) die_nomem(); if (!stralloc_append(&realsender,"@")) die_nomem(); if (!stralloc_catb(&realsender,s+sep1,sep2-sep1-1)) die_nomem(); if (!stralloc_0(&realsender)) die_nomem(); return 1; }
void stralloc_catlong0(stralloc *sa,long l,unsigned int n) { if (l < 0) { stralloc_append(sa,'-'); l = -l; } stralloc_catulong0(sa,l,n); }
extern void stralloc_add_formatv( stralloc_t* s, const char* fmt, va_list args ) { STRALLOC_DEFINE(s2); stralloc_formatv(s2, fmt, args); stralloc_append( s, s2 ); stralloc_reset( s2 ); }
int stralloc_catlong0(stralloc *sa,long l,unsigned int n) { if (l < 0) { if (!stralloc_append(sa,'-')) return 0; l = -l; } return stralloc_catulong0(sa,l,n); }
static int getsa(buffer *b,stralloc *sa,int *match) { if (!*match) return 0; if (getln(b,sa,match,'\n') == -1) return -1; if (*match) return 1; if (!sa->len) return 0; if (!stralloc_append(sa,"\n")) return -1; return 1; }
/* * For LDAP, '(', ')', '\', '*' and '\0' have to be escaped with '\'. * We ignore the '\0' case because it is not possible to have a '\0' in s. */ int filter_escape(stralloc *filter, char *s, unsigned int len) { char x; /* pre reserve some space */ if (!stralloc_readyplus(filter, len)) return 0; for (; len != 0; len--) { x = *s++; if (x == '*' || x == '(' || x == ')' || x == '\\') if (!stralloc_append(filter, "\\")) return 0; if (!stralloc_append(filter, &x)) return 0; } return 1; }
/* * For LDAP, '(', ')', '\', '*' and '\0' have to be escaped with '\'. * We ignore the '\0' case because it is not possible to have a '\0' in s. */ char * filter_escape(char *s) { char x; if( !(s && *s) ) return 0; /* pre reserve some space */ if (!stralloc_ready(&escapedstr, str_len(s))) return 0; if (!stralloc_copys(&escapedstr, "")) return 0; do { x = *s; if (x == '*' || x == '(' || x == ')' || x == '\\') if (!stralloc_append(&escapedstr, "\\")) return 0; if (!stralloc_append(&escapedstr, s)) return 0; } while (*s++); return escapedstr.s; }
/* Creates an entry for message num and the list listno and code "done". * Returns NULL on success, and the error string on error. */ static const char *_logmsg(struct subdbinfo *info, unsigned long num, unsigned long listno, unsigned long subs, int done) { sqlite3_stmt *stmt; int res; if (!stralloc_copys(&logline,"INSERT INTO ")) die_nomem(); if (!stralloc_cats(&logline,info->base_table)) die_nomem(); if (!stralloc_cats(&logline,"_mlog (msgnum,listno,tai,subs,done) VALUES (")) die_nomem(); if (!stralloc_catb(&logline,strnum,fmt_ulong(strnum,num))) die_nomem(); if (!stralloc_cats(&logline,",")) die_nomem(); if (!stralloc_catb(&logline,strnum,fmt_ulong(strnum,listno))) die_nomem(); if (!stralloc_cats(&line,",")) die_nomem(); if (!stralloc_catb(&line,strnum,fmt_ulong(strnum,now()))) die_nomem(); if (!stralloc_cats(&line,",'")) die_nomem(); if (!stralloc_catb(&logline,strnum,fmt_ulong(strnum,subs))) die_nomem(); if (!stralloc_cats(&logline,",")) die_nomem(); if (done < 0) { done = - done; if (!stralloc_append(&logline,"-")) die_nomem(); } if (!stralloc_catb(&logline,strnum,fmt_uint(strnum,done))) die_nomem(); if (!stralloc_append(&logline,")")) die_nomem(); if (!stralloc_0(&logline)) die_nomem(); if ((stmt = _sqlquery(info, &logline)) == NULL) /* log query */ return sqlite3_errmsg((sqlite3*)info->conn); res = sqlite3_step(stmt); sqlite3_finalize(stmt); if (res != SQLITE_DONE) { if (res != SQLITE_CONSTRAINT) /* ignore dups */ return sqlite3_errmsg((sqlite3*)info->conn); } return 0; }
static const char *makepath(const char *fn) { if (!stralloc_copy(&path,&basedir)) die_nomem(); if (fn) { if (!stralloc_append(&path,"/")) die_nomem(); if (!stralloc_cats(&path,fn)) die_nomem(); } if (!stralloc_0(&path)) die_nomem(); return path.s; }
int stralloc_catnum0(stralloc *sa, long long l, long long n) { if (!sa) { errno = EINVAL; return 0; } if (l < 0) { if (!stralloc_append(sa,"-")) return 0; l = -l; } return stralloc_catunum0(sa, l, n); }
int geton(const char *action) { const char *fl; int r; unsigned int i; unsigned char ch; fl = get_from(target.s,action); /* try to match up */ r = subscribe(workdir,target.s,1,fl,(*action == ACTION_RC[0]) ? "+mod" : "+",-1); if (flagdig == FLD_DENY || flagdig == FLD_ALLOW) strerr_die2x(0,INFO,MSG1(ERR_EXTRA_SUB,target.s)); switch (r) { case 1: qmail_puts(&qq,"List-Unsubscribe: <mailto:"); /*rfc2369 */ qmail_put(&qq,outlocal.s,outlocal.len); qmail_puts(&qq,"-unsubscribe-"); /* url-encode since verptarget is controlled by sender */ /* note &verptarget ends in '\0', hence len - 1! */ for (i = 0; i < verptarget.len - 1; i++) { ch = verptarget.s[i]; if (str_chr("\"?;<>&/:%+#",ch) < 10 || (ch <= ' ') || (ch & 0x80)) { urlstr[1] = hex[ch / 16]; urlstr[2] = hex[ch & 0xf]; qmail_put(&qq,urlstr,3); } else { qmail_put(&qq,verptarget.s + i, 1); } } qmail_puts(&qq,"@"); qmail_put(&qq,outhost.s,outhost.len); /* safe */ qmail_puts(&qq,">\n"); hdr_subject(MSG(SUB_WELCOME)); hdr_ctboundary(); stralloc_copy(&confirm,&outlocal); stralloc_cats(&confirm,"-unsubscribe-"); stralloc_cats(&confirm,verptarget.s); stralloc_append(&confirm,'@'); stralloc_cat(&confirm,&outhost); stralloc_0(&confirm); set_cpconfirm(confirm.s,outlocal.len); /* for !R in copy */ copy(&qq,"text/top",flagcd); copy_act("text/sub-ok"); break; default: if (str_start(action,ACTION_TC)) strerr_die2x(0,INFO,MSG(ERR_SUB_NOP)); hdr_subject(MSG(SUB_SUBSCRIBE_NOP)); hdr_ctboundary(); copy(&qq,"text/top",flagcd); copy_act("text/sub-nop"); break; } return r; }
static int doit(stralloc *out,stralloc *fqdn) { unsigned int i; char code; char ch; char ip[16]; if (!stralloc_copys(out,"")) return -1; if (!stralloc_readyplus(fqdn,1)) return -1; fqdn->s[fqdn->len]=0; if ((i=ip6_scan(fqdn->s,ip))) { if (!fqdn->s[i]) { stralloc_copyb(out,ip,16); return 0; } } if ((i=ip4_scan(fqdn->s,ip+12))) { if (!fqdn->s[i]) { byte_zero(ip,10); ip[10]=ip[11]=0xff; stralloc_copyb(out,ip,16); return 0; } } code = 0; for (i = 0;i <= fqdn->len;++i) { if (i < fqdn->len) ch = fqdn->s[i]; else ch = '.'; if ((ch == '[') || (ch == ']')) continue; if (ch == '.') { if (!stralloc_append(out,&code)) return -1; code = 0; continue; } if ((ch >= '0') && (ch <= '9')) { code *= 10; code += ch - '0'; continue; } if (!dns_domain_fromdot(&q,fqdn->s,fqdn->len)) return -1; if (dns_resolve(q,DNS_T_AAAA) == -1) return -1; if (dns_ip6_packet(out,dns_resolve_tx.packet,dns_resolve_tx.packetlen) == -1) return -1; dns_transmit_free(&dns_resolve_tx); dns_domain_free(&q); return 0; } out->len &= ~3; return 0; }
static int stralloc_cat_table(stralloc *s, const struct subdbinfo *info, const char *table) { if (!stralloc_cats(s,info->base_table)) return 0; if (table) { if (!stralloc_append(s,"_")) return 0; if (!stralloc_cats(s,table)) return 0; } return 1; }
void unescape(char *s, stralloc *t) { if (!stralloc_copys(t, "")) temp_nomem(); do { if (s[0] == '\\' && s[1] == ':') s++; else if (s[0] == ':') { if (!stralloc_0(t)) temp_nomem(); continue; } if (!stralloc_append(t, s)) temp_nomem(); } while (*s++); }
static int init(char ip[64]) { int i; unsigned int j; int iplen = 0; char *x; x = env_get("DNSCACHEIP"); if (x) while (iplen <= 60) { if (*x == '.') ++x; else { i = ip4_scan(x,ip + iplen); if (!i) break; x += i; iplen += 4; } } if (!iplen) { i = openreadclose("/etc/resolv.conf",&data,64); if (i == -1) return -1; if (i) { if (!stralloc_append(&data,'\n')) return -1; i = 0; for (j = 0;j < data.len;++j) if (data.s[j] == '\n') { if (byte_equal("nameserver ",11,data.s + i) || byte_equal("nameserver\t",11,data.s + i)) { i += 10; while ((data.s[i] == ' ') || (data.s[i] == '\t')) ++i; if (iplen <= 60) if (ip4_scan(data.s + i,ip + iplen)) { if (byte_equal(ip + iplen,4,"\0\0\0\0")) byte_copy(ip + iplen,4,"\177\0\0\1"); iplen += 4; } } i = j + 1; } } } if (!iplen) { byte_copy(ip,4,"\177\0\0\1"); iplen = 4; } byte_zero(ip + iplen,64 - iplen); return 0; }
void doconfirm(const char *act) /* This should only be called with valid act for sub/unsub confirms. If act */ /* is not ACTION_[RST]C, it is assumed to be an unsubscribe conf.*/ /* "act" is the first letter of desired confirm request only as STRING! */ { strnum[fmt_ulong(strnum,when)] = 0; cookie(hash,key.s,key.len-flagdig,strnum,target.s,act); stralloc_copy(&confirm,&outlocal); stralloc_append(&confirm,'-'); stralloc_catb(&confirm,act,1); stralloc_cats(&confirm,"c."); stralloc_cats(&confirm,strnum); stralloc_append(&confirm,'.'); stralloc_catb(&confirm,hash,COOKIE); stralloc_append(&confirm,'-'); stralloc_cats(&confirm,verptarget.s); stralloc_append(&confirm,'@'); stralloc_cat(&confirm,&outhost); stralloc_0(&confirm); set_cpconfirm(confirm.s,outlocal.len); /* for copy */ set_cpaction(act); set_cphash(hash); set_cpwhen(when); qmail_puts(&qq,"Reply-To: "); quote2("ed,confirm.s); qmail_put(&qq,quoted.s,quoted.len); qmail_puts(&qq,"\n"); hdr_subject((*act == ACTION_SC[0]) ? MSG(SUB_USR_SUBSCRIBE) : (*act == ACTION_UC[0]) ? MSG(SUB_USR_UNSUBSCRIBE) : (*act == ACTION_TC[0] || *act == ACTION_RC[0]) ? MSG(SUB_MOD_SUBSCRIBE) : MSG(SUB_MOD_UNSUBSCRIBE)); hdr_ctboundary(); copy(&qq,"text/top",flagcd); }
void iso2txt(char *s, int len, stralloc *sa) { unsigned char *c; for(c = s; c < s + len; c++) { if(*c > 127 || *c < 32 || *c == '\\' || *c == ',') { stralloc_append(sa, "\\"); stralloc_readyplus(sa, 3); sa->s[sa->len++] = ((*c & 0xc0) >> 6) + '0'; sa->s[sa->len++] = ((*c & 0x38) >> 3) + '0'; sa->s[sa->len++] = (*c & 0x07) + '0'; } else
void make_verptarget(void) /* puts target with '=' instead of last '@' into stralloc verptarget */ /* and does set_cpverptarget */ { unsigned int i; i = str_rchr(target.s,'@'); stralloc_copyb(&verptarget,target.s,i); if (target.s[i]) { stralloc_append(&verptarget,'='); stralloc_cats(&verptarget,target.s + i + 1); } stralloc_0(&verptarget); set_cpverptarget(verptarget.s); }
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; }