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

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

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

  代码:

  struct prioq_elt {

  datetime_sec dt;//时间戳,优先级

  unsigned long id;//邮件唯一id,你可以把它同qmail-queue分析中介绍中pid文件inode联系起来

  } ;

  prioq在prioq.h中prioq是这样定义的

  GEN_ALLOC_typedef(prioq,struct prioq_elt,p,len,a)

  展开后实际上定义为

  typedef struct prioq

  {

  struct prioq_elt *p; // 指针

  unsigned int len; //队列的长度

  unsigned int a;

  }prioq;

  消息块: --> message 我把它叫作消息块是因为他并不包含消息内容,也许这样称呼它并不确切

  代码:

  struct message {

  int flagdeleted; //删除标记,在qmail-pop3d程式退出时进行实际删除动作

  unsigned long size; //消息文件大小

  char *fn; //消息文件名

  } *m;

  主要功能:

  qmail-pop3d是则vchkpw或checkpassword之类的程式启动的。这些程式(vchkpw)会更改环境变量USER,

  HOME,SHELL等等,并在启动qmail-pop3d前将工作目录改变到$HOME下.

  qmail-pop3d在启动时首先检查./Maildir/tmp(./Maildir是在argv中指定的)下最后访问时间超过36小

  时的文件,如果存在就将其删除。也正是由于qmail-pop3d在启动时就有chdir的动作,所以qmail-pop3d

  不支持mailbox形式的pop.

  扫描Maildir/cur及Maildir/new目录构造一个消息块数组 m(首先是构造一个临时队列pq,然后根据这个队列

  来构造消息块数组),输出+OK,进入命令循环,等待用户输入pop命令进行相应的处理.具体见代码分析.

  代码:

  void die() { _exit(0); }

  //超时读,超时时间为20分钟,正常返回读到的字节数,否则程式失败die()

  int saferead(fd,buf,len) int fd; char *buf; int len;

  {

  int r;

  r = timeoutread(1200,fd,buf,len);

  if (r <= 0) die();

  return r;

  }

  //超时写,超时时间为20分钟,正常返回写的字节数,否则程式失败die()

  int safewrite(fd,buf,len) int fd; char *buf; int len;

  {

  int r;

  r = timeoutwrite(1200,fd,buf,len);

  if (r <= 0) die();

  return r;

  }

  /*定义ssout为向fd1写,超时时间为20分钟

  定义ssin为从fd0读,超时时间为20分钟

  由于tcpserver或inetd已经重定向了fd1,fd0到网络,所以这就

  等同于向网络读写*/

  char ssoutbuf[1024];

  substdio ssout = SUBSTDIO_FDBUF(safewrite,1,ssoutbuf,sizeof ssoutbuf);

  char ssinbuf[128];

  substdio ssin = SUBSTDIO_FDBUF(saferead,0,ssinbuf,sizeof ssinbuf);

  void put(buf,len) char *buf; int len;

  {

  substdio_put(&ssout,buf,len);//将buf缓存中的内容向网络写

  }

  void puts(s) char *s;

  {

  substdio_puts(&ssout,s);//将s的内容向网络写,这个函数实际上是调用的substdio_put

  }

  void flush() //确保输出缓存中已经没有内容。

  {

  substdio_flush(&ssout);

  }

  void err(s) char *s;

  {

  puts("-ERR ");

  puts(s);

  puts("\r\n");

  flush();

  }

  //错误处理函数

  void die_nomem() { err("out of memory"); die(); }

  void die_nomaildir() { err("this user has no $HOME/Maildir"); die(); }

  void die_scan() { err("unable to scan $HOME/Maildir"); die(); }

  void err_syntax() { err("syntax error"); }

  void err_unimpl() { err("unimplemented"); }

  void err_deleted() { err("already deleted"); }

  void err_nozero() { err("messages are counted from 1"); }

  void err_toobig() { err("not that many messages"); }

  void err_nosuch() { err("unable to open that message"); }

  void err_nounlink() { err("unable to unlink all deleted messages"); }

  void okay() { puts("+OK \r\n"); flush(); }

  void printfn(fn) char *fn;

  {

  fn += 4;

  put(fn,str_chr(fn,':'));

  }

  char strnum[FMT_ULONG];

  stralloc line = {0};

  void blast(ssfrom,limit)//从ssfrom读数据输出到fd1,一次一行(用全局缓存line)

  substdio *ssfrom;

  unsigned long limit;//除开消息头部信息,最多读limit行,limit为0将全部读完

  {

  int match;

  int inheaders = 1;

  for (;;) {

  if (getln(ssfrom,&line,&match,'\n') != 0) die();

  if (!match && !line.len) break;

  if (match) --line.len; /* no way to pass this info over POP */

  if (limit) if (!inheaders) if (!--limit) break;

  if (!line.len)

  inheaders = 0;

  else

  if (line.s[0] == '.')

  put(".",1);

  put(line.s,line.len);

  put("\r\n",2);

  if (!match) break;

  }

  put("\r\n.\r\n",5);

  flush();

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



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

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