Programmer:ҹδÃß
Comefrom: ChongQing Gearbox co.,ltd
¹Ø¼üÊý¾Ý½á¹¹
¶ÓÁÐ: --> prioq
Õâ¸öÊý¾Ý½á¹¹ÔںܶàqmailºÜ¶à³ÌʽÖж¼ÓÐÓõ½£¬×îºÃ¼ÇÏÂÀ´
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; //¶ÓÁеij¤¶È
unsigned int a;
}prioq;
[/code:1:c3936d2617]
ÏûÏ¢¿é: --> message ÎÒ°ÑËü½Ð×÷ÏûÏ¢¿éÊÇÒòΪËû²¢²»°üº¬ÏûÏ¢ÄÚÈÝ£¬Ò²ÐíÕâÑù³ÆºôËü²¢²»È·ÇÐ [code:1:c3936d2617]
struct message {
int flagdeleted; //ɾ³ý±ê¼Ç£¬ÔÚqmail-pop3d³ÌʽÍ˳öʱ½øÐÐʵ¼Êɾ³ý¶¯×÷
unsigned long size; //ÏûÏ¢Îļþ´óС
char *fn; //ÏûÏ¢ÎļþÃû
} *m;
[/code:1:c3936d2617]
Ö÷Òª¹¦ÄÜ£º
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ÃüÁî½øÐÐÏàÓ¦µÄ´¦Àí.¾ßÌå¼û´úÂë·ÖÎö.
[code:1:c3936d2617]
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();
}
stralloc filenames = {0};
prioq pq = {0};
struct message {
int flagdeleted; //ɾ³ý±ê¼Ç£¬ÔÚ³ÌʽÍ˳öʱ½øÐÐʵ¼Êɾ³ý¶¯×÷
unsigned long size; //Îļþ´óС
char *fn; //ÎļþÃû
} *m;
int numm;//È«¾Ö±äÁ¿¼Ç¼¶ÓÁ㤶È
int last = 0;
void getlist()
{
struct prioq_elt pe;
struct stat st;
int i;
maildir_clean(&line);//Çå³ýMaildir/tmp/Ŀ¼ÏÂ×îºó·ÃÎÊʱ¼ä³¬¹ý 36СʱµÄÎļþ
if (maildir_scan(&pq,&filenames,1,1) == -1) die_scan();
numm = pq.p ? pq.len : 0; //¼Ç¼Ï¶ÓÁ㤶È
//ͨ¹ý¶ÓÁÐpq¹¹ÔìÏûÏ¢¿éÊý×é,¹¹½¨½áÊøºó¶ÓÁÐpqɾ³ý
m = (struct message *) alloc(numm * sizeof(struct message));//·ÖÅäÏûÏ¢¿é
if (!m) die_nomem();
for (i = 0;i < numm;++i) {
if (!prioq_min(&pq,&pe)) { numm = i; break; }
prioq_delmin(&pq);
m[i].fn = filenames.s + pe.id;
m[i].flagdeleted = 0;
if (stat(m[i].fn,&st) == -1)
m[i].size = 0;
else
m[i].size = st.st_size;
}
}
void pop3_stat() //´òÓ¡ÀàËÆ +OK <ÏûÏ¢ÊýÁ¿><ɾ³ý±ê¼ÇδÉèÖõÄÏûÏ¢ËùÕ¼¿Õ¼ä>
{ //Èç +OK 3 3555±íʾ×ܹ²ÓÐ3ÌõÏûÏ¢£¬Õ¼Óÿռä3555(ͨ¹ýstatÈ¡µÃµÄ)
int i;
unsigned long total;
total = 0;
for (i = 0;i < numm;++i) if (!m[i].flagdeleted) total += m[i].size;
puts("+OK ");
put(strnum,fmt_uint(strnum,numm));
puts(" ");
put(strnum,fmt_ulong(strnum,total));
puts("\r\n");
flush();
}
void pop3_rset()//ÖØÖÃpop¶Ô»°,Çå³ýËùÓÐɾ³ý±ê¼Ç
{
int i;
for (i = 0;i < numm;++i) m[i].flagdeleted = 0;
last = 0;
okay();
}
void pop3_last()//ÏÔʾ×îºóÒ»¸öÏûÏ¢¿é
{
puts("+OK ");
put(strnum,fmt_uint(strnum,last));
puts("\r\n");
flush();
}
void pop3_quit()//½áÊøÒ»´Îpop¶Ô»°£¬É¾³ýËùÓÐɾ³ý±ê¼ÇÉèÖõÄÏûÏ¢,½«newϵÄÏûÏ¢ÒÆµ½curÏÂ
{
int i;
for (i = 0;i < numm;++i)
if (m[i].flagdeleted) {
if (unlink(m[i].fn) == -1) err_nounlink();
}
else
if (str_start(m[i].fn,"new/")) {
if (!stralloc_copys(&line,"cur/")) die_nomem();
if (!stralloc_cats(&line,m[i].fn + 4)) die_nomem();
if (!stralloc_cats(&line,":2,")) die_nomem();
if (!stralloc_0(&line)) die_nomem();
rename(m[i].fn,line.s); /* if it fails, bummer */
}
okay();
die();
}
//¼ì²éÏûÏ¢¿éÊÇ·ñ´æÔÚ¡£»òÏûÏ¢¿éµÄɾ³ý±ê¼ÇÊÇ·ñÒѾÉèÖÃÁË
//³É¹¦·µ»ØÏûÏ¢¿éµÄλÖÃintÐÍ
//ʧ°Ü·µ»Ø-1
int msgno(arg) char *arg;
{
unsigned long u;
if (!scan_ulong(arg,&u)) { err_syntax(); return -1; }
if (!u) { err_nozero(); return -1; }
--u;
if (u >= numm) { err_toobig(); return -1; }
if (m[u].flagdeleted) { err_deleted(); return -1; }
return u;
}
void pop3_dele(arg) char *arg;//½«argÖ¸¶¨ÏûÏ¢¿éÉèÖÃɾ³ý±ê¼Ç,ʵ¼Êɾ³ý¶¯×÷½«ÔÚpop3Í˳öʱ½øÐÐ
{
int i;
i = msgno(arg);
if (i == -1) return;
m[i].flagdeleted = 1;
if (i + 1 > last) last = i + 1;
okay();
}
void list(i,flaguidl)
int i;
int flaguidl;
{//ÏÔʾÏûÏ¢¿éµÄÄÚÈÝ£¬Èç¹ûflaguidlÉèÖã¬Êä³öÏûÏ¢ÎļþÃû,·ñÔòÏûÏ¢´óС
put(strnum,fmt_uint(strnum,i + 1));
puts(" ");
if (flaguidl) printfn(m[i].fn);
else put(strnum,fmt_ulong(strnum,m[i].size));
puts("\r\n");
}
//Èç¹ûÖ¸¶¨Á˲ÎÊýargÄÇôÁгöargÖ¸¶¨µÄÏûÏ¢¿éµÄÄÚÈÝ£¬·ñÔòÁгöÈ«²¿ÏûÏ¢
void dolisting(arg,flaguidl) char *arg; int flaguidl;
{
unsigned int i;
if (*arg) {
i = msgno(arg);
if (i == -1) return;
puts("+OK ");
list(i,flaguidl);
}
else {
okay();
for (i = 0;i < numm;++i)
if (!m[i].flagdeleted)
list(i,flaguidl);
puts(".\r\n");
}
flush();
}
void pop3_uidl(arg) char *arg; { dolisting(arg,1); }
void pop3_list(arg) char *arg; { dolisting(arg,0); }
substdio ssmsg; char ssmsgbuf[1024];
void pop3_top(arg) char *arg;//ÏÔʾָ¶¨ÏûÏ¢µÄÄÚÈÝ
{
int i;
unsigned long limit;
int fd;
i = msgno(arg);//ÓʼþºÅ
if (i == -1) return;
arg += scan_ulong(arg,&limit);//ÏÔʾ¼¸ÐУ¬Èç¹ûδָ¶¨ÄÇôlimitΪ0(balstº¯Êý´òÓ¡È«²¿ÄÚÈÝ)
while (*arg == ' ') ++arg;
if (scan_ulong(arg,&limit)) ++limit; else limit = 0;
fd = open_read(m[i].fn);
if (fd == -1) { err_nosuch(); return; }
okay();
//¹ØÏµssmsgΪ´ÓÖ¸¶¨µÄÏûÏ¢ÎļþÖжÁ
substdio_fdbuf(&ssmsg,read,fd,ssmsgbuf,sizeof(ssmsgbuf));
//´ÓssmsgÖжÁµ½fd1,Èç¹ûlimit´óÓÚ0½«Ö»¶ÁÈ¡³ýÏûϢͷÍâµÄlimitÐУ¬Èç¹ûµÈÓÚ0¶ÁÈ«²¿Óʼþ
blast(&ssmsg,limit);
close(fd);
}
struct commands pop3commands[] = { //pop3ÃüÁî¼°´¦Àíº¯Êý±í
{ "quit", pop3_quit, 0 }
, { "stat", pop3_stat, 0 }
, { "list", pop3_list, 0 }//ÏÔʾÏûÏ¢´óС
, { "uidl", pop3_uidl, 0 }//ÏÔʾÏûÏ¢ÎļþÃû
, { "dele", pop3_dele, 0 }
, { "retr", pop3_top, 0 }//ȡһÌõÏûÏ¢µÄÄÚÈÝ,ÓëtopʵÏÖÊÇÒ»ÑùµÄ
, { "rset", pop3_rset, 0 }//ÖØÖÃpop¶Ô»°£¬Çå³ýËùÓÐɾ³ý±ê¼Ç
, { "last", pop3_last, 0 }
, { "top", pop3_top, 0 }
, { "noop", okay, 0 }
, { 0, err_unimpl, 0 }
} ;
/*qmail-pop3dÓÉvchkpw»òcheckpasswordÖ®ÀàµÄ³ÌʽÆð¶¯£¬Ö»ÓÐÈÏ֤ͨ¹ýºó²ÅÄÜ
Ö´Ðб¾³ÌʽÌṩ¸÷ÖÖpop3ÃüÁî
*/
void main(argc,argv)
int argc;
char **argv;
{
sig_alarmcatch(die);
sig_pipeignore();
if (!argv[1]) die_nomaildir();
//ÓÉÓÚvchkpw»òcheckpasswordÖ®ÀàµÄ³ÌʽÔÚÆô¶¯pop3֮ǰÒѾ½«¹¤×÷Ŀ¼¸Ä±äµ½HOMEÏÂÁË.
//ËùÒÔÕâÀïÖ±½Ó½øÈëargÖ¸¶¨µÄMaildirĿ¼.Ò²ÊÇÓÉÓÚÕâ¸ö¸Ä±äĿ¼ÔÒò¡£qamil-pop3d²»Ö§³ÖMailbox.
if (chdir(argv[1]) == -1) die_nomaildir();
getlist(); //ÕâÀï¹¹ÔìÁËÎÒÃÇÇ°ÃæÌáµ½ÁËÏûÏ¢¿éÊý×é*m
okay();
//½øÈëÃüÁîÑ»·
commands(&ssin,pop3commands);
die();
}