qmail-local程式碼分析(轉)
qmail-local程式碼分析(轉)[@more@]我分析的程式碼沒有“夜未眠”大哥的好,可能還有的不正確,就請各位多多指教,謝謝程式碼:#include #include #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); }/*刪除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/");/*將"tmp/"拷到s中*/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");//時間為24小時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));//dtline:郵件頭Delivered-To部分//rpline:郵件頭返回路徑//無需"From "頭部if (substdio_put(&ssout,rpline.s,rpline.len) == -1) goto fail;if (substdio_put(&ssout,dtline.s,dtline.len) == -1) goto fail;//將郵件寫到檔案fd中switch(substdio_copy(&ssout,&ss)){case -2: tryunlinktmp(); _exit(4);case -3: goto fail;}if (substdio_flush(&ssout) == -1) goto fail;//將fd所指檔案資料由系統緩衝區寫回磁碟正確返回0,錯誤返回-1if (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 *///maildir 格式郵箱的郵件投遞,不要鎖定void maildir(fn)char *fn;{int child;int wstat;//#define seek_begin(fd) (seek_set((fd),(seek_pos) 0))//指向檔案0的開頭if (seek_begin(0) == -1) temp_rewind();switch(child = fork()){case -1:temp_fork();case 0:maildir_child(fn);/////////////////////////////////////_exit(111);}//返回子程式fd的結束狀態值於wstat中wait_pid(&wstat,child);//#define wait_crashed(w) ((w) & 127)if (wait_crashed(wstat))temp_childcrashed();//#define wait_exitcode(w) ((w) >> 8) 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)");}}//mbox 格式郵箱的郵件投遞,必須鎖定void mailfile(fn)char *fn;{int fd;substdio ss;substdio ssout;int match;seek_pos pos;int flaglocked;//到檔案0開頭if (seek_begin(0) == -1) temp_rewind();//開啟檔案fnfd = open_append(fn);if (fd == -1)strerr_die5x(111,"Unable to open ",fn,": ",error_str(errno),". (#4.2.1)");//時間訊號,30秒sig_alarmcatch(temp_slowlock);alarm(30);//鎖定flaglocked = (lock_ex(fd) != -1);alarm(0);sig_alarmdefault();//結尾seek_end(fd);//pos實際指向檔案尾(檔案大小)pos = seek_cur(fd);substdio_fdbuf(&ss,read,0,buf,sizeof(buf));substdio_fdbuf(&ssout,write,fd,outbuf,sizeof(outbuf));//dtline:郵件頭Delivered-To部分//rpline:郵件頭返回路徑//ufline:mbox 是標準的UNIX郵箱格式, 多個郵件存放在一個獨立檔案內, 每個郵件由一個"From" 的行開始.//這一行看起來像一個標題欄位, 不過那不是標題, 那僅僅是傳送代理新增的, 便於郵件讀出器可以找到每個郵件開始部分的一個標記.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,'
') != 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,"
")) goto writeerrs;break;}}if (substdio_bputs(&ssout,"
")) 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;//轉發郵件,地址在recips中void mailforward(recips)char **recips;{//struct qmail {// int flagerr;// unsigned long pid;// int fdm;// int fde;// substdio ss;// char buf[1024];// } ;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,'
') != 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;//#define seek_begin(fd) (seek_set((fd),(seek_pos) 0))//typedef unsigned long seek_pos//將檔案0的指標移到開始位置。if (seek_begin(0) == -1) temp_rewind();//給ss附值,ss->x=buf,s->fd = 0;s->op = read;s->p = 0(位元組數);s->n = sizeof(buf)(還有的空間)substdio_fdbuf(&ss,read,0,buf,sizeof(buf));for (;;){if (getln(&ss,&messline,&match,'
') != 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)");elsestrerr_warn1("Warning: home directory is sticky.",0);}//得到檔案".qmail"+dash+safeext+dashowner的許可權,正確返回0,錯誤為-1int 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;}//qme檔案存在且是一般檔案返回1,否則為0int qmeexists(fd,cutable)int *fd;int *cutable;{struct stat st;if (!stralloc_0(&qme)) temp_nomem();*fd = open_read(qme.s);if (*fd == -1) {if (error_temp(errno)) temp_qmail(qme.s);if (errno == error_perm) temp_qmail(qme.s);if (errno == error_acces) temp_qmail(qme.s);return 0;}if (fstat(*fd,&st) == -1) temp_qmail(qme.s);//S_IFREG表示一般檔案 if ((st.st_mode & S_IFMT) == S_IFREG) {if (st.st_mode & auto_patrn)strerr_die1x(111,"Uh-oh: .qmail file is writable. (#4.7.0)");*cutable = !!(st.st_mode & 0100);//看檔案的owner許可權是否為可執行的。是*cutable = 1,不是*cutable = 0return 1;}close(*fd);return 0;}/* "" "": "" *//* "-/" "": "-/" "-/default" *//* "-/" "a": "-/a" "-/default" *//* "-/" "a-": "-/a-" "-/a-default" "-/default" *//* "-/" "a-b": "-/a-b" "-/a-default" "-/default" *//* "-/" "a-b-": "-/a-b-" "-/a-b-default" "-/a-default" "-/default" *//* "-/" "a-b-c": "-/a-b-c" "-/a-b-default" "-/a-default" "-/default" *///開啟檔案&qme,如是一般檔案再看是否為default,如果是,"DEFAULT"+*(ext+i)結合加入void qmesearch(fd,cutable)int *fd;int *cutable;{int i;if (!stralloc_copys(&qme,".qmail")) temp_nomem();if (!stralloc_cats(&qme,dash)) temp_nomem();if (!stralloc_cat(&qme,&safeext)) temp_nomem();if (qmeexists(fd,cutable)) {if (safeext.len >= 7) {i = safeext.len - 7;if (!byte_diff("default",7,safeext.s + i))if (i <= str_len(ext)) /* paranoia */if (!env_put2("DEFAULT",ext + i)) temp_nomem();}return;}for (i = safeext.len;i >= 0;--i)if (!i || (safeext.s[i - 1] == '-')) {if (!stralloc_copys(&qme,".qmail")) temp_nomem();if (!stralloc_cats(&qme,dash)) temp_nomem();if (!stralloc_catb(&qme,safeext.s,i)) temp_nomem();if (!stralloc_cats(&qme,"default")) temp_nomem();if (qmeexists(fd,cutable)) {if (i <= str_len(ext)) /* paranoia */if (!env_put2("DEFAULT",ext + i)) temp_nomem();return;}}*fd = -1;}unsigned long count_file = 0;unsigned long count_forward = 0;unsigned long count_program = 0;char count_buf[FMT_ULONG];void count_print(){substdio_puts(subfdoutsmall,"did ");substdio_put(subfdoutsmall,count_buf,fmt_ulong(count_buf,count_file));substdio_puts(subfdoutsmall,"+");substdio_put(subfdoutsmall,count_buf,fmt_ulong(count_buf,count_forward));substdio_puts(subfdoutsmall,"+");substdio_put(subfdoutsmall,count_buf,fmt_ulong(count_buf,count_program));substdio_puts(subfdoutsmall,"
");if (mailforward_qp){substdio_puts(subfdoutsmall,"qp ");substdio_put(subfdoutsmall,count_buf,fmt_ulong(count_buf,mailforward_qp));substdio_puts(subfdoutsmall,"
");}substdio_flush(subfdoutsmall);}void sayit(type,cmd,len)char *type;char *cmd;int len;{substdio_puts(subfdoutsmall,type);substdio_put(subfdoutsmall,cmd,len);substdio_putsflush(subfdoutsmall,"
");}void main(argc,argv)int argc;char **argv;{int opt;int i;int j;int k;int fd;int numforward;char **recips;datetime_sec starttime;int flagforwardonly;char *x;umask(077);//將系統umask值設為077&0777的值。open函式的真正許可權為mode&-umasksig_pipeignore();//忽略訊號//將environ空間擴大(加10個字串位置)錯誤返回0if (!env_init()) temp_nomem();//-n Instead of reading and delivering the message, print a description of// the delivery instructions. (man page)//-N 是預設值flagdoit = 1;while ((opt = getopt(argc,argv,"nN")) != opteof)switch(opt){case 'n': flagdoit = 0; break;case 'N': flagdoit = 1; break;default:usage();}argc -= optind;argv += optind;//將引數拷到相應的變數中。if (!(user = *argv++)) usage();if (!(homedir = *argv++)) usage();if (!(local = *argv++)) usage();if (!(dash = *argv++)) usage();if (!(ext = *argv++)) usage();if (!(host = *argv++)) usage();if (!(sender = *argv++)) usage();if (!(aliasempty = *argv++)) usage();if (*argv) usage();//目錄是以'/'開頭的if (homedir[0] != '/') usage();if (chdir(homedir) == -1)strerr_die5x(111,"Unable to switch to ",homedir,": ",error_str(errno),". (#4.3.0)");checkhome();//將"HOST"和host結合為"HOST="+host,加到environ後面。下同if (!env_put2("HOST",host)) temp_nomem();//接收地址的域名部分if (!env_put2("HOME",homedir)) temp_nomem();//使用者的主目錄if (!env_put2("USER",user)) temp_nomem();//當前的使用者if (!env_put2("LOCAL",local)) temp_nomem();//接收地址的local部分//將本地的地址擴充套件。如local為"dingwenbin",host為pact518.hit.edu.cn,則envrecip為"dingwenbin@pact518.hit.edu.cn"if (!stralloc_copys(&envrecip,local)) temp_nomem();if (!stralloc_cats(&envrecip,"@")) temp_nomem();if (!stralloc_cats(&envrecip,host)) temp_nomem();//將envrecip->s加'Z'拷到foo->s.if (!stralloc_copy(&foo,&envrecip)) temp_nomem();//#define stralloc_0(sa) stralloc_append(sa,"")//GEN_ALLOC_append(stralloc,char,s,len,a,i,n,x,30,stralloc_readyplus,stralloc_append)//struct stralloc{char *s;int len;int a;},len是s的長度,a是總共分配的空間。//stralloc_ready(x,n)作用是:x沒有分配空間就分配n大小空間。已分配了且空間小於n就擴大空間//stralloc_readyplus(x,n)作用是:x沒有分配空間就分配n大小空間。分配給x的空間小於x->len+n,就擴大空間if (!stralloc_0(&foo)) temp_nomem();//將"RECIPIENT"和foo.s結合為"RECIPIENT="+foo.s,加到environ後面。下同//信封上接收者的地址 if (!env_put2("RECIPIENT",foo.s)) temp_nomem();//郵件頭Delivered-To部分if (!stralloc_copys(&dtline,"Delivered-To: ")) temp_nomem();if (!stralloc_cat(&dtline,&envrecip)) temp_nomem();for (i = 0;i < dtline.len;++i) if (dtline.s[i] == '
') dtline.s[i] = '_';if (!stralloc_cats(&dtline,"
")) temp_nomem();if (!stralloc_copy(&foo,&dtline)) temp_nomem();if (!stralloc_0(&foo)) temp_nomem();if (!env_put2("DTLINE",foo.s)) temp_nomem();if (flagdoit)bouncexf();//將"SENDER"和sender結合為"SENDER="+sender,加到environ後面。// 信封上傳送者地址 if (!env_put2("SENDER",sender)) temp_nomem();//將"RPLINE"和"Return-Path:
"結合後加入environif (!quote2(&foo,sender)) temp_nomem();if (!stralloc_copys(&rpline,"Return-Path: if (!stralloc_cat(&rpline,&foo)) temp_nomem();for (i = 0;i < rpline.len;++i) if (rpline.s[i] == '
') rpline.s[i] = '_';if (!stralloc_cats(&rpline,">
")) temp_nomem();if (!stralloc_copy(&foo,&rpline)) temp_nomem();if (!stralloc_0(&foo)) temp_nomem();//郵件頭返回路徑 if (!env_put2("RPLINE",foo.s)) temp_nomem();//將"From"+*sender拷到ufline中。*sender為空,則將"From"+"MAILER-DAEMON"拷進去 if (!stralloc_copys(&ufline,"From ")) temp_nomem();if (*sender){int len; int i; char ch;len = str_len(sender);if (!stralloc_readyplus(&ufline,len)) temp_nomem();for (i = 0;i < len;++i){ch = sender[i];if ((ch == ' ') || (ch == ' ') || (ch == '
')) ch = '-';ufline.s[ufline.len + i] = ch;}ufline.len += len;}elseif (!stralloc_cats(&ufline,"MAILER-DAEMON")) temp_nomem();if (!stralloc_cats(&ufline," ")) temp_nomem();//在ufline後面加上現在時間。starttime = now();if (!stralloc_cats(&ufline,myctime(starttime))) temp_nomem();if (!stralloc_copy(&foo,&ufline)) temp_nomem();if (!stralloc_0(&foo)) temp_nomem();//UUCP風格的"From"行它包含訊息所參與的UUCP大宗//路徑形式的路由、最後一臺接收訊息的機器處理訊息的時間和日期以及一//指明從哪臺主機接收來的可選部分。由於每個處理過這個訊息的系統都會生成這個欄位,所//以它通常包括在信封資料下。if (!env_put2("UFLINE",foo.s)) temp_nomem();//到空行的作用是:如果ext為"aa-bb-cc-dd",則依次把"EXT=aa-bb-cc-dd","EXT2=bb-cc-dd","EXT3=cc-dd","EXT4=dd"加入//地址擴充套件x = ext;if (!env_put2("EXT",x)) temp_nomem();x += str_chr(x,'-'); if (*x) ++x;if (!env_put2("EXT2",x)) temp_nomem();x += str_chr(x,'-'); if (*x) ++x;if (!env_put2("EXT3",x)) temp_nomem();x += str_chr(x,'-'); if (*x) ++x;if (!env_put2("EXT4",x)) temp_nomem();if (!stralloc_copys(&safeext,ext)) temp_nomem();//將safeext中字串轉化為小寫的case_lowerb(safeext.s,safeext.len);for (i = 0;i < safeext.len;++i)if (safeext.s[i] == '.')safeext.s[i] = ':';//例如host為202.18.236.150,則"HOST2=202.18.236","HOST3=202.18","HOST4=202",加入其中//接收地址的域名部分 i = str_len(host);i = byte_rchr(host,i,'.');if (!stralloc_copyb(&foo,host,i)) temp_nomem();if (!stralloc_0(&foo)) temp_nomem();if (!env_put2("HOST2",foo.s)) temp_nomem();i = byte_rchr(host,i,'.');if (!stralloc_copyb(&foo,host,i)) temp_nomem();if (!stralloc_0(&foo)) temp_nomem();if (!env_put2("HOST3",foo.s)) temp_nomem();i = byte_rchr(host,i,'.');if (!stralloc_copyb(&foo,host,i)) temp_nomem();if (!stralloc_0(&foo)) temp_nomem();if (!env_put2("HOST4",foo.s)) temp_nomem();flagforwardonly = 0;qmesearch(&fd,&flagforwardonly);if (fd == -1)/*檔案沒開啟*/if (*dash)strerr_die1x(100,"Sorry, no mailbox here by that name. (#5.1.1)");if (!stralloc_copys(&ueo,sender)) temp_nomem();if (str_diff(sender,""))/*sender不空*/if (str_diff(sender,"#@[]"))/*sender和"#@[]"不同*/if (qmeox("-owner") == 0){if (qmeox("-owner-default") == 0){if (!stralloc_copys(&ueo,local)) temp_nomem();if (!stralloc_cats(&ueo,"-owner-@")) temp_nomem();if (!stralloc_cats(&ueo,host)) temp_nomem();if (!stralloc_cats(&ueo,"-@[]")) temp_nomem();}/*ueo為local+"-owner-@"+host+"-@[]"*/else{if (!stralloc_copys(&ueo,local)) temp_nomem();if (!stralloc_cats(&ueo,"-owner@")) temp_nomem();if (!stralloc_cats(&ueo,host)) temp_nomem();}/*ueo為local+"-owner@"+host*/}if (!stralloc_0(&ueo)) temp_nomem();//轉發的傳送人地址if (!env_put2("NEWSENDER",ueo.s)) temp_nomem();if (!stralloc_ready(&cmds,0)) temp_nomem();cmds.len = 0;if (fd != -1)if (slurpclose(fd,&cmds,256) == -1) temp_nomem();if (!cmds.len)/*如果fd檔案中沒有內容*/{if (!stralloc_copys(&cmds,aliasempty)) temp_nomem();flagforwardonly = 0;}if (!cmds.len || (cmds.s[cmds.len - 1] != '
'))if (!stralloc_cats(&cmds,"
")) temp_nomem();numforward = 0;/*檢查有幾行的第一個字元不是'#','.','/','|'*/i = 0;/*i為每行的開始位置*/for (j = 0;j < cmds.len;++j)if (cmds.s[j] == '
'){switch(cmds.s[i]) { case '#': case '.': case '/': case '|': break;default: ++numforward; }i = j + 1;}recips = (char **) alloc((numforward + 1) * sizeof(char *));if (!recips) temp_nomem();numforward = 0;flag99 = 0;i = 0;for (j = 0;j < cmds.len;++j)if (cmds.s[j] == '
'){cmds.s[j] = 0;k = j;while ((k > i) && (cmds.s[k - 1] == ' ') || (cmds.s[k - 1] == ' '))cmds.s[--k] = 0;// 字元 傳送型別 值 // # 無 (註釋) 忽略// | 程式 由shell 執行的命令 // / 或者 . mbox郵箱格式 (如果路徑最後一個字元不是一個斜槓) mbox 的路徑名 (包括斜槓"/"或者 點".")// / 或者 . maildir郵箱格式 (如果路徑最後一個字元是一個反斜槓) maildir 的路徑名 (包括斜槓"/"或者 點".") // & 轉發 轉發郵件的地址 // 字母或者數字 轉發 轉發郵件的地址 (包括第一個字元) switch(cmds.s[i]){case 0: /* k == i */if (i) break;strerr_die1x(111,"Uh-oh: first line of .qmail file is blank. (#4.2.1)");case '#':break;case '.':case '/':++count_file;if (flagforwardonly) strerr_die1x(111,"Uh-oh: .qmail has file delivery but has x bit set. (#4.7.0)");if (cmds.s[k - 1] == '/')if (flagdoit) maildir(cmds.s + i);///////////////////////////////////////////else sayit("maildir ",cmds.s + i,k - i);elseif (flagdoit) mailfile(cmds.s + i);else sayit("mbox ",cmds.s + i,k - i);break;case '|':++count_program;if (flagforwardonly) strerr_die1x(111,"Uh-oh: .qmail has prog delivery but has x bit set. (#4.7.0)");if (flagdoit) mailprogram(cmds.s + i + 1);else sayit("program ",cmds.s + i + 1,k - i - 1);break;case '+':if (str_equal(cmds.s + i + 1,"list"))flagforwardonly = 1;break;case '&':++i;default:++count_forward;if (flagdoit) recips[numforward++] = cmds.s + i;else sayit("forward ",cmds.s + i,k - i);break;}i = j + 1;if (flag99) break;}//轉發的地址數不為0就轉發if (numforward) if (flagdoit){recips[numforward] = 0;mailforward(recips);}count_print();_exit(0);
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/8225414/viewspace-944742/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Linux核心分析--系統呼叫實現程式碼分析(轉)Linux
- SQL worm sapphire 關鍵程式碼分析 (轉)SQLWormAPP
- 程式碼分析
- AsyncTask 程式碼分析
- 對.NET Framework "事件"機制理解的程式碼分析 (轉)Framework事件
- 微信小程式-開心大轉盤(圓盤指標)程式碼分析微信小程式指標
- Win2K下關聯程式/埠之程式碼初步分析(轉)
- 以太坊原始碼分析(5)accounts程式碼分析原始碼
- duwamish7的一些程式碼分析總結 (轉)
- ORACLE常見錯誤程式碼的分析與解決(轉)Oracle
- boost::any原始碼分析 (轉)原始碼
- LNet程式碼分析
- beego框架程式碼分析Go框架
- MGJRouter程式碼分析
- 藉助ai來分析程式碼,理解程式碼AI
- gzip-1.2.4程式分析 (轉)
- 精妙程式碼 (轉)
- 中綴轉字尾表示式思路分析和程式碼實現
- 劍指offer—58_2.左旋轉字串—分析及程式碼(Java)字串Java
- Linux作業系統的許可權程式碼分析【轉】Linux作業系統
- qt程式建立及模板程式碼分析QT
- 搭建sonarqube分析golang程式碼Golang
- golang http/transport 程式碼分析GolangHTTP
- JS彈幕程式碼分析JS
- kvm-PLE程式碼分析
- 程式碼覆蓋率分析
- 1初學程式碼分析
- php4.0.0遠端溢位原始碼分析與測試程式 (轉)PHP原始碼
- java 程式碼格式(轉)Java
- 程式碼的味道 (轉)
- ABAP程式碼分析工具 - 事務碼SQF
- 原始碼分析Gateway請求轉發原始碼Gateway
- sidecar-inject程式碼分析IDE
- YYModel程式碼分析筆記筆記
- 禁止百度轉碼程式碼
- 劍指offer—58.翻轉單詞順序列—分析及程式碼(Java)Java
- 無程式碼相對於低程式碼的優勢分析
- 程式碼效能分析-Dottrace跟蹤程式碼執行時間