/* This routine inserts the cookie into table_cookie. We log arrival of * the message (done=0). */ void sub_sql_tagmsg(struct subdbinfo *info, unsigned long msgnum, /* number of this message */ const char *hashout, /* previously calculated hash */ unsigned long bodysize, unsigned long chunk) { const char *ret; char strnum[FMT_ULONG]; if (chunk >= 53L) chunk = 0L; /* sanity */ /* INSERT INTO table_cookie (msgnum,tai,cookie,bodysize,chunk) VALUES (...) */ /* (we may have tried message before, but failed to complete, so */ /* ER_DUP_ENTRY is ok) */ stralloc_copys(&query,"INSERT INTO "); stralloc_cats(&query,info->base_table); stralloc_cats(&query,"_cookie (msgnum,tai,cookie,bodysize,chunk) VALUES "); stralloc_cats(&query,sql_tagmsg_values_defn); stralloc_copyb(¶ms[0],strnum,fmt_ulong(strnum,msgnum)); stralloc_copyb(¶ms[1],hashout,COOKIE); stralloc_copyb(¶ms[2],strnum,fmt_ulong(strnum,bodysize)); stralloc_copyb(¶ms[3],strnum,fmt_ulong(strnum,chunk)); sql_exec(info,&query,4,params); /* ignore dups */ if (! (ret = logmsg(msgnum,0L,0L,1))) return; /* log done=1*/ if (*ret) strerr_die2x(111,FATAL,ret); }
static int extractparam(stralloc* tag,const char* wanted,stralloc* before,stralloc* arg,stralloc* after) { int l=strlen(wanted); char* x,* max,* y; if (tag->len<l+4) return 0; max=tag->s+tag->len; y=0; x=tag->s; if (*x != '<') return 0; ++x; for (; x<max && !isspace(*x); ++x) ; for (; x<max && isspace(*x); ++x) ; for (; x<max-l; ++x) { if (max-x>l && case_equalb(x,l,wanted) && x[l]=='=') { x+=l+1; if (stralloc_copyb(before,tag->s,x-tag->s)==0) return 0; if (*x=='"') { ++x; y=x; for (; x<max && *x!='"'; ++x) ; if (stralloc_copyb(arg,y,x-y)==0) return 0; ++x; } else { y=x; for (; x<max && !isspace(*x) && *x!='>'; ++x) ; if (stralloc_copyb(arg,y,x-y)==0) return 0; } y=x; if (stralloc_copyb(after,y,max-y)==0) return 0; return 1; } } return 0; }
/* Outputs all addresses in the table through subwrite. subwrite must be * a function returning >=0 on success, -1 on error, and taking * arguments (char* string, unsigned int length). It will be called once * per address and should take care of newline or whatever needed for * the output form. */ unsigned long sub_sql_putsubs(struct subdbinfo *info, const char *table, unsigned long hash_lo, unsigned long hash_hi, int subwrite()) /* write function. */ { void *result; unsigned long no = 0L; char strnum[FMT_ULONG]; stralloc_copyb(¶ms[0],strnum,fmt_ulong(strnum,hash_lo)); stralloc_copyb(¶ms[1],strnum,fmt_ulong(strnum,hash_hi)); make_name(info,table?"_":0,table,0); /* main query */ stralloc_copys(&query,"SELECT address FROM "); stralloc_cat(&query,&name); stralloc_cats(&query," WHERE "); stralloc_cats(&query,sql_putsubs_where_defn); result = sql_select(info,&query,2,params); no = 0; while (sql_fetch_row(info,result,1,&addr)) { if (subwrite(addr.s,addr.len) == -1) die_write(); no++; /* count for list-list fxn */ } sql_free_result(info,result); return no; }
/* Creates an entry for message num and the list listno and code "done". * Returns NULL on success, and the error string on error. */ const char *sub_sql_logmsg(struct subdbinfo *info, unsigned long num, unsigned long listno, unsigned long subs, int done) { char *s; char strnum[FMT_ULONG]; stralloc_copys(&query,"INSERT INTO "); stralloc_cats(&query,info->base_table); stralloc_cats(&query,"_mlog (msgnum,listno,subs,done) VALUES "); stralloc_cats(&query,sql_logmsg_values_defn); stralloc_copyb(¶ms[0],strnum,fmt_ulong(strnum,num)); stralloc_copyb(¶ms[1],strnum,fmt_ulong(strnum,listno)); stralloc_copyb(¶ms[2],strnum,fmt_ulong(strnum,subs)); s = strnum; if (done < 0) { done = - done; *s++ = '-'; } s[fmt_uint(s,done)] = 0; stralloc_copys(¶ms[3],s); sql_exec(info,&query,4,params); /* ignore dups */ return 0; }
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; }
void mkauthhash(const char *s,unsigned int len,char *h) /* This is a string that should be the same for all messages from a given */ /* author. Doesn't have to be the real rfc822 address. We look for a '@' */ /* and grab everything up to the next '>', ' ', or ';'. We go back the same */ /* way, then take everything up to the '@' or the first '-'. The latter */ /* avoids problems with posters that band their addresses. */ { unsigned int i,j,k,l; char ch; j = k = l = 0; i = byte_rchr(s,len,'@'); if (i < len) { /* if not then i=sa->len, j=k=l=0 */ j = i; while (++j < len) { /* if not found, then j=sa->len */ ch = s[j]; if (ch == '>' || ch == ' ' || ch == ';') break; } k = i; while (k > 0) { /* k <= i */ ch = s[--k]; if (ch == '<' || ch == ' ' || ch == ';') break; } l = k; /* k <= l <= i; */ while (l < i && s[l] != '-') ++l; if (!stralloc_copyb(&dummy,s + k, l - k)) die_nomem(); if (!stralloc_catb(&dummy,s + i, j - i)) die_nomem(); makehash(dummy.s,dummy.len,h); } else /* use entire line if no '@' found */ makehash(s,len,h); }
static int decode_prvs(const char *s) { /* The BATV standard says the user part should have the format * "tag-type=tag-val=loc-core" where "loc-core" is the original local * address, but all the examples I could find in actual use had the * last two parts reversed. What a mess. So, I have to check if * either the first or second part is a valid prvs tag, and use the * other one. */ int at; int sep; if (s[at = str_rchr(s,'@')] == 0) return 0; /* Format: [email protected] */ for (sep = 5; sep < at && s[sep] != '='; ++sep) ; if (sep >= at) return 0; if (is_prvs_tag(s+5,sep-5)) { if (!stralloc_copys(&realsender,s+sep+1)) die_nomem(); if (!stralloc_0(&realsender)) die_nomem(); return 1; } /* Format: [email protected] */ for (sep = at - 1; sep > 5 && s[sep] != '='; --sep) ; if (is_prvs_tag(s + sep + 1, at - sep - 1)) { if (!stralloc_copyb(&realsender,s+5,sep-5)) die_nomem(); if (!stralloc_cats(&realsender,s+at)) die_nomem(); if (!stralloc_0(&realsender)) die_nomem(); return 1; } return 0; }
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 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; }
/* Checks the hash against the cookie table. If it matches, returns NULL, * else returns "". If error, returns error string. */ const char *sub_sql_checktag (struct subdbinfo *info, unsigned long num, /* message number */ unsigned long listno, /* bottom of range => slave */ const char *action, const char *seed, const char *hash) /* cookie */ { void *result; char strnum[FMT_ULONG]; /* SELECT msgnum FROM table_cookie WHERE msgnum=num and cookie='hash' */ /* succeeds only is everything correct. */ if (listno) { /* only for slaves */ stralloc_copyb(¶ms[0],strnum,fmt_ulong(strnum,listno)); stralloc_copyb(¶ms[1],strnum,fmt_ulong(strnum,num)); stralloc_copys(&query,"SELECT listno FROM "); stralloc_cats(&query,info->base_table); stralloc_cats(&query,"_mlog WHERE "); stralloc_cats(&query,sql_checktag_listno_where_defn); result = sql_select(info,&query,2,params); if (sql_fetch_row(info,result,1,params)) { sql_free_result(info,result); return ""; /* already done */ } /* no result */ sql_free_result(info,result); } stralloc_copyb(¶ms[0],strnum,fmt_ulong(strnum,num)); stralloc_copyb(¶ms[1],hash,COOKIE); stralloc_copys(&query,"SELECT msgnum FROM "); stralloc_cats(&query,info->base_table); stralloc_cats(&query,"_cookie WHERE "); stralloc_cats(&query,sql_checktag_msgnum_where_defn); result = sql_select(info,&query,2,params); if (!sql_fetch_row(info,result,1,params)) { sql_free_result(info,result); return ""; /* not parent => perm error */ } sql_free_result(info,result); /* success! cookie matches */ return (char *)0; (void)action; (void)seed; }
int dns_domain_prependb2(char **out, const char *d, const char *s1, unsigned int n1, const char *s2, unsigned int n2) { static stralloc sa; if (!stralloc_copyb(&sa, s1, n1)) return 0; if (s2 && n2) if (!stralloc_catb(&sa, s2, n2)) return 0; if (!dns_domain_todot_cat(&sa, d)) return 0; if (!dns_domain_fromdot(out, sa.s, sa.len)) return 0; return 1; }
void rr_finish(const char *owner) { if (byte_equal(owner,2,"\1*")) { owner += 2; result.s[2] -= 19; } if (!stralloc_copyb(&key,owner,dns_domain_length(owner))) nomem(); case_lowerb(key.s,key.len); if (cdb_make_add(&cdb,key.s,key.len,result.s,result.len) == -1) die_datatmp(); }
/* Searches the subscriber log and outputs via subwrite(s,len) any entry * that matches search. A '_' is search is a wildcard. Any other * non-alphanum/'.' char is replaced by a '_'. */ static void _searchlog(struct subdbinfo *info, const char *table, char *search, /* search string */ int subwrite()) /* output fxn */ { sqlite3_stmt *stmt; int res; datetime_sec when; struct datetime dt; char date[DATE822FMT]; /* SELECT (*) FROM list_slog WHERE fromline LIKE '%search%' OR address */ /* LIKE '%search%' ORDER BY tai; */ /* The '*' is formatted to look like the output of the non-mysql version */ /* This requires reading the entire table, since search fields are not */ /* indexed, but this is a rare query and time is not of the essence. */ if (!stralloc_copys(&line,"SELECT tai, edir||etype||' '||address||' '||fromline" " FROM ")) die_nomem(); if (!stralloc_cat_table(&line,info,table)) die_nomem(); if (!stralloc_cats(&line,"_slog")) die_nomem(); if (*search) { /* We can afford to wait for LIKE '%xx%' */ if (!stralloc_cats(&line," WHERE fromline LIKE '%")) die_nomem(); if (!stralloc_cats(&line,search)) die_nomem(); if (!stralloc_cats(&line,"%' OR address LIKE '%")) die_nomem(); if (!stralloc_cats(&line,search)) die_nomem(); if (!stralloc_cats(&line,"%'")) die_nomem(); } /* ordering by tai which is an index */ if (!stralloc_cats(&line," ORDER by tai")) die_nomem(); if (!stralloc_0(&line)) die_nomem(); if ((stmt = _sqlquery(info, &line)) == NULL) strerr_die2x(111,FATAL,sqlite3_errmsg((sqlite3*)info->conn)); while ((res = sqlite3_step(stmt)) != SQLITE_DONE) { if (res != SQLITE_ROW) strerr_die2x(111,FATAL,sqlite3_errmsg((sqlite3*)info->conn)); (void)scan_ulong((const char*)sqlite3_column_text(stmt,0),&when); datetime_tai(&dt,when); if (!stralloc_copyb(&line,date,date822fmt(date,&dt)-1)) die_nomem(); if (!stralloc_cats(&line,": ")) die_nomem(); if (!stralloc_catb(&line,strnum,fmt_ulong(strnum,when))) die_nomem(); if (!stralloc_cats(&line," ")) die_nomem(); if (!stralloc_catb(&line, (const char*)sqlite3_column_text(stmt,1), sqlite3_column_bytes(stmt,1))) die_nomem(); if (subwrite(line.s,line.len) == -1) die_write(); } sqlite3_finalize(stmt); }
static int env_val(const char *env,const char *val,int len) { if (envsa) { if (!stralloc_cats(envsa,env)) return 0; if (!stralloc_catb(envsa,"=",1)) return 0; if (!stralloc_catb(envsa,val,len)) return 0; if (!stralloc_0(envsa)) return 0; return 1; } if (!stralloc_copyb(&etemp,val,len)) return 0; if (!stralloc_0(&etemp)) return 0; return pathexec_env(env,etemp.s); }
static int _issub(struct subdbinfo *info, const char *table, const char *userhost, stralloc *recorded) { sqlite3_stmt *stmt; unsigned int j; int res; /* SELECT address FROM list WHERE address = 'userhost' AND hash */ /* BETWEEN 0 AND 52. Without the hash restriction, we'd make it */ /* even easier to defeat. Just faking sender to the list name would*/ /* work. Since sender checks for posts are bogus anyway, I don't */ /* know if it's worth the cost of the "WHERE ...". */ if (!stralloc_copys(&addr,userhost)) die_nomem(); j = byte_rchr(addr.s,addr.len,'@'); if (j == addr.len) return 0; case_lowerb(addr.s + j + 1,addr.len - j - 1); if (!stralloc_copys(&line,"SELECT address FROM ")) die_nomem(); if (!stralloc_cat_table(&line,info,table)) die_nomem(); if (!stralloc_cats(&line," WHERE address LIKE '")) die_nomem(); if (!stralloc_cat(&line,&addr)) die_nomem(); if (!stralloc_cats(&line,"'")) die_nomem(); if (!stralloc_0(&line)) die_nomem(); if ((stmt = _sqlquery(info, &line)) == NULL) /* select */ strerr_die2x(111,FATAL,sqlite3_errmsg((sqlite3*)info->conn)); /* No data returned in QUERY */ res = sqlite3_step(stmt); if (res != SQLITE_ROW) { if (res != SQLITE_DONE) strerr_die2x(111,FATAL,sqlite3_errmsg((sqlite3*)info->conn)); sqlite3_finalize(stmt); return 0; } if (recorded) { if (!stralloc_copyb(recorded, (const char*)sqlite3_column_text(stmt, 0), sqlite3_column_bytes(stmt, 0))) die_nomem(); if (!stralloc_0(recorded)) die_nomem(); } sqlite3_finalize(stmt); return 1; }
/* Searches the subscriber log and outputs via subwrite(s,len) any entry * that matches search. A '_' is search is a wildcard. Any other * non-alphanum/'.' char is replaced by a '_'. */ void sub_sql_searchlog(struct subdbinfo *info, const char *table, char *search, /* search string */ int subwrite()) /* output fxn */ { void *result; datetime_sec when; struct datetime dt; char date[DATE822FMT]; int nparams; char strnum[FMT_ULONG]; make_name(info,table?"_":0,table,0); /* SELECT (*) FROM list_slog WHERE fromline LIKE '%search%' OR address */ /* LIKE '%search%' ORDER BY tai; */ /* The '*' is formatted to look like the output of the non-mysql version */ /* This requires reading the entire table, since search fields are not */ /* indexed, but this is a rare query and time is not of the essence. */ stralloc_copys(&query,"SELECT "); stralloc_cats(&query,sql_searchlog_select_defn); stralloc_cats(&query," FROM "); stralloc_cat(&query,&name); stralloc_cats(&query,"_slog"); if (*search) { /* We can afford to wait for LIKE '%xx%' */ stralloc_copys(¶ms[0],search); stralloc_copys(¶ms[1],search); nparams = 2; stralloc_cats(&query," WHERE "); stralloc_cats(&query,sql_searchlog_where_defn); } else nparams = 0; /* ordering by tai which is an index */ stralloc_cats(&query," ORDER by tai"); result = sql_select(info,&query,nparams,params); while (sql_fetch_row(info,result,2,params)) { stralloc_0(¶ms[0]); (void)scan_ulong(params[0].s,&when); datetime_tai(&dt,when); stralloc_copyb(¶ms[0],date,date822fmt(date,&dt)-1); stralloc_cats(¶ms[0],": "); stralloc_catb(¶ms[0],strnum,fmt_ulong(strnum,when)); stralloc_cats(¶ms[0]," "); stralloc_cat(¶ms[0],¶ms[1]); if (subwrite(params[0].s,params[0].len) == -1) die_write(); } sql_free_result(info,result); }
void rr_start(const char type[2],unsigned long ttl,const char ttd[8],const char loc[2]) { char buf[4]; if (!stralloc_copyb(&result,type,2)) nomem(); if (byte_equal(loc,2,"\0\0")) rr_add("=",1); else { rr_add(">",1); rr_add(loc,2); } uint32_pack_big(buf,ttl); rr_add(buf,4); rr_add(ttd,8); }
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(); }
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 get_local_maildir(stralloc *home, stralloc *maildir) { substdio ss; char buf[512]; int dirfd, fd, match, save; dirfd = open_read("."); if (dirfd == -1) return ERRNO; if (chdir(home->s) == -1) return ERRNO; if ((fd = open_read(".qmail")) == -1) { if (errno == error_noent) return 0; return ERRNO; } substdio_fdbuf(&ss, subread, fd, buf, sizeof(buf)); while (1) { if (getln(&ss, maildir, &match, '\n') != 0) goto tryclose; if (!match && !maildir->len) { if (!stralloc_copyb(maildir, "", 1)) goto tryclose; break; } if ((maildir->s[0] == '.' || maildir->s[0] == '/') && maildir->s[maildir->len-2] == '/') { maildir->s[maildir->len-1] = '\0'; break; } } if (fchdir(dirfd) == -1) return ERRNO; close(dirfd); close(fd); return 0; tryclose: save = errno; /* preserve errno */ if (fchdir(dirfd) == -1) return ERRNO; close(dirfd); close(fd); errno = save; return ERRNO; }
/* set a variable value * ----------------------------------------------------------------------- */ const char *var_setvint(const char *v, int i, int flags) { struct var *var; var = var_create(v, flags); var->flags |= flags; if(var->sa.a == 0) var->sa.s = NULL; stralloc_copyb(&var->sa, v, var->len); stralloc_catc(&var->sa, '='); stralloc_catlong(&var->sa, i); stralloc_nul(&var->sa); var->offset = var->len + 1; return var->sa.s; }
void rr_start(const char type[2],unsigned long ttl,const char ttd[8],uint32 loc) { char buf[4]; char locp[4]; if (!stralloc_copyb(&result,type,2)) nomem(); //if (byte_equal(loc,2,"\0\0")) char[2]->>uint32loc if (loc == 0U) rr_add("=",1); else { rr_add(">",1); uint32_pack(locp,loc); rr_add(locp,4); } uint32_pack_big(buf,ttl); rr_add(buf,4); rr_add(ttd,8); }
void rr_finish (const char *owner) { if (byte_equal (owner, 2, "\1*")) { owner += 2; result.s[2] -= 19; } if (!stralloc_copyb (&key, owner, dns_domain_length (owner))) err (-1, "could not allocate enough memory"); case_lowerb (key.s, key.len); if (cdb_make_add (&cdb, key.s, key.len, result.s, result.len) == -1) errx (-1, "could not create file `data.tmp'"); }
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 read_files(void) { if (euid > 0 && !flags['c' - 'a']) read_line("/ezmlmrc",&cfname); read_line("/dot",&dot); read_line("/outlocal",&local); read_line("/outhost",&host); read_line("/digestcode",&code); read_line("/sublist",&popt[0]); read_line("/fromheader",&popt[3]); read_line("/tstdigopts",&popt[4]); read_line("/owner",&popt[5]); if (read_line("/subdb",&popt[6]) != 0 && read_line("/sql",&line) == 0) { stralloc_copyb(&popt[6],"sql:",4); stralloc_catb(&popt[6],line.s,line.len); } read_line("/modpost",&popt[7]); read_line("/modsub",&popt[8]); read_line("/remote",&popt[9]); }
int sql_fetch_row(struct subdbinfo *info, void *result, unsigned int ncolumns, struct stralloc *columns) { unsigned int i; sqlite3_stmt *stmt = result; switch (sqlite3_step(stmt)) { case SQLITE_DONE: return 0; case SQLITE_ROW: break; default: die_sqlerror(info); } for (i = 0; i < ncolumns; ++i) stralloc_copyb(&columns[i],(char*)sqlite3_column_text(stmt,i),sqlite3_column_bytes(stmt,i)); return 1; }
/* Returns a modified mail string if an alias_domain-real_domain mapping is found * It simply returns its argument if no mapping is found * On error returns NULL * */ char* replace_domain(const char* mail) { static stralloc new_mail = {0}; unsigned int at; char* new_domain; at = str_rchr(mail, '@'); if (mail[at] != '@') return (char*) 0; if (new_domain=qldap_domain_alias(mail + at + 1)) { if(!stralloc_copyb(&new_mail,mail,at + 1)) return (char*) 0; if(!stralloc_cats(&new_mail,new_domain)) return (char*) 0; if(!stralloc_0(&new_mail)) return (char*) 0; return new_mail.s; } return (char*) mail; /* Do nothing */ }
void pathexec_run(const char *file,char **argv,char **envp) { char *path; unsigned int split; int savederrno; if (file[str_chr(file,'/')]) { execve(file,argv,envp); return; } path = env_get("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 != error_noent) { savederrno = errno; if ((errno != error_acces) && (errno != error_perm) && (errno != error_isdir)) return; } if (!path[split]) { if (savederrno) errno = savederrno; return; } path += split; path += 1; } }
int dmarc_get(const stralloc *rec,const char *key,stralloc *out) { const char *rp; const unsigned int keylen = str_len(key); const char *end = rec->s + rec->len; const char *tp; rp = rec->s; while (end - rp > keylen + 1) { if (byte_equal(rp,keylen,key) && (rp[keylen] == '=' || rp[keylen] == ' ')) { rp += keylen; /* Skip space before = */ while (rp < end && *rp == ' ') ++rp; /* Skip = */ if (rp >= end || *rp++ != '=') return 0; /* Skip space after = */ while (rp < end && *rp == ' ') ++rp; /* Skip over to trailing ; */ tp = rp; while (tp < end && *tp != ';') ++tp; /* Trim space before ; */ while (tp > rp && tp[-1] == ' ') --tp; /* Finally, can return */ stralloc_copyb(out,rp,tp - rp); return 1; } while (rp < end && *rp++ != ';') ; while (rp < end && *rp == ' ') ++rp; } return 0; }
static void rr_addloq(const char type[2],const char *d, uint32 loc, uint32 mid,uint32 uid) { #ifdef USE_LOCMAPS char map[8]; dbger("-addloq: %s,%u (%u),%u,%u",d,loc,NOMATCH_HASH,uid,mid); if (loc != NOMATCH_HASH) return; dbger("NOMATCH hash found, adding loq records for %s",d); /* if (byte_equal(type,2,DNS_T_A)) { dbger("lookup LOQ for A record %s",fqdn_read(out,d)); } dbger("+addloq %s,%u,%u",fqdn_read(out,d),mid,uid); */ if (!stralloc_copyb(&key,"\0?",2)) nomem(); if (!stralloc_catb(&key,type,2)) nomem(); if (!stralloc_catb(&key,d,dns_domain_length(d))) nomem(); uint32_pack(map,mid); uint32_pack(map+4,uid); cdb_make_add(&cdb,key.s,key.len,map,8); #endif return; }