?? qmail-local.c
字號:
//向本地郵件系統(tǒng)上的用戶投遞消息
#include <sys/types.h>#include <sys/stat.h>#include "readwrite.h"#include "sig.h"#include "env.h"#include "byte.h"#include "exit.h"#include "fork.h"#include "open.h"#include "wait.h"#include "lock.h"#include "seek.h"#include "substdio.h"#include "getln.h"#include "strerr.h"#include "subfd.h"#include "sgetopt.h"#include "alloc.h"#include "error.h"#include "stralloc.h"#include "fmt.h"#include "str.h"#include "now.h"#include "case.h"#include "quote.h"#include "qmail.h"#include "slurpclose.h"#include "myctime.h"#include "gfrom.h"#include "auto_patrn.h"void usage() { strerr_die1x(100,"qmail-local: usage: qmail-local [ -nN ] user homedir local dash ext domain sender aliasempty"); }void temp_nomem() { strerr_die1x(111,"Out of memory. (#4.3.0)"); }void temp_rewind() { strerr_die1x(111,"Unable to rewind message. (#4.3.0)"); }void temp_childcrashed() { strerr_die1x(111,"Aack, child crashed. (#4.3.0)"); }void temp_fork() { strerr_die3x(111,"Unable to fork: ",error_str(errno),". (#4.3.0)"); }void temp_read() { strerr_die3x(111,"Unable to read message: ",error_str(errno),". (#4.3.0)"); }void temp_slowlock(){ strerr_die1x(111,"File has been locked for 30 seconds straight. (#4.3.0)"); }void temp_qmail(fn) char *fn;{ strerr_die5x(111,"Unable to open ",fn,": ",error_str(errno),". (#4.3.0)"); }int flagdoit;int flag99;char *user;char *homedir;char *local;char *dash;char *ext;char *host;char *sender;char *aliasempty;stralloc safeext = {0};stralloc ufline = {0};stralloc rpline = {0};stralloc envrecip = {0};stralloc dtline = {0};stralloc qme = {0};stralloc ueo = {0};stralloc cmds = {0};stralloc messline = {0};stralloc foo = {0};char buf[1024];char outbuf[1024];/* child process */char fntmptph[80 + FMT_ULONG * 2];char fnnewtph[80 + FMT_ULONG * 2];void tryunlinktmp() { unlink(fntmptph); }void sigalrm() { tryunlinktmp(); _exit(3); }void maildir_child(dir)char *dir;{ unsigned long pid; unsigned long time; char host[64]; char *s; int loop; struct stat st; int fd; substdio ss; substdio ssout; sig_alarmcatch(sigalrm); if (chdir(dir) == -1) { if (error_temp(errno)) _exit(1); _exit(2); } pid = getpid(); host[0] = 0; gethostname(host,sizeof(host)); for (loop = 0;;++loop) { time = now(); s = fntmptph; s += fmt_str(s,"tmp/"); s += fmt_ulong(s,time); *s++ = '.'; s += fmt_ulong(s,pid); *s++ = '.'; s += fmt_strn(s,host,sizeof(host)); *s++ = 0; if (stat(fntmptph,&st) == -1) if (errno == error_noent) break; /* really should never get to this point */ if (loop == 2) _exit(1); sleep(2); } str_copy(fnnewtph,fntmptph); byte_copy(fnnewtph,3,"new"); alarm(86400); fd = open_excl(fntmptph); if (fd == -1) _exit(1); substdio_fdbuf(&ss,read,0,buf,sizeof(buf)); substdio_fdbuf(&ssout,write,fd,outbuf,sizeof(outbuf)); if (substdio_put(&ssout,rpline.s,rpline.len) == -1) goto fail; if (substdio_put(&ssout,dtline.s,dtline.len) == -1) goto fail; switch(substdio_copy(&ssout,&ss)) { case -2: tryunlinktmp(); _exit(4); case -3: goto fail; } if (substdio_flush(&ssout) == -1) goto fail; if (fsync(fd) == -1) goto fail; if (close(fd) == -1) goto fail; /* NFS dorks */ if (link(fntmptph,fnnewtph) == -1) goto fail; /* if it was error_exist, almost certainly successful; i hate NFS */ tryunlinktmp(); _exit(0); fail: tryunlinktmp(); _exit(1);}/* end child process */void maildir(fn)char *fn;{ int child; int wstat; if (seek_begin(0) == -1) temp_rewind(); switch(child = fork()) { case -1: temp_fork(); case 0: maildir_child(fn); _exit(111); } wait_pid(&wstat,child); if (wait_crashed(wstat)) temp_childcrashed(); switch(wait_exitcode(wstat)) { case 0: break; case 2: strerr_die1x(111,"Unable to chdir to maildir. (#4.2.1)"); case 3: strerr_die1x(111,"Timeout on maildir delivery. (#4.3.0)"); case 4: strerr_die1x(111,"Unable to read message. (#4.3.0)"); default: strerr_die1x(111,"Temporary error on maildir delivery. (#4.3.0)"); }}void mailfile(fn)char *fn;{ int fd; substdio ss; substdio ssout; int match; seek_pos pos; int flaglocked; if (seek_begin(0) == -1) temp_rewind(); fd = open_append(fn); if (fd == -1) strerr_die5x(111,"Unable to open ",fn,": ",error_str(errno),". (#4.2.1)"); sig_alarmcatch(temp_slowlock); alarm(30); flaglocked = (lock_ex(fd) != -1); alarm(0); sig_alarmdefault(); seek_end(fd); pos = seek_cur(fd); substdio_fdbuf(&ss,read,0,buf,sizeof(buf)); substdio_fdbuf(&ssout,write,fd,outbuf,sizeof(outbuf)); if (substdio_put(&ssout,ufline.s,ufline.len)) goto writeerrs; if (substdio_put(&ssout,rpline.s,rpline.len)) goto writeerrs; if (substdio_put(&ssout,dtline.s,dtline.len)) goto writeerrs; for (;;) { if (getln(&ss,&messline,&match,'\n') != 0) { strerr_warn3("Unable to read message: ",error_str(errno),". (#4.3.0)",0); if (flaglocked) seek_trunc(fd,pos); close(fd); _exit(111); } if (!match && !messline.len) break; if (gfrom(messline.s,messline.len)) if (substdio_bput(&ssout,">",1)) goto writeerrs; if (substdio_bput(&ssout,messline.s,messline.len)) goto writeerrs; if (!match) { if (substdio_bputs(&ssout,"\n")) goto writeerrs; break; } } if (substdio_bputs(&ssout,"\n")) goto writeerrs; if (substdio_flush(&ssout)) goto writeerrs; if (fsync(fd) == -1) goto writeerrs; close(fd); return; writeerrs: strerr_warn5("Unable to write ",fn,": ",error_str(errno),". (#4.3.0)",0); if (flaglocked) seek_trunc(fd,pos); close(fd); _exit(111);}void mailprogram(prog)char *prog;{ int child; char *(args[4]); int wstat; if (seek_begin(0) == -1) temp_rewind(); switch(child = fork()) { case -1: temp_fork(); case 0: args[0] = "/bin/sh"; args[1] = "-c"; args[2] = prog; args[3] = 0; sig_pipedefault(); execv(*args,args); strerr_die3x(111,"Unable to run /bin/sh: ",error_str(errno),". (#4.3.0)"); } wait_pid(&wstat,child); if (wait_crashed(wstat)) temp_childcrashed(); switch(wait_exitcode(wstat)) { case 100: case 64: case 65: case 70: case 76: case 77: case 78: case 112: _exit(100); case 0: break; case 99: flag99 = 1; break; default: _exit(111); }}unsigned long mailforward_qp = 0;void mailforward(recips)char **recips;{ struct qmail qqt; char *qqx; substdio ss; int match; if (seek_begin(0) == -1) temp_rewind(); substdio_fdbuf(&ss,read,0,buf,sizeof(buf)); if (qmail_open(&qqt) == -1) temp_fork(); mailforward_qp = qmail_qp(&qqt); qmail_put(&qqt,dtline.s,dtline.len); do { if (getln(&ss,&messline,&match,'\n') != 0) { qmail_fail(&qqt); break; } qmail_put(&qqt,messline.s,messline.len); } while (match); qmail_from(&qqt,ueo.s); while (*recips) qmail_to(&qqt,*recips++); qqx = qmail_close(&qqt); if (!*qqx) return; strerr_die3x(*qqx == 'D' ? 100 : 111,"Unable to forward message: ",qqx + 1,".");}void bouncexf(){ int match; substdio ss; if (seek_begin(0) == -1) temp_rewind(); substdio_fdbuf(&ss,read,0,buf,sizeof(buf)); for (;;) { if (getln(&ss,&messline,&match,'\n') != 0) temp_read(); if (!match) break; if (messline.len <= 1) break; if (messline.len == dtline.len) if (!str_diffn(messline.s,dtline.s,dtline.len)) strerr_die1x(100,"This message is looping: it already has my Delivered-To line. (#5.4.6)"); }}void checkhome(){ struct stat st; if (stat(".",&st) == -1) strerr_die3x(111,"Unable to stat home directory: ",error_str(errno),". (#4.3.0)"); if (st.st_mode & auto_patrn) strerr_die1x(111,"Uh-oh: home directory is writable. (#4.7.0)"); if (st.st_mode & 01000) if (flagdoit) strerr_die1x(111,"Home directory is sticky: user is editing his .qmail file. (#4.2.1)"); else strerr_warn1("Warning: home directory is sticky.",0);}int qmeox(dashowner)char *dashowner;{ struct stat st; if (!stralloc_copys(&qme,".qmail")) temp_nomem(); if (!stralloc_cats(&qme,dash)) temp_nomem(); if (!stralloc_cat(&qme,&safeext)) temp_nomem(); if (!stralloc_cats(&qme,dashowner)) temp_nomem(); if (!stralloc_0(&qme)) temp_nomem(); if (stat(qme.s,&st) == -1) { if (error_temp(errno)) temp_qmail(qme.s); return -1; } return 0;}int qmeexists(fd,cutable)int *fd;int *cutable;{ struct stat st;
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -