Linux中国 Linux中国门户站!
设为主页 设为主页
收藏本站 收藏本站
 
当前位置 :首页 ->Linux技术 ->Linux程序设计 ->正文

程序员眼中的qmail(qmail源代码分析)

来源:5dmail.net 作者:未知  时间:2007-04-22 点击: [收藏] [投稿]

  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]p[pid]F[mailfrom]T[rcptto1][rcptto2][rcptton]

 如果您对本文有任何疑问或者建议,请到讨论区发表您的意见: >> 论坛入口 <<



上一篇:使用 Flex 和 Bison 更好地进行错误处理   下一篇:GNU 线性编程工具包(线性优化简介)

文章评论】 【收藏本文】 【推荐好友】 【打印本文】 【我要投稿】 【论坛讨论
更多相关文章
Power by linux-cn.com 粤ICP备05006655号