分享
 
 
 

qmail源代码分析之qmail-popup.c

王朝other·作者佚名  2008-05-31
窄屏简体版  字體: |||超大  

qmail-popup.c分析

Programmer:夜未眠

Come from:ChongQing Gearbox co.,ltd

qmail-popup也是由tcpserver或tcp-env之类的程式启动。这些程式是通过管道与qmail-popup通信的。这也是qmail的美妙之处,总观整个qmail源代码,除少量dns代码外。基本上没有使用网络编程。各个进程间大部分都是通管道通信。把监听,读写网络部分交给inetd或tcpserver来作。使得qmail代码相当容易阅读理解。

主要功能:

1.从网络读pop3命令,进行相应处理。

2.调用子进程(vchkpw或checkpassword,具体是哪一个由你在运行参数中指定,当然,仔细分析完doanddie函数后你也许就能编写自己的checkpw了,呵呵)完成检验密码,启动qmail-pop3d的工作

重要的函数是doanddie. 理解这个函数基本上就能理解qmail pop密码的检验流程。

几个程式间的关系是:

tcpserver--qmail-popup--vchkpw----认证成功-qmail-pop3d

| |

| |

[/code:1:1477526f27]

==========================

[code:1:1477526f27]

void die() { _exit(1); }

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

{

int r;

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

if (r

return r;

}

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

{

int r;

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

if (r

return r;

}

char ssoutbuf[128];

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

char ssinbuf[128];

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

void puts(s) char *s;

{

substdio_puts(%26amp;ssout,s);

}

void flush()

{

substdio_flush(%26amp;ssout);

}

void err(s) char *s;

{

puts("-ERR ");

puts(s);

puts("\r\n");

flush();

}

void die_usage() { err("usage: popup hostname subprogram"); die(); }

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

void die_pipe() { err("unable to open pipe"); die(); }

void die_write() { err("unable to write pipe"); die(); }

void die_fork() { err("unable to fork"); die(); }

void die_childcrashed() { err("aack, child crashed"); }

void die_badauth() { err("authorization failed"); }

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

void err_wantuser() { err("USER first"); }

void err_authoriz() { err("authorization first"); }

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

void pop3_quit() { okay(); die(); }

//FMT_ULONG 40 /* enough space to hold 2^128 - 1 in decimal, plus \0 */

char unique[FMT_ULONG + FMT_ULONG + 3];

char *hostname;

stralloc username = {0};

int seenuser = 0;

char **childargs;

substdio ssup;

char upbuf[128];

void doanddie(user,userlen,pass)

char *user;

unsigned int userlen; /* including 0 byte */

char *pass;

{

int child;

int wstat;

int pi[2];

if (fd_copy(2,1) == -1) die_pipe();//关闭出错(fd2),将标准输出(fd1),定向到标准出错(fd2)

close(3);

if (pipe(pi) == -1) die_pipe();

if (pi[0] != 3) die_pipe(); //确保向子进程能够读到硬编码的fd 3

switch(child = fork()) { //建立子进程执行subprogram给出的程式,一般是一个检验用户名和密码的程式

case -1:

die_fork();

case 0:

close(pi[1]);

sig_pipedefault();//子进程执行checkpassword或vchkpw之类的程式,检验密码,如果认证通过

execvp(*childargs,childargs);//这些再调用qmail-pop3d

_exit(1);

}

//父进程向子进程的fd3传送用户名及密码,这是一个约定。如果你要写自已的检验密码的程式,记得

//从fd3读密码哦。

close(pi[0]);

substdio_fdbuf(%26amp;ssup,write,pi[1],upbuf,sizeof upbuf);

if (substdio_put(%26amp;ssup,user,userlen) == -1) die_write();

if (substdio_put(%26amp;ssup,pass,str_len(pass) + 1) == -1) die_write();

//父进程向子进程传送

if (substdio_puts(%26amp;ssup,"

if (substdio_puts(%26amp;ssup,unique) == -1) die_write();

if (substdio_puts(%26amp;ssup,hostname) == -1) die_write();

if (substdio_put(%26amp;ssup,"",2) == -1) die_write();

if (substdio_flush(%26amp;ssup) == -1) die_write();

close(pi[1]);

//清除密码及用户名缓冲区

byte_zero(pass,str_len(pass));

byte_zero(upbuf,sizeof upbuf);

if (wait_pid(%26amp;wstat,child) == -1) die();//等待子进程结束

if (wait_crashed(wstat)) die_childcrashed();

if (wait_exitcode(wstat)) die_badauth();

//完成一次pop3对话退出

die();

}

//显示欢迎信息

void pop3_greet()

{

char *s;

s = unique;

s += fmt_uint(s,getpid());

*s++ = '.';

s += fmt_ulong(s,(unsigned long) now());

*s++ = '@';

*s++ = 0;

puts("+OK

puts(unique);

puts(hostname);

puts("\r\n");

flush();

}

//设置标志,初始化用户名变量

void pop3_user(arg) char *arg;

{

if (!*arg) { err_syntax(); return; }

okay();

seenuser = 1; //user命令已经执行的标志

if (!stralloc_copys(%26amp;username,arg)) die_nomem(); //将参数存入username

if (!stralloc_0(%26amp;username)) die_nomem();

}

void pop3_pass(arg) char *arg;

{

if (!seenuser) { err_wantuser(); return; }//如果没有执行user命令,返回

if (!*arg) { err_syntax(); return; }

doanddie(username.s,username.len,arg);//调用子进程验正密码并等待它完成

}

void pop3_apop(arg) char *arg;//用户名及密码在一个命令中给出的情况,见user,pass

{

char *space;

space = arg + str_chr(arg,' ');

if (!*space) { err_syntax(); return; }

*space++ = 0;

doanddie(arg,space - arg,space);

}

struct commands pop3commands[] = {//命令及相应的处理函数表

{ "user", pop3_user, 0 }

, { "pass", pop3_pass, 0 }

, { "apop", pop3_apop, 0 }

, { "quit", pop3_quit, 0 }

, { "noop", okay, 0 }

, { 0, err_authoriz, 0 }

} ;

void main(argc,argv)

int argc;

char **argv;

{

sig_alarmcatch(die);//捕获sigalrm信号

sig_pipeignore();//忽略pipe信号

hostname = argv[1]; //hostname 指向 程式的第一个参数

if (!hostname) die_usage();

childargs = argv + 2;

if (!*childargs) die_usage();

pop3_greet();//显示欢迎信息后进入命令循环,等待用户命令

commands(%26amp;ssin,pop3commands);

die();

},

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有