qmail-queue源代码分析 Programmer:夜未眠 Comefrom:ChongQing Gearbox co.,ltd 程序主要完成的功能是: 1.生成自已的邮件首部,也就是你在邮件头中见到的类似下面的东西 Recevied (qmail 855 invoked by uid 0); 2 May 2003 12:18:09 -0000 2.建立3个文件 queue/mess/ / //邮件正文 queue/intd/ 用户id,进程id,mailfrom,rcptto queue/todo/ 是intd目录下文件的复本. 3.写命名管道lock/trigger通知新邮件
#define DEATH 86400 /* 24 hours; _must_ be below q-s's OSSIFIED (36 hours) */ #define ADDR 1003
char inbuf[2048]; struct substdio ssin; char outbuf[256]; struct substdio ssout;
datetime_sec starttime; struct datetime dt; unsigned long mypid; unsigned long uid; char *pidfn; struct stat pidst; unsigned long messnum; char *messfn; char *todofn; char *intdfn; int messfd; int intdfd; int flagmademess = 0; int flagmadeintd = 0;
//错误清理 void cleanup() { if (flagmadeintd) { seek_trunc(intdfd,0); if (unlink(intdfn) == -1) return; } if (flagmademess) { seek_trunc(messfd,0); if (unlink(messfn) == -1) return; } }
void die(e) int e; { _exit(e); } void die_write() { cleanup(); die(53); } void die_read() { cleanup(); die(54); } void sigalrm() { /* thou shalt not clean up here */ die(52); } void sigbug() { die(81); }
unsigned int receivedlen; char *received;
static unsigned int receivedfmt(s) char *s; { unsigned int i; unsigned int len; len = 0; /*生成 /* "Received: (qmail-queue invoked by alias); 26 Sep 1995 04:46:54 -0000\n" */ [日 月 年 时 分 秒] 的形式. */ i = fmt_str(s,"Received: (qmail "); len += i; if (s) s += i; i = fmt_ulong(s,mypid); len += i; if (s) s += i; i = fmt_str(s," invoked "); len += i; if (s) s += i; if (uid == auto_uida) { i = fmt_str(s,"by alias"); len += i; if (s) s += i; } else if (uid == auto_uidd) { i = fmt_str(s,"from network"); len += i; if (s) s += i; } else if (uid == auto_uids) { i = fmt_str(s,"for bounce"); len += i; if (s) s += i; } else { i = fmt_str(s,"by uid "); len += i; if (s) s += i; i = fmt_ulong(s,uid); len += i; if (s) s += i; } i = fmt_str(s,"); "); len += i; if (s) s += i; i = date822fmt(s,%26amp;dt); len += i; if (s) s += i; return len; }
void received_setup() { receivedlen = receivedfmt((char *) 0); received = alloc(receivedlen + 1); if (!received) die(51); receivedfmt(received); }
unsigned int pidfmt(s,seq) char *s; unsigned long seq; { unsigned int i; unsigned int len;
//生成类型pid/3434.34242424.1的字符串到s中 //这个字符串实际上就是/var/qmail/queue/pid目录下一个文件名。指示当前进程的pid. len = 0; i = fmt_str(s,"pid/"); len += i; if (s) s += i; i = fmt_ulong(s,mypid); len += i; if (s) s += i; i = fmt_str(s,"."); len += i; if (s) s += i; i = fmt_ulong(s,starttime); len += i; if (s) s += i; i = fmt_str(s,"."); len += i; if (s) s += i; i = fmt_ulong(s,seq); len += i; if (s) s += i; ++len; if (s) *s++ = 0;
return len; }
char *fnnum(dirslash,flagsplit) char *dirslash; int flagsplit; { char *s;
s = alloc(fmtqfn((char *) 0,dirslash,messnum,flagsplit)); if (!s) die(51); fmtqfn(s,dirslash,messnum,flagsplit); return s; }
void pidopen() //建立类似/var/run/inet.pid之类的进程id文件. { unsigned int len; unsigned long seq;
seq = 1; len = pidfmt((char *) 0,seq); pidfn = alloc(len); if (!pidfn) die(51);
for (seq = 1;seq < 10;++seq) { if (pidfmt((char *) 0,seq) > len) die(81); /* paranoia */ pidfmt(pidfn,seq); messfd = open_excl(pidfn); if (messfd != -1) return; }
die(63); }
char tmp[FMT_ULONG];
void main() { unsigned int len; char ch;
sig_blocknone(); umask(033); if (chdir(auto_qmail) == -1) die(61); if (chdir("queue") == -1) die(62);//改变工作目录到/var/qmail/queue
mypid = getpid(); uid = getuid(); starttime = now(); datetime_tai(%26amp;dt,starttime);//将起始时间转换为可读年月日时分秒的形式 //生成自已的邮件头存入缓存reseived中 //例如: received="Received: (qmail 3434 invoked by 34434); Apr 27 2003 14:55:34" received_setup();
sig_pipeignore(); sig_miscignore(); sig_alarmcatch(sigalrm);//捕捉alarm信号,控制超时 sig_bugcatch(sigbug);
alarm(DEATH); //超时秒数,缺省值是86400(24小时) 后错误返回52
pidopen();//建立进程id文件 if (fstat(messfd,%26amp;pidst) == -1) die(63);
messnum = pidst.st_ino; //进程id文件的inode节点号
/*生成将要建立的文件的文件名 几个文件都是根据刚才建立的pid文件的inode节点号命名的.inode不可能被两个文件同时占用,这保证了邮件唯一性。 其中mess目录下的文件放置有一个%23的问题, tips: 因为是%23所以该目录名最大的可能只有22,明白queue/mess目录下目录为什么最大只22了吧
Tags:分析 源代码 if len char int unsigned // die 文件 fmt_str
|
|