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); }
static void execute(const char *fn,const char *def) /* Load and execute a qmail command file. */ { stralloc file = {0,0,0}; int code; if (def != 0) env_put2("DEFAULT",def); else env_unset("DEFAULT"); if (slurp(fn,&file,256) != 1) strerr_die6sys(111,FATAL,ERR_READ_INPUT,basedir.s,"/",fn,": "); code = execute_file(fn,&file); substdio_puts(subfderr,"did 0+"); substdio_put(subfderr,strnum,fmt_ulong(strnum,did_forward)); substdio_puts(subfderr,"+"); substdio_put(subfderr,strnum,fmt_ulong(strnum,did_program)); substdio_putsflush(subfderr,"\n"); _exit(code); }
int std_subscribe(const char *dir, const char *subdir, const char *userhost, int flagadd, const char *comment, const char *event, int forcehash) /* add (flagadd=1) or remove (flagadd=0) userhost from the subscr. database */ /* dbname. Comment is e.g. the subscriber from line or name. It is added to */ /* the log. Event is the action type, e.g. "probe", "manual", etc. The */ /* direction (sub/unsub) is inferred from flagadd. Returns 1 on success, 0 */ /* on failure. If flagmysql is set and the file "sql" is found in the */ /* directory dbname, it is parsed and a mysql db is assumed. if forcehash is */ /* >=0 it is used in place of the calculated hash. This makes it possible to */ /* add addresses with a hash that does not exist. forcehash has to be 0..99. */ /* for unsubscribes, the address is only removed if forcehash matches the */ /* actual hash. This way, ezmlm-manage can be prevented from touching certain*/ /* addresses that can only be removed by ezmlm-unsub. Usually, this would be */ /* used for sublist addresses (to avoid removal) and sublist aliases (to */ /* prevent users from subscribing them (although the cookie mechanism would */ /* prevent the resulting duplicate message from being distributed. */ { int fdlock; unsigned int j; unsigned char ch,lcch; int match; int flagwasthere; if (userhost[str_chr(userhost,'\n')]) strerr_die2x(100,FATAL,ERR_ADDR_NL); if (!stralloc_copys(&addr,"T")) die_nomem(); if (!stralloc_cats(&addr,userhost)) die_nomem(); if (addr.len > 401) strerr_die2x(100,FATAL,ERR_ADDR_LONG); j = byte_rchr(addr.s,addr.len,'@'); if (j == addr.len) strerr_die2x(100,FATAL,ERR_ADDR_AT); case_lowerb(addr.s + j + 1,addr.len - j - 1); if (!stralloc_copy(&lcaddr,&addr)) die_nomem(); case_lowerb(lcaddr.s + 1,j - 1); /* make all-lc version of address */ if (forcehash >= 0 && forcehash <= 52) { ch = lcch = 64 + (unsigned char) forcehash; } else { ch = 64 + subhashsa(&addr); lcch = 64 + subhashsa(&lcaddr); } if (!stralloc_0(&addr)) die_nomem(); if (!stralloc_0(&lcaddr)) die_nomem(); std_makepath(&fn,dir,subdir,"/subscribers/",lcch); std_makepath(&fnlock,dir,subdir,"/lock",0); if (!stralloc_copyb(&fnnew,fn.s,fn.len-1)) die_nomem(); /* code later depends on fnnew = fn + 'n' */ if (!stralloc_cats(&fnnew,"n")) die_nomem(); if (!stralloc_0(&fnnew)) die_nomem(); fdlock = lockfile(fnlock.s); /* do lower case hashed version first */ fdnew = open_trunc(fnnew.s); if (fdnew == -1) die_write(); substdio_fdbuf(&ssnew,write,fdnew,ssnewbuf,sizeof(ssnewbuf)); flagwasthere = 0; fd = open_read(fn.s); if (fd == -1) { if (errno != error_noent) { close(fdnew); die_read(); } } else { substdio_fdbuf(&ss,read,fd,ssbuf,sizeof(ssbuf)); for (;;) { if (getln(&ss,&line,&match,'\0') == -1) { close(fd); close(fdnew); die_read(); } if (!match) break; if (line.len == addr.len) if (!case_diffb(line.s,line.len,addr.s)) { flagwasthere = 1; if (!flagadd) continue; } if (substdio_bput(&ssnew,line.s,line.len) == -1) { close(fd); close(fdnew); die_write(); } } close(fd); } if (flagadd && !flagwasthere) if (substdio_bput(&ssnew,addr.s,addr.len) == -1) { close(fdnew); die_write(); } if (substdio_flush(&ssnew) == -1) { close(fdnew); die_write(); } if (fsync(fdnew) == -1) { close(fdnew); die_write(); } close(fdnew); if (rename(fnnew.s,fn.s) == -1) strerr_die6sys(111,FATAL,ERR_MOVE,fnnew.s," to ",fn.s,": "); if ((ch == lcch) || flagwasthere) { close(fdlock); if (flagadd ^ flagwasthere) { if (!stralloc_0(&addr)) die_nomem(); logaddr(dir,subdir,event,addr.s+1,comment); return 1; } return 0; } /* If unsub and not found and hashed differ, OR */ /* sub and not found (so added with new hash) */ /* do the 'case-dependent' hash */ fn.s[fn.len - 2] = ch; fnnew.s[fnnew.len - 3] = ch; fdnew = open_trunc(fnnew.s); if (fdnew == -1) die_write(); substdio_fdbuf(&ssnew,write,fdnew,ssnewbuf,sizeof(ssnewbuf)); fd = open_read(fn.s); if (fd == -1) { if (errno != error_noent) { close(fdnew); die_read(); } } else { substdio_fdbuf(&ss,read,fd,ssbuf,sizeof(ssbuf)); for (;;) { if (getln(&ss,&line,&match,'\0') == -1) { close(fd); close(fdnew); die_read(); } if (!match) break; if (line.len == addr.len) if (!case_diffb(line.s,line.len,addr.s)) { flagwasthere = 1; continue; /* always want to remove from case-sensitive hash */ } if (substdio_bput(&ssnew,line.s,line.len) == -1) { close(fd); close(fdnew); die_write(); } } close(fd); } if (substdio_flush(&ssnew) == -1) { close(fdnew); die_write(); } if (fsync(fdnew) == -1) { close(fdnew); die_write(); } close(fdnew); if (rename(fnnew.s,fn.s) == -1) strerr_die6sys(111,FATAL,ERR_MOVE,fnnew.s," to ",fn.s,": "); close(fdlock); if (flagadd ^ flagwasthere) { if (!stralloc_0(&addr)) die_nomem(); logaddr(dir,subdir,event,addr.s+1,comment); return 1; } return 0; }
void fatal(char *m1, char *m2) { strerr_die6sys(100, "runsvdir ", svdir, ": fatal: ", m1, m2, ": "); }
void fail(void) { strerr_die6sys(111,fatal,"unable to create ",dir,"/",fn,": "); }
int main(int argc,char **argv) { unsigned long ttl; struct stat st; int i; int j; int k; char ch; if (!*argv) die_usage(); if (!*++argv) die_usage(); fn = *argv; if (!*++argv) die_usage(); fnnew = *argv; if (!*++argv) die_usage(); if (str_diff(*argv,"add")) die_usage(); if (!*++argv) die_usage(); if (str_equal(*argv,"ns")) mode = '.'; else if (str_equal(*argv,"childns")) mode = '&'; else if (str_equal(*argv,"host")) mode = '='; else if (str_equal(*argv,"host6")) mode = '6'; else if (str_equal(*argv,"alias")) mode = '+'; else if (str_equal(*argv,"alias6")) mode = '3'; else if (str_equal(*argv,"mx")) mode = '@'; else die_usage(); if (!*++argv) die_usage(); if (!dns_domain_fromdot(&target,*argv,str_len(*argv))) nomem(); if (!*++argv) die_usage(); if (mode == '6' || mode == '3') { if (!ip6_scan(*argv,targetip6)) die_usage(); } else { if (!ip4_scan(*argv,targetip)) die_usage(); } umask(077); fd = open_read(fn); if (fd == -1) die_read(); if (fstat(fd,&st) == -1) die_read(); buffer_init(&b,buffer_unixread,fd,bspace,sizeof bspace); fdnew = open_trunc(fnnew); if (fdnew == -1) die_write(); if (fchmod(fdnew,st.st_mode & 0644) == -1) die_write(); buffer_init(&bnew,buffer_unixwrite,fdnew,bnewspace,sizeof bnewspace); switch(mode) { case '.': case '&': ttl = TTL_NS; for (i = 0;i < 26;++i) { ch = 'a' + i; if (!stralloc_copyb(&f[0],&ch,1)) nomem(); if (!stralloc_cats(&f[0],".ns.")) nomem(); if (!dns_domain_todot_cat(&f[0],target)) nomem(); if (!dns_domain_fromdot(&names[i],f[0].s,f[0].len)) nomem(); } break; case '+': case '=': case '6': case '3': ttl = TTL_POSITIVE; break; case '@': ttl = TTL_POSITIVE; for (i = 0;i < 26;++i) { ch = 'a' + i; if (!stralloc_copyb(&f[0],&ch,1)) nomem(); if (!stralloc_cats(&f[0],".mx.")) nomem(); if (!dns_domain_todot_cat(&f[0],target)) nomem(); if (!dns_domain_fromdot(&names[i],f[0].s,f[0].len)) nomem(); } break; } while (match) { if (getln(&b,&line,&match,'\n') == -1) die_read(); put(line.s,line.len); if (line.len && !match) put("\n",1); while (line.len) { ch = line.s[line.len - 1]; if ((ch != ' ') && (ch != '\t') && (ch != '\n')) break; --line.len; } if (!line.len) continue; if (line.s[0] == '#') continue; j = 1; for (i = 0;i < NUMFIELDS;++i) { if (j >= line.len) { if (!stralloc_copys(&f[i],"")) nomem(); } else { k = byte_chr(line.s + j,line.len - j,':'); if (!stralloc_copyb(&f[i],line.s + j,k)) nomem(); j += k + 1; } } switch(mode) { case '.': case '&': if (line.s[0] == mode) { if (!dns_domain_fromdot(&d1,f[0].s,f[0].len)) nomem(); if (dns_domain_equal(d1,target)) { if (byte_chr(f[2].s,f[2].len,'.') >= f[2].len) { if (!stralloc_cats(&f[2],".ns.")) nomem(); if (!stralloc_catb(&f[2],f[0].s,f[0].len)) nomem(); } if (!dns_domain_fromdot(&d2,f[2].s,f[2].len)) nomem(); if (!stralloc_0(&f[3])) nomem(); if (!scan_ulong(f[3].s,&ttl)) ttl = TTL_NS; for (i = 0;i < 26;++i) if (dns_domain_equal(d2,names[i])) { used[i] = 1; break; } } } break; case '=': if (line.s[0] == '=') { if (!dns_domain_fromdot(&d1,f[0].s,f[0].len)) nomem(); if (dns_domain_equal(d1,target)) strerr_die2x(100,FATAL,"host name already used"); if (!stralloc_0(&f[1])) nomem(); if (ip4_scan(f[1].s,ip)) if (byte_equal(ip,4,targetip)) strerr_die2x(100,FATAL,"IP address already used"); } break; case '6': if (line.s[0] == '6') { if (!dns_domain_fromdot(&d1,f[0].s,f[0].len)) nomem(); if (dns_domain_equal(d1,target)) strerr_die2x(100,FATAL,"host name already used"); if (!stralloc_0(&f[1])) nomem(); if (ip6_scan(f[1].s,ip6)) if (byte_equal(ip,16,targetip6)) strerr_die2x(100,FATAL,"IPv6 address already used"); } break; case '@': if (line.s[0] == '@') { if (!dns_domain_fromdot(&d1,f[0].s,f[0].len)) nomem(); if (dns_domain_equal(d1,target)) { if (byte_chr(f[2].s,f[2].len,'.') >= f[2].len) { if (!stralloc_cats(&f[2],".mx.")) nomem(); if (!stralloc_catb(&f[2],f[0].s,f[0].len)) nomem(); } if (!dns_domain_fromdot(&d2,f[2].s,f[2].len)) nomem(); if (!stralloc_0(&f[4])) nomem(); if (!scan_ulong(f[4].s,&ttl)) ttl = TTL_POSITIVE; for (i = 0;i < 26;++i) if (dns_domain_equal(d2,names[i])) { used[i] = 1; break; } } } break; } } if (!stralloc_copyb(&f[0],&mode,1)) nomem(); if (!dns_domain_todot_cat(&f[0],target)) nomem(); if (!stralloc_cats(&f[0],":")) nomem(); if (mode == '6' || mode == '3') { if (!stralloc_catb(&f[0],ip6str,ip6_fmt_flat(ip6str,targetip6))) nomem(); } else { if (!stralloc_catb(&f[0],ipstr,ip4_fmt(ipstr,targetip))) nomem(); } switch(mode) { case '.': case '&': case '@': for (i = 0;i < 26;++i) if (!used[i]) break; if (i >= 26) strerr_die2x(100,FATAL,"too many records for that domain"); ch = 'a' + i; if (!stralloc_cats(&f[0],":")) nomem(); if (!stralloc_catb(&f[0],&ch,1)) nomem(); if (mode == '@') if (!stralloc_cats(&f[0],":")) nomem(); break; } if (!stralloc_cats(&f[0],":")) nomem(); if (!stralloc_catb(&f[0],strnum,fmt_ulong(strnum,ttl))) nomem(); if (!stralloc_cats(&f[0],"\n")) nomem(); put(f[0].s,f[0].len); if (buffer_flush(&bnew) == -1) die_write(); if (fsync(fdnew) == -1) die_write(); if (close(fdnew) == -1) die_write(); /* NFS dorks */ if (rename(fnnew,fn) == -1) strerr_die6sys(111,FATAL,"unable to move ",fnnew," to ",fn,": "); _exit(0); }
int main(int argc, char **argv, char **envp) { char ch; struct cdbmake cm; array_t data = ARRAY_INIT(1); int32_t dlen; int fd; uint32_t i; array_t key = ARRAY_INIT(1); int32_t klen; char *path; char *tmp; if (!*argv || !*++argv) usage(); path = *argv; if (!*++argv) usage(); tmp = *argv; /* Create the temporary file and start the cdb creation process with it. */ fd = open("test.cdb", O_CREAT | O_TRUNC | O_WRONLY, 0644); if (fd == -1) strerr_die4sys(111, FATAL, "unable to create ", tmp, ": "); if (cdbmake_start(&cm, fd) == -1) strerr_die2sys(111, FATAL, "cdbmake initialization failed: "); for (;;) { /* Skip over new lines and require the first character to be '+'. */ ch = get_ch(); if (ch == '\n') break; if (ch != '+') die_format(); /* Read the key length. */ klen = get_len(','); if (klen == -1) die_format(); /* Read the data length. */ dlen = get_len(':'); if (dlen == -1) die_format(); /* Truncate the key array and load it with the key from the cdb record. */ array_trunc(&key); for (i = 0; i < klen; i++) { ch = get_ch(); array_append(&key, &ch, 1); } /* Verify the separator is ->. */ if ((get_ch() != '-') || (get_ch() != '>')) die_format(); /* Truncate the data array and load it with the data from the cdb record. */ array_trunc(&data); for (i = 0; i < dlen; i++) { ch = get_ch(); array_append(&data, &ch, 1); } /* The line is valid, so add it to the cdb file and check that it ends with * a new line. */ if (cdbmake_add(&cm, array_start(&key), klen, array_start(&data), dlen) == -1) die_write(); if (get_ch() != '\n') die_format(); } /* Finish the cdb file, sync it to disk, close it, and finally rename it to * the target path. */ if (cdbmake_finish(&cm) == -1) die_write(); if (fsync(fd) == -1) die_write(); if (close(fd) == -1) die_write(); if (rename(tmp, path) == -1) strerr_die6sys(111, FATAL, "unable to rename ", tmp, " to ", path, ": "); _exit(0); }
void main(int argc,char **argv) { char *dir; int fdlock; char *sender; int match; int flaginheader; int flagmodpost; int flagremote; const char *pmod; const char *err; int opt; unsigned int i; char szchar[2] = "-"; int child; (void) umask(022); sig_pipeignore(); if (!stralloc_copys(&sendopt,"-")) die_nomem(); while ((opt = getopt(argc,argv,"bBcCmMpPrRsSvVyY")) != opteof) switch(opt) { case 'b': flagbody = 1; break; case 'B': flagbody = 0; break; case 'm': flagmime = 1; break; case 'M': flagmime = 0; break; case 'p': flagpublic = 1; break; /* anyone can post (still moderated)*/ case 'P': flagpublic = 0; break; /* only moderators can post */ case 's': flagself = 1; break; /* modpost and DIR/mod diff fxns */ case 'S': flagself = 0; break; /* same fxn */ case 'y': flagconfirm = 1; break; /* force post confirmation */ case 'Y': flagconfirm = 0; break; /* disable post confirmation */ case 'c': /* ezmlm-send flags */ case 'C': case 'r': case 'R': szchar[0] = (char) opt & 0xff; if (!stralloc_append(&sendopt,szchar)) die_nomem(); break; case 'v': case 'V': strerr_die2x(0,"ezmlm-store version: ",auto_version); default: die_usage(); } sender = env_get("SENDER"); if (sender) { if (!*sender || str_equal(sender,"#@[]")) strerr_die2x(100,FATAL,ERR_BOUNCE); } startup(dir = argv[optind]); load_config(dir); if (flagconfirm == -1) flagconfirm = getconf_line(&confirmpost,"confirmpost",0,dir); else getconf_line(&confirmpost,"confirmpost",0,dir); flagmodpost = getconf_line(&moderators,"modpost",0,dir); flagremote = getconf_line(&line,"remote",0,dir); if (!flagmodpost && !flagconfirm) { /* not msg-mod. Pipe to ezmlm-send */ if ((child = wrap_fork()) == 0) wrap_execbin("/ezmlm-send", &sendopt, dir); /* parent */ wrap_exitcode(child); } if (!moderators.len || !(moderators.s[0] == '/')) { if (!stralloc_copys(&moderators,dir)) die_nomem(); if (!stralloc_cats(&moderators,"/mod")) die_nomem(); } if (!stralloc_0(&moderators)) die_nomem(); if (sender) { pmod = issub(moderators.s,0,sender); closesub(); /* sender = moderator? */ } else pmod = 0; if (!pmod && !flagpublic) strerr_die2x(100,FATAL,ERR_NO_POST); fdlock = lockfile("mod/lock"); if (!stralloc_copys(&mydtline, flagconfirm ? "Delivered-To: confirm to " : "Delivered-To: moderator for ")) die_nomem(); if (!stralloc_catb(&mydtline,outlocal.s,outlocal.len)) die_nomem(); if (!stralloc_append(&mydtline,"@")) die_nomem(); if (!stralloc_catb(&mydtline,outhost.s,outhost.len)) die_nomem(); if (!stralloc_cats(&mydtline,"\n")) die_nomem(); if (!stralloc_copys(&returnpath,"Return-Path: <")) die_nomem(); if (sender) { if (!stralloc_cats(&returnpath,sender)) die_nomem(); for (i = 14; i < returnpath.len;++i) if (returnpath.s[i] == '\n' || !returnpath.s[i] ) returnpath.s[i] = '_'; /* NUL and '\n' are bad, but we don't quote since this is */ /* only for ezmlm-moderate, NOT for SMTP */ } if (!stralloc_cats(&returnpath,">\n")) die_nomem(); pid = getpid(); /* unique file name */ for (i = 0;;++i) /* got lock - nobody else can add files */ { when = now(); /* when is also used later for date! */ if (!stralloc_copys(&fnmsg, flagconfirm?"mod/unconfirmed/":"mod/pending/")) die_nomem(); if (!stralloc_copyb(&fnbase,strnum,fmt_ulong(strnum,when))) die_nomem(); if (!stralloc_append(&fnbase,".")) die_nomem(); if (!stralloc_catb(&fnbase,strnum,fmt_ulong(strnum,pid))) die_nomem(); if (!stralloc_cat(&fnmsg,&fnbase)) die_nomem(); if (!stralloc_0(&fnmsg)) die_nomem(); if (stat(fnmsg.s,&st) == -1) if (errno == error_noent) break; /* really should never get to this point */ if (i == 2) strerr_die2x(111,FATAL,ERR_UNIQUE); sleep(2); } if (!stralloc_copys(&action,"-")) die_nomem(); if (!stralloc_cats(&action,flagconfirm?ACTION_DISCARD:ACTION_REJECT)) die_nomem(); if (!stralloc_cat(&action,&fnbase)) die_nomem(); if (!stralloc_0(&action)) die_nomem(); makeacthash(&action); if (!quote("ed,&outlocal)) die_nomem(); if (!stralloc_copy(&reject,"ed)) die_nomem(); if (!stralloc_cat(&reject,&action)) die_nomem(); if (!stralloc_0(&reject)) die_nomem(); if (!stralloc_copys(&action,"-")) die_nomem(); if (!stralloc_cats(&action,flagconfirm?ACTION_CONFIRM:ACTION_ACCEPT)) die_nomem(); if (!stralloc_cat(&action,&fnbase)) die_nomem(); if (!stralloc_0(&action)) die_nomem(); makeacthash(&action); if (!stralloc_copy(&accept,"ed)) die_nomem(); if (!stralloc_cat(&accept,&action)) die_nomem(); if (!stralloc_0(&accept)) die_nomem(); set_cptarget(accept.s); /* for copy () */ set_cpconfirm(reject.s,quoted.len); fdmsg = open_trunc(fnmsg.s); if (fdmsg == -1) strerr_die6sys(111,FATAL,ERR_WRITE,dir,"/",fnmsg.s,": "); substdio_fdbuf(&ssmsg,write,fdmsg,msgbuf,sizeof(msgbuf)); if (qmail_open(&qq, (stralloc *) 0) == -1) /* Open mailer */ strerr_die2sys(111,FATAL,ERR_QMAIL_QUEUE); hdr_add2("Mailing-List: ",mailinglist.s,mailinglist.len); if (listid.len > 0) hdr_add2("List-ID: ",listid.s,listid.len); hdr_datemsgid(when); if (flagconfirm) hdr_from("-owner"); else hdr_add2s("From: ",reject.s); hdr_add2s("Reply-To: ",accept.s); if (!flagconfirm && !pmod && flagremote) { /* if remote admin add -allow- address */ qmail_puts(&qq,"Cc: "); /* for ezmlm-gate users */ strnum[fmt_ulong(strnum,(unsigned long) when)] = 0; cookie(hash,key.s,key.len-FLD_ALLOW,strnum,sender,"t"); if (!stralloc_copy(&line,&outlocal)) die_nomem(); if (!stralloc_cats(&line,"-allow-tc.")) die_nomem(); if (!stralloc_cats(&line,strnum)) die_nomem(); if (!stralloc_append(&line,".")) die_nomem(); if (!stralloc_catb(&line,hash,COOKIE)) die_nomem(); if (!stralloc_append(&line,"-")) die_nomem(); i = str_rchr(sender,'@'); if (!stralloc_catb(&line,sender,i)) die_nomem(); if (sender[i]) { if (!stralloc_append(&line,"=")) die_nomem(); if (!stralloc_cats(&line,sender + i + 1)) die_nomem(); } qmail_put(&qq,line.s,line.len); qmail_puts(&qq,"@"); qmail_put(&qq,outhost.s,outhost.len); qmail_puts(&qq,"\n"); } qmail_puts(&qq,"To: <"); if (flagconfirm) { if (sender) qmail_puts(&qq, sender); } else { if (!quote("ed,&outlocal)) die_nomem(); qmail_put(&qq,quoted.s,quoted.len); qmail_puts(&qq,"-moderators@"); qmail_put(&qq,outhost.s,outhost.len); } qmail_puts(&qq,">\n"); /* FIXME: Drop the custom subject hack and use hdr_listsubject1 */ if (!stralloc_copys(&subject,"Subject: ")) die_nomem(); if (flagconfirm) { if (confirmpost.len) { if (!stralloc_cat(&subject,&confirmpost)) die_nomem(); if (!stralloc_cats(&subject," ")) die_nomem(); } else { if (!stralloc_cats(&subject,TXT_CONFIRM_POST)) die_nomem(); } } else { if (!stralloc_cats(&subject,TXT_MODERATE)) die_nomem(); } if (!quote("ed,&outlocal)) die_nomem(); if (!stralloc_cat(&subject,"ed)) die_nomem(); if (!stralloc_append(&subject,"@")) die_nomem(); if (!stralloc_cat(&subject,&outhost)) die_nomem(); if (flagmime) { hdr_mime(CTYPE_MULTIPART); qmail_put(&qq,subject.s,subject.len); hdr_boundary(0); hdr_ctype(CTYPE_TEXT); hdr_transferenc(); } else { qmail_put(&qq,subject.s,subject.len); qmail_puts(&qq,"\n\n"); } copy(&qq,flagconfirm?"text/post-confirm":"text/mod-request",flagcd); if (flagcd == 'B') { encodeB("",0,&line,2); qmail_put(&qq,line.s,line.len); } if (substdio_put(&ssmsg,returnpath.s,returnpath.len) == -1) die_msg(); if (substdio_put(&ssmsg,mydtline.s,mydtline.len) == -1) die_msg(); substdio_fdbuf(&ssin,read,0,inbuf,sizeof(inbuf)); if (flagmime) { hdr_boundary(0); hdr_ctype(CTYPE_MESSAGE); qmail_puts(&qq, "\n"); } qmail_put(&qq,returnpath.s,returnpath.len); qmail_put(&qq,mydtline.s,mydtline.len); flaginheader = 1; for (;;) { if (getln(&ssin,&line,&match,'\n') == -1) strerr_die2sys(111,FATAL,ERR_READ_INPUT); if (!match) break; if (line.len == 1) flaginheader = 0; if (flaginheader) { if ((line.len == mydtline.len) && !byte_diff(line.s,line.len,mydtline.s)) { close(fdmsg); /* be nice - clean up */ unlink(fnmsg.s); strerr_die2x(100,FATAL,ERR_LOOPING); } if (case_startb(line.s,line.len,"mailing-list:")) { close(fdmsg); /* be nice - clean up */ unlink(fnmsg.s); strerr_die2x(100,FATAL,ERR_MAILING_LIST); } } if (flagbody || flaginheader) /* skip body if !flagbody */ qmail_put(&qq,line.s,line.len); if (substdio_put(&ssmsg,line.s,line.len) == -1) die_msg(); } if (flagmime) hdr_boundary(1); /* close archive before qmail. Loss of qmail will result in re-run, and */ /* worst case this results in a duplicate msg sitting orphaned until it's */ /* cleaned out. */ if (substdio_flush(&ssmsg) == -1) die_msg(); if (fsync(fdmsg) == -1) die_msg(); if (fchmod(fdmsg,MODE_MOD_MSG | 0700) == -1) die_msg(); if (close(fdmsg) == -1) die_msg(); /* NFS stupidity */ close(fdlock); if (flagconfirm) { qmail_from(&qq,reject.s); /* envelope sender */ } else { if (!stralloc_copy(&line,&outlocal)) die_nomem(); if (!stralloc_cats(&line,"-return-@")) die_nomem(); if (!stralloc_cat(&line,&outhost)) die_nomem(); if (!stralloc_0(&line)) die_nomem(); qmail_from(&qq,line.s); /* envelope sender */ } if (flagconfirm) /* to sender */ qmail_to(&qq,sender); else if (pmod) /* to moderator only */ qmail_to(&qq,pmod); else { if (flagself) { /* to all moderators */ if (!stralloc_copys(&moderators,dir)) die_nomem(); if (!stralloc_cats(&moderators,"/mod")) die_nomem(); if (!stralloc_0(&moderators)) die_nomem(); } putsubs(moderators.s,0,0,52,subto,1); } if (*(err = qmail_close(&qq)) == '\0') { strnum[fmt_ulong(strnum,qmail_qp(&qq))] = 0; strerr_die2x(0,"ezmlm-store: info: qp ",strnum); } else strerr_die3x(111,FATAL,ERR_TMP_QMAIL_QUEUE,err+1); }
void die_read() { strerr_die6sys(111,FATAL,"unable to read ",dir,"/",fn.s,": "); }