程序员眼中的qmail(qmail源代码分析)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(&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,&pidst) == -1) die(63); messnum = pidst.st_ino; //进程id文件的inode节点号 /*生成将要建立的文件的文件名 几个文件都是根据刚才建立的pid文件的inode节点号命名的.inode不可能被两个文件同时占用,这保证了邮件唯一性。 其中mess目录下的文件放置有一个%23的问题, tips: 因为是%23所以该目录名最大的可能只有22,明白queue/mess目录下目录为什么最大只22了吧 比如说inode节点号为3455,那么3455%23=5,那么将生成/var/qmail/queue/mess/5/3455 这样一个文件来存放邮件。 /var/qmail/queue/todo/3455与/var/qmail/queue/intd/3455是相同的,都是保存用户id,进程id,mailfrom,rcptto的。 */ messfn = fnnum("mess/",1); //解释为message file name todofn = fnnum("todo/",0); //todo file name intdfn = fnnum("intd/",0); //intd file name if (link(pidfn,messfn) == -1) die(64); if (unlink(pidfn) == -1) die(63); //进程id文件使命很快结束,死掉了 //所以你不应该想在queue/pid目录中找到进程id文件。 //另外,qmail-clean也将定期清理queue/pid目录下的pid文件,说定期其实也不是,qmail-clean会在每收到30个清理邮件的请求后清理pid目录一次.这在分析qmail-clean时我们将会看到. flagmademess = 1; //fd1关联到写mess/下新建的文件。 通过管道连接<--------qmail-smtp 的 qqt->fde //也就是说qmail-smtpd进程写它的qqt-fde,那就相当于写mess/下新建立的邮件 //注意是关联不是正式写 substdio_fdbuf(&ssout,write,messfd,outbuf,sizeof(outbuf)); //fd0关联到读标准输入到缓存区inbuf 通过管道连接 <---------qmail-smtp 的 qqt->fdm //也就是说读ssin将从qmail-smtpd的qqt->fdm端读 substdio_fdbuf(&ssin,read,0,inbuf,sizeof(inbuf)); //向mess/下的邮件文件写qmail-queue的头部信息 if (substdio_bput(&ssout,received,receivedlen) == -1) die_write(); //从fd1读smtpd设置的邮件首部 switch(substdio_copy(&ssout,&ssin)) { case -2: die_read(); case -3: die_write(); } if (substdio_flush(&ssout) == -1) die_write(); if (fsync(messfd) == -1) die_write(); intdfd = open_excl(intdfn); if (intdfd == -1) die(65); flagmadeintd = 1; //fd1关联到写intd/下新建立的文件 fd0关联到读inbuff缓冲区 substdio_fdbuf(&ssout,write,intdfd,outbuf,sizeof(outbuf)); substdio_fdbuf(&ssin,read,1,inbuf,sizeof(inbuf)); /* 向intd下新建立的文件写如下格式内容 这些内容来自于qmail-smtpd.c中的data命令的解释函数。 u[uid] 更多相关文章
|
推荐文章
精彩文章
|