Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1252942
  • 博文数量: 177
  • 博客积分: 1528
  • 博客等级: 上尉
  • 技术积分: 1891
  • 用 户 组: 普通用户
  • 注册时间: 2010-12-15 18:03
文章分类

全部博文(177)

文章存档

2020年(1)

2018年(19)

2017年(4)

2016年(21)

2015年(40)

2014年(13)

2013年(26)

2012年(16)

2011年(37)

我的朋友

分类: LINUX

2012-06-15 16:21:23

pop3控制函数 
[code:1:f4f229a6fe] 


#ifdef HAVE_CONFIG_H 
#include "config.h" 
#endif 

#include  
#include  
#include  
#include  

#include "defs.h" 

static char *chop_tail(char *p); 


Head *head_register(int page, int idx) 

    Head  *tmp; 

    if ((tmp = malloc(sizeof(Head))) == NULL)  return NULL; 
    memset(tmp, 0, sizeof(Head)); 

    tmp->pm = pm_handler(idx, page); 
    if (tmp->pm == NULL)  { 
free(tmp); 
return NULL; 
    } 

    tmp->this = tmp; 
    return tmp; 


void head_destruct(Head *hdo) 

    if (hdo != NULL)  { /* all memory allocating routines are issued*/ 
pm_close(hdo->pm); /* by pmalloc.c, therefore no more releasing*/ 
free(hdo->this); /* procession required */ 
    } 


char *head_loading(Head *hdo, char *s) 

    struct head_chain  *hc, *hctmp; 
    HLin   *hltmp; 
    int    len; 
     
    if (!isheadline(s))  return s; 

    /* continuing last head line 
       If a headline starts with a white space character such as SPACE, 
       H-TAB, it should be the remain part of last head line */ 
     
    if (isspace(*s))  {

/* it should not be the first of all the head part, otherwise 
   it declares the end of head part */ 
     
if (hdo->last == NULL)  return s; 

hctmp = pm_alloc(hdo->pm, sizeof(struct head_chain)); 
if (hctmp == NULL)  return s; 

hctmp->next = NULL; 
hctmp->str = pm_dup_str(hdo->pm, s); 

if (hdo->last->hc == NULL)  hdo->last->hc = hctmp; 
else { 
    for (hc = hdo->last->hc; hc->next; hc = hc->next); 
    hc->next = hctmp; 


if (hctmp->str)  { 
    len = strlen(hctmp->str); 
    hdo->last->len += len; 
    hdo->len += len; 

return NULL; 
    } 

    /* create new head line structure */ 
     
    hltmp = pm_alloc(hdo->pm, sizeof(HLin)); 
    if (hltmp == NULL)  return s; 
     
    hltmp->rm = 0; 
    hltmp->len = len = strlen(s); 
    hltmp->hc = hltmp->next = NULL; 
    hltmp->headin = pm_dup_str(hdo->pm, s); 
    if (hltmp->headin == NULL)  { 
hltmp->body = NULL; 
hltmp->key = NULL; 
    } else { 
hltmp->body = strchr(hltmp->headin, ':'); 
*hltmp->body = 0; 
hltmp->key = pm_dup_str(hdo->pm, hltmp->headin); 
chop_tail(hltmp->key); 
*hltmp->body = ':'; 
for (hltmp->body++; isspace(*hltmp->body); hltmp->body++); 
    } 
     
    if (hdo->hlin == NULL)  hdo->hlin = hltmp; 
    else  hdo->last->next = hltmp; 
     
    hdo->last = hltmp; 
    hdo->len += len; 
    hdo->num++; 
     
    return NULL; 


void head_clean(Head *hdo) 

    pm_free(hdo->pm); 
    hdo->len = 0; 
    hdo->num = 0; 
    hdo->fmsp = NULL; 
    hdo->hlin = NULL; 
    hdo->last = NULL; 
    hdo->skey = NULL; 
    hdo->scur = NULL; 


/* put the head part in the file into head cache  
   Note: when call this function, the FromSps line should be inside the 
   'buf' argument, and file seeking in the 'fin' has moved to next line */ 

int head_to_cache(Head *hdo, FILE *fin, char *buf, int len) 

    hdo->fmsp = pm_dup_str(hdo->pm, buf); 
    while (fgets(buf, len, fin))  {
if (head_loading(hdo, buf) != NULL)  break; 
    } 
    return 0; 


int head_of_file(Head *hdo, FILE *fin, char *buf, int len) 
{
    /* skip leading nonsense lines */ 

    while (fgets(buf, len, fin))  { 
if (ismailstart(buf))   
    return head_to_cache(hdo, fin, buf, len); 
    } 

    return -1; 
}    

char *head_append(Head *hdo, char *head) 

    return head_loading(hdo, head); 
}


void head_remove_first(Head *hdo, char *key) 

    HLin  *hl; 

    for (hl = hdo->hlin; hl; hl = hl->next)  { 
if (!strcasecmp(hl->key, key))  { 
    hl->rm = 1; 
    break; 

    } 


void head_remove_all(Head *hdo, char *key) 

    HLin  *hl; 

    for (hl = hdo->hlin; hl; hl = hl->next)  { 
if (!strcasecmp(hl->key, key))  hl->rm = 1; 
    } 



/* check heads against given mask. If rm set, remove all heads in the mask; 
 * otherwise remove all heads except heads in the mask */ 

void head_mask(Head *hdo, char *mask, int rm) 

    HLin  *hl; 
    char  *p, *k, flag, buf[512]; 

    strncpy(buf, mask, 511); 
    buf[511] =  0; 
    for (hl = hdo->hlin; hl; hl = hl->next)  { 
p = k = buf; 
flag = 0; 
while (*p)  { 
    k = strchr(p, ':'); 
    if (k)  *k = 0; 

    if (!strcasecmp(hl->key, p))  { 
if (rm)  hl->rm = 1; 
flag = 1; 
    } 

    if (k)  *k = ':', p = k + 1; 
    else  break; 
    if (flag == 1)  break; 

if (!flag && !rm)  hl->rm = 1; 
    } 


     
HLin *head_check(Head *hdo, char *key) 

    HLin  *hl; 

    hdo->skey = pm_dup_str(hdo->pm, key); 
    for (hl = hdo->hlin; hl; hl = hl->next)  { 
if (!strcasecmp(hl->key, key) && !hl->rm)  { 
    hdo->scur = hl->next; 
    return hl; 

    } 
    return NULL; 



HLin *head_check_next(Head *hdo) 

    HLin  *hl; 

    if (hdo->skey == NULL)  return NULL; 
     
    for (hl = hdo->scur; hl; hl = hl->next)  { 
if (!strcasecmp(hl->key, hdo->skey) && !hl->rm)  { 
    hdo->scur = hl->next; 
    return hl; 

    } 
    return NULL; 



char *head_fetch(HLin *h) 

    char  *p; 
    struct  head_chain  *hc; 

    if ((p = malloc(h->len + 1)) == NULL)  return NULL; 

    strcpy(p, h->headin); 
    for (hc = h->hc; hc; hc = hc->next)  strcat(p, hc->str); 

    return p; 



char *head_fetch_body(HLin *h) 

    char  *p; 
    struct  head_chain  *hc; 

    if ((p = malloc(h->len + 1)) == NULL)  return NULL; 

    strcpy(p, h->body); 
    for (hc = h->hc; hc; hc = hc->next)  strcat(p, hc->str); 

    return p; 


/* Has the specified class headline existed ?  
   It check the head index (class) first, then search the cache for  
   the same class head */ 

HLin *head_exist(Head *hdo, char *head) 

    char  idx[256]; 
    HLin  *hl; 

    if (head_index(head, idx, 256) == NULL)  return NULL; 
     
    for (hl = hdo->hlin; hl; hl = hl->next)  { 
if (!strcasecmp(hl->key, idx) && !hl->rm)  return hl; 
    } 
    return NULL; 

     
     
void head_dump(Head *hdo, FILE *fout, int fmsp) 

    HLin   *hl; 
    struct head_chain *hc; 

    if (hdo->fmsp && fmsp)  fputs(hdo->fmsp, fout); 
     
    for (hl = hdo->hlin; hl; hl = hl->next)  { 
if (hl->rm)  continue; 

if (hl->headin)  fputs(hl->headin, fout); 

for (hc = hl->hc; hc; hc = hc->next)   
    fputs(hc->str, fout); 
    } 
    fflush(fout); 



char *head_index(char *headline, char *buf, int len) 

    char  *p; 
     
    strncpy(buf, headline, len); 
    buf[len-1] = 0; 
    p = strchr(buf, ':'); 
    if (p == NULL)  return NULL; 
    *p = 0; 
    chop_tail(buf); 
    return buf; 

     

int head_cmp(char *s, char *d) 

    char  sh[256], dh[256]; 

    if (!s || !d)  return 1; 
     
    s = head_index(s, sh, 256); 
    d = head_index(d, dh, 256); 
     
    if (!s && !d)  return 0; /* they are all the same non-heads */ 
    if (!s || !d)  return 1;
     
    return strcasecmp(sh, dh); 


/* 
static int isblankline(char *buf) 

    while (*buf)  { 
       if (isspace(*buf))  buf++; 
       else  return 0; 
    } 
    return 1; 


static int isheadline(char *buf) 

    if (isblankline(buf))  return 0; 
    if (isspace(*buf))  return 1; 
    if (strchr(buf, ':'))  return 1; 
    return 0; 

*/ 


static char *chop_tail(char *p) 

    int  i; 

    if (p == NULL)  return p; 
    for (i = strlen(p); (i >= 0) && (p[i] >= 0) && (p[i] <= ' '); p[i--] = 0); 
    return p; 



#ifdef EXECUTABLE 


int main(int argc, char **argv) 

    FILE  *fp; 
    Head  *head; 
    HLin  *hl; 
    char  buf[512], tmp[512]; 

    if (argc < 2)  { 
printf("usage:  %s folder\n", argv[0]); 
return 0; 
    } 

    head = head_register(4096, 128); 
    if (head == NULL)  return 1; 
     
    fp = fopen(argv[1], "r"); 
    if (fp == NULL)  return 1; 

    while (!feof(fp))  { 
head_of_file(head, fp, buf, 512); 

head_append(head, "myhead1: nothing at all\n"); 
head_append(head, "myhead2: good day\n and bad day\n"); 

printf("> Head %d items, %d bytes in total.\n", head->num, head->len); 
head_dump(head, stdout, 1); 

while (fgets(tmp, 512, stdin))  { 
    chop_tail(tmp); 
    if ((hl = head_check(head, tmp)) != NULL)  { 
printf("## %s", hl->headin); 
head_remove_all(head, tmp); 
head_dump(head, stdout, 1); 
    } 


head_clean(head); 
printf("\n"); 
    } 

    fclose(fp); 
    head_destruct(head); 
    return 0; 


#endif 

[/code:1:f4f229a6fe] 
smtp控制 
[code:1:f4f229a6fe] 


#ifdef HAVE_CONFIG_H 
#include "config.h" 
#endif 

#include  
#include  
#include  

#if HAVE_UNISTD_H 
  #include  
  #include  
#endif 

#include "defs.h" 


static int smtp_helo(int sock); 
static int smtp_from(int sock, char *cmd); 
static int smtp_rcpto(int sock, char *cmd); 
static int smtp_data(int sock); 
static int smtp_dotclose(int sock); 
static int smtp_reset(int sock); 
static int smtp_quit(int sock); 
static int smtp_answer(int sock, char *buf, int len); 
static int smtp_transact(int sock, char *cmd, int len); 
static int smtp_sendmsg(int sock, Mail *m, char *sender); 


static int smtp_helo(int sock) 

    char buf[SVRBUF]; 
    int  rs; 
     
    sprintf(buf, "HELO %s", get_user()); 
    rs = smtp_transact(sock, buf, SVRBUF); 
    if (rs != OK)   
return rs; 
    if (!strncmp(buf, "250", 3))   
return OK; 
     
    return MISANSWER; 


static int smtp_from(int sock, char *cmd) 

    char buf[SVRBUF]; 
    int  rs; 
     
    if (cmd == NULL)   
strcpy(buf, "MAIL FROM:<>"); 
    else   
sprintf(buf, "MAIL FROM:<%s>", email_pure(cmd)); 
    rs = smtp_transact(sock, buf, SVRBUF); 
    if (rs != OK)   
return rs; 
     
    if (!strncmp(buf, "250", 3))   
return OK; 
    logPrintf(LOG_INFO, "smtp: %s", buf); 
/*     
    strcpy(buf, "QUIT"); 
    rs = smtp_transact(sock, buf, SVRBUF); 
    if (rs != OK)  return rs; 
*/ 
    return MISANSWER; 


/* this routine has changed. The 'cmd' argument accept several receiption 
   address seperated by comma. e.g.:  ... */ 

static int smtp_rcpto(int sock, char *cmd) 

    char  buf[SVRBUF], *p; 
    Iadr  *iadr; 
    int   cnt = 0; 
     
    if ((p = cmd) == NULL)  
return 0; 
     
    while ((iadr = email_addr(p)) != NULL)  { 
if (iadr->rtto)   
    sprintf(buf, "RCPT TO:%s", iadr->rtto); 
else   
    sprintf(buf, "RCPT TO:<%s>", iadr->email); 

if (smtp_transact(sock, buf, SVRBUF) != OK)   
    return 0; 

if (!strncmp(buf, "250", 3))   
    cnt++; 
else  
    logPrintf(LOG_INFO, "smtp: %s", buf); 

if ((p = iadr->next) == NULL)   
    break; 
    }
    return cnt; 


static int smtp_data(int sock) 

    char buf[SVRBUF]; 
    int  rs; 
     
    strcpy(buf, "DATA"); 
    rs = smtp_transact(sock, buf, SVRBUF); 
    if (rs != OK)  
return rs; 
     
    if (!strncmp(buf, "354", 3))   
return OK; 

    logPrintf(LOG_INFO, "smtp: %s", buf); 
    return MISANSWER; 


static int smtp_dotclose(int sock) 

    char buf[SVRBUF]; 
    int  rs; 
     
    strcpy(buf, "."); 
    rs = smtp_transact(sock, buf, SVRBUF); 
    if (rs != OK)   
return rs; 
     
    if (!strncmp(buf, "250", 3))   
return OK; 
     
    logPrintf(LOG_INFO, "smtp: %s", buf); 
/* 
    strcpy(buf, "QUIT"); 
    rs = smtp_transact(sock, buf, SVRBUF); 
    if (rs != OK)  return rs; 
*/ 
    return MISANSWER; 


static int smtp_reset(int sock) 

    char buf[SVRBUF]; 
    int  rs; 
     
    strcpy(buf, "RSET"); 
    rs = smtp_transact(sock, buf, SVRBUF); 
    if (rs != OK)   
return rs; 
     
    return OK; 


static int smtp_quit(int sock) 

    char buf[SVRBUF]; 
    int  rs; 
     
    strcpy(buf, "QUIT"); 
    rs = smtp_transact(sock, buf, SVRBUF); 
    if (rs != OK)   
return rs; 
    return OK; 


static int smtp_answer(int sock, char *buf, int len) 

    char tmp[SVRBUF]; 
    int  rs; 
     
    rs = sock_readall(sock, buf, len, timeout); 
    if (rs != OK)   
return rs; 
     
    if (verbose)   
conPrintf("<< %s", buf); 
     
    strcpy(tmp, buf); 
    while (tmp[3] == '-')  { 
     rs = sock_readall(sock, tmp, SVRBUF, timeout); 
     if (rs != OK)   
    return rs; 

     if (verbose)   
    conPrintf("<< %s", tmp); 
    } 
    return OK; 


static int smtp_transact(int sock, char *cmd, int len) 

    char  buf[SVRBUF]; 
    int   rs; 
     
    if (verbose)   
conPrintf("-> %s\n", cmd); 
     
    sprintf(buf, "%s\r\n", cmd); 
    rs = sock_write(sock, buf, strlen(buf), timeout); 
    if (rs != OK)  
return rs; 
     
    rs = smtp_answer(sock, cmd, len); 
    return rs; 


static int smtp_sendmsg(int sock, Mail *m, char *sender) 

    FILE  *fp; 
    char  buf[SVRBUF], *bulk, *tmp; 
    int   rs; 

    if ((m->behave & ACT_SUSP) != 0)  { 
conPrintf("Suspended message.\n"); 
return OK;  /* reserved message */ 
    } 
     
    if ((fp = fopen(m->msg->name, "r")) == NULL)  { 
dbgPrintf("message folder open failed. [%s]\n", m->msg->name); 
return OPENFILERR; 
    } 
     
    if ((rs = smtp_from(sock, sender)) != OK)  { 
dbgPrintf("reject return path. [%s]\n", sender); 
rs = WARNING; 
goto send_fail; 
    } 
     
    rs  = smtp_rcpto(sock, m->to); 
    rs += smtp_rcpto(sock, m->cc); 
    rs += smtp_rcpto(sock, m->bcc); 
    if (rs == 0)  { 
dbgPrintf("reject all target addresses, abort it.\n"); 
rs = WARNING; 
goto send_fail; 
    } 

    rs = smtp_data(sock); 
    if (rs == MISANSWER)  { 
dbgPrintf("data transfering refused by peer!\n"); 
goto send_fail; 
    } 

    *buf = '.'; 
    bulk = buf + 1; 

    /* skip starting FromSps line */ 

    while (fgets(bulk, SVRBUF - 1, fp))  { 
if (ismailstart(bulk)) 
    break; 
    } 
     
    prog_init(m->msg->msize - ftell(fp), 40); 
    while (fgets(bulk, SVRBUF - 1, fp))  { 
tmp = bulk + strlen(bulk) - 1; 
if (*tmp == '\n')  { 
    *tmp++ = '\r', *tmp++ = '\n', *tmp = '\0'; 


if (*bulk == '.')  { 
    prog_do(strlen(buf)); 
    rs = linesend(sock, buf, timeout); 
} else { 
    prog_do(strlen(bulk)); 
    rs = linesend(sock, bulk, timeout); 


if (rs != OK) 
    goto send_fail; 
    } 
    prog_end(); 
    rs = sflush(sock, timeout); 
    if (rs != OK) 
goto send_fail; 
     
    rs = smtp_dotclose(sock); 
    if (rs != OK) 
goto send_fail; 
     
    /* so, the message has sent successfully, mark it as removed. */ 

    m->removed = 1; 
    fclose(fp); 
    return OK; 
     
send_fail: 
    fclose(fp); 
    smtp_reset(sock); 
    return rs; 



/* create an smtp server list. 
 * The input argument 'host' and 'auth' comes from command line. It returns 
 * an smtp server structure for going to use. The step is: 
 *  1. First it creates a server chain by the appearence order according to  
 *     the options 'smtp' positing in the config file. 
 *  2. If the 'auth' argument is given, it will replace the coresponsive  
 *     elements in the 'smtp' option. 
 *  3. If the 'host' argument is given with an Internet address, it will create 
 *     a new server structure and then will insert it to the head. 
 *  4. If the 'host' argument is given with the form of "@number", such as @2, 
 *     it will return the element in the list by the 'number', in this example 
 *     it is the second element, so that Pmail will connect the specified smtp 
 *     server. Otherwise the first element in the queue will be returned. 
 *  5. The 'auth' originally is with the form of 'id:passwd'. But there is an 
 *     extensive form available, 'id:passwd:reply-address', for connecting 
 *     smtp server only. With another context such as POP3 server it's invalid. 
 *  6. If some entry is not written down, that means no need of it. The same 
 *     effect can be made by the (*) character. If a blank element is wanted, 
 *     you should leave the entry blank. But if your choice is actually the (*) 
 *     character, then you should use (\*). 
 */ 

static SMTP *smtpsvr = NULL; 
static char *lauth = NULL; 
static char *defhost = NULL; 
static char *defreply = NULL; 

SMTP *smtp_host_chain(char *host, char *auth) 

    SMTP  *sm = NULL, *tmp; 
    char  *idx[4], *auidx[3], *p; 
    int   i, rs; 
     
    /* first we process the authentication information from command line */ 
     
    if (auth && (lauth = dup_str(auth)))  { 
rs = fixtoken(lauth, auidx, 3, ":"); 
for (i = 0; i < rs; i++)  { 
    if (!strcmp(auidx[i], "*")) 
auidx[i] = NULL; 
    else if (!strcmp(auidx[i], "\\*")) 
auidx[i]++; 

    } 

    /* then create the smtp server chain */ 
     
    for (p = rc_check(RCKEY_SMTP); p; p = rc_check_next())  { 
     
rs = sizeof(SMTP) + strlen(p); 
if ((tmp = malloc(rs)) == NULL) 
    break; 

memset(tmp, 0, rs); 
strcpy(tmp->buf, p); 
rs = fixtoken(tmp->buf, idx, 4, ":"); 
for (i = 0; i < rs; i++)  { 
    if (!strcmp(idx[i], "*")) 
idx[i] = NULL; 
    else if (!strcmp(idx[i], "\\*")) 
idx[i]++; 


tmp->host = idx[0]; 
tmp->reply = idx[1]; 
tmp->id = idx[2]; 
tmp->passwd = idx[3]; 

if (lauth)  { 
    tmp->id = auidx[0]; 
    tmp->passwd = auidx[1]; 
    if (auidx[2]) 
tmp->reply = auidx[2]; 


if (smtpsvr == NULL) 
    smtpsvr = sm = tmp; 
else { 
    sm->next = tmp; 
    sm = sm->next; 
}    
    } 
     
    /* To check which server structure should be returned. 
     * If a command line host specified, append an smtp server structure. */ 
     
    if (host == NULL) 
sm = smtpsvr; 
    else  if (*host == '@')  { 
rs = atoi(host+1); 
for (i = 1, sm = smtpsvr; sm; i++, sm = sm->next)  { 
    if (i == rs) 
break; 

if (sm == NULL) 
    sm = smtpsvr; /* out of smtp server number */ 
    } else { 
rs = sizeof(SMTP) + strlen(host); 
if ((tmp = malloc(rs)) != NULL) { 
    memset(tmp, 0, rs); 
    strcpy(tmp->buf, host); 
    tmp->host = tmp->buf; 
    if (lauth)  { 
tmp->id = auidx[0]; 
tmp->passwd = auidx[1]; 
tmp->reply = auidx[2]; 
    } 

    tmp->next = smtpsvr; 
    smtpsvr = tmp; 
     

sm = smtpsvr; 
    } 

    /* double check to prevent the appearance of invaild elements */ 

    if (sm == NULL)  { 
sm = smtpsvr = malloc(sizeof(SMTP)); 
if (smtpsvr == NULL) 
    return NULL; 
else 
    memset(smtpsvr, 0, sizeof(SMTP)); 
    } 
    if ((sm->host == NULL) || (*sm->host == 0))  { 
defhost = dup_str(get_hostname()); 
sm->host = defhost; 
    } 
    if ((sm->reply == NULL) || (*sm->reply == 0))  { 
p = rc_check(RCKEY_REPLY); 
if (p && *p)  defreply = dup_str(p); 
else { 
    rs = strlen(get_user()) + strlen(get_hostname()) + 5; 
    if ((defreply = malloc(rs)) != NULL)  { 
strcpy(defreply, get_user()); 
strcat(defreply, "@"); 
strcat(defreply, get_hostname()); 
    } 

sm->reply = defreply; 
    } 
     
    return sm; 


void smtp_host_list() 

    SMTP *sm; 
    char buf[SVRBUF]; 
    int  i; 

    conPrintf("SMTP servers list:\n"); 
    for (i = 1, sm = smtpsvr; sm; i++, sm = sm->next)  { 
ssprintf(buf, SVRBUF, "%4d %-25s %-25s %s:%s\n",  
i, sm->host, sm->reply, sm->id, sm->passwd); 
conPrintf(buf); 
    } 
    conPrintf("\n"); 


void smtp_host_clean() 

    SMTP *sm, *tmp; 

    if (smtpsvr)  { 
sm = smtpsvr; 
while (sm)  { 
    tmp = sm; 
    sm = sm->next; 
    free(tmp); 

    } 
    if (lauth) 
free(lauth); 
    if (defhost) 
free(defhost); 
    if (defreply) 
free(defreply); 


int smtp_main(Folder *rootfld, SMTP *sm) 

    Folder *fo; 
    Mail   *m; 
    char   buf[SVRBUF]; 
    int    sock, scnt, rs; 
     
     
    if (sm == NULL)  { 
logPrintf(LOG_WARN, "No SMTP server existed.\n"); 
return FAILURE; 
    } 

    /* double check the existance of message for sending */ 
     
    for (rs = 0, fo = rootfld; fo; fo = fo->next) 
rs += fo->num; 
    if (rs == 0)  { 
conPrintf("No message to deliver.\n"); 
return WARNING; 
    } 
     
    /* open socket and connect to the destination server */ 
     
    conPrintf("Trying SMTP server [%s] ... ", sm->host); 
    if ((sock = open_socket(sm->host, SMTP_PORT)) < 0)  { 
conPrintf("failed!\n"); 
logPrintf(LOG_ERR, "smtp: fail to connect to %s\n", sm->host); 
return sock; 
    } 
    conPrintf("ok.\n"); 
    logPrintf(LOG_INFO, "smtp: %s connected for sending.\n", sm->host); 
     
    rs = smtp_answer(sock, buf, SVRBUF); 
    if (rs != OK) 
return rs; 
    if (strncmp(buf, "220", 3)) 
return MISANSWER; 
     
    rs = smtp_helo(sock); 
    if (rs != OK) 
return rs; 
     
    /* if ((rs = smtp_reset(sock)) != OK) 
return rs; */ 
    
    for (scnt = 0, fo = rootfld; fo; fo = fo->next)  { 
conPrintf("Folder %s, %d messages are ready.\n", fo->name, fo->num); 
for (m = fo->mail; m; m = m->next)  { 
    if (verbose)  { 
conPrintf("sending %3d/%d, (%-8ld)\n",  
m->id, fo->num, m->msg->msize); 
    } else { 
conPrintf("sending %3d/%d, (%-8ld) ", 
m->id, fo->num, m->msg->msize); 
    } 
    rs = smtp_sendmsg(sock, m, sm->reply); 
    if (rs == OK) 
scnt++; 
    else if (rs != WARNING) 
break; /* fatal error encountered */ 

    } 

    smtp_quit(sock); 
    close(sock); 
    logPrintf(LOG_INFO, "smtp: %d mails delivered.\n", scnt); 

    return rs; 



[/code:1:f4f229a6fe] 
消息头控制 
[code:1:f4f229a6fe] 


#ifdef HAVE_CONFIG_H 
#include "config.h" 
#endif 

#include  
#include  
#include  
#include  

#include "defs.h" 

static char *chop_tail(char *p); 


Head *head_register(int page, int idx) 

    Head  *tmp; 

    if ((tmp = malloc(sizeof(Head))) == NULL)  return NULL; 
    memset(tmp, 0, sizeof(Head)); 

    tmp->pm = pm_handler(idx, page); 
    if (tmp->pm == NULL)  { 
free(tmp); 
return NULL; 
    } 

    tmp->this = tmp; 
    return tmp; 


void head_destruct(Head *hdo) 

    if (hdo != NULL)  { /* all memory allocating routines are issued*/ 
pm_close(hdo->pm); /* by pmalloc.c, therefore no more releasing*/ 
free(hdo->this); /* procession required */ 
    } 


char *head_loading(Head *hdo, char *s) 

    struct head_chain  *hc, *hctmp; 
    HLin   *hltmp; 
    int    len; 
     
    if (!isheadline(s))  return s; 

    /* continuing last head line 
       If a headline starts with a white space character such as SPACE, 
       H-TAB, it should be the remain part of last head line */ 
     
    if (isspace(*s))  {

/* it should not be the first of all the head part, otherwise 
   it declares the end of head part */ 
     
if (hdo->last == NULL)  return s; 

hctmp = pm_alloc(hdo->pm, sizeof(struct head_chain)); 
if (hctmp == NULL)  return s; 

hctmp->next = NULL; 
hctmp->str = pm_dup_str(hdo->pm, s); 

if (hdo->last->hc == NULL)  hdo->last->hc = hctmp; 
else { 
    for (hc = hdo->last->hc; hc->next; hc = hc->next); 
    hc->next = hctmp; 


if (hctmp->str)  { 
    len = strlen(hctmp->str); 
    hdo->last->len += len; 
    hdo->len += len; 

return NULL; 
    } 

    /* create new head line structure */ 
     
    hltmp = pm_alloc(hdo->pm, sizeof(HLin)); 
    if (hltmp == NULL)  return s; 
     
    hltmp->rm = 0; 
    hltmp->len = len = strlen(s); 
    hltmp->hc = hltmp->next = NULL; 
    hltmp->headin = pm_dup_str(hdo->pm, s); 
    if (hltmp->headin == NULL)  { 
hltmp->body = NULL; 
hltmp->key = NULL; 
    } else { 
hltmp->body = strchr(hltmp->headin, ':'); 
*hltmp->body = 0; 
hltmp->key = pm_dup_str(hdo->pm, hltmp->headin); 
chop_tail(hltmp->key); 
*hltmp->body = ':'; 
for (hltmp->body++; isspace(*hltmp->body); hltmp->body++); 
    } 
     
    if (hdo->hlin == NULL)  hdo->hlin = hltmp; 
    else  hdo->last->next = hltmp; 
     
    hdo->last = hltmp; 
    hdo->len += len; 
    hdo->num++; 
     
    return NULL; 


void head_clean(Head *hdo) 

    pm_free(hdo->pm); 
    hdo->len = 0; 
    hdo->num = 0; 
    hdo->fmsp = NULL; 
    hdo->hlin = NULL; 
    hdo->last = NULL; 
    hdo->skey = NULL; 
    hdo->scur = NULL; 


/* put the head part in the file into head cache  
   Note: when call this function, the FromSps line should be inside the 
   'buf' argument, and file seeking in the 'fin' has moved to next line */ 

int head_to_cache(Head *hdo, FILE *fin, char *buf, int len) 

    hdo->fmsp = pm_dup_str(hdo->pm, buf); 
    while (fgets(buf, len, fin))  {
if (head_loading(hdo, buf) != NULL)  break; 
    } 
    return 0; 


int head_of_file(Head *hdo, FILE *fin, char *buf, int len) 
{
    /* skip leading nonsense lines */ 

    while (fgets(buf, len, fin))  { 
if (ismailstart(buf))   
    return head_to_cache(hdo, fin, buf, len); 
    } 

    return -1; 
}    

char *head_append(Head *hdo, char *head) 

    return head_loading(hdo, head); 
}


void head_remove_first(Head *hdo, char *key) 

    HLin  *hl; 

    for (hl = hdo->hlin; hl; hl = hl->next)  { 
if (!strcasecmp(hl->key, key))  { 
    hl->rm = 1; 
    break; 

    } 


void head_remove_all(Head *hdo, char *key) 

    HLin  *hl; 

    for (hl = hdo->hlin; hl; hl = hl->next)  { 
if (!strcasecmp(hl->key, key))  hl->rm = 1; 
    } 



/* check heads against given mask. If rm set, remove all heads in the mask; 
 * otherwise remove all heads except heads in the mask */ 

void head_mask(Head *hdo, char *mask, int rm) 

    HLin  *hl; 
    char  *p, *k, flag, buf[512]; 

    strncpy(buf, mask, 511); 
    buf[511] =  0; 
    for (hl = hdo->hlin; hl; hl = hl->next)  { 
p = k = buf; 
flag = 0; 
while (*p)  { 
    k = strchr(p, ':'); 
    if (k)  *k = 0; 

    if (!strcasecmp(hl->key, p))  { 
if (rm)  hl->rm = 1; 
flag = 1; 
    } 

    if (k)  *k = ':', p = k + 1; 
    else  break; 
    if (flag == 1)  break; 

if (!flag && !rm)  hl->rm = 1; 
    } 


     
HLin *head_check(Head *hdo, char *key) 

    HLin  *hl; 

    hdo->skey = pm_dup_str(hdo->pm, key); 
    for (hl = hdo->hlin; hl; hl = hl->next)  { 
if (!strcasecmp(hl->key, key) && !hl->rm)  { 
    hdo->scur = hl->next; 
    return hl; 

    } 
    return NULL; 



HLin *head_check_next(Head *hdo) 

    HLin  *hl; 

    if (hdo->skey == NULL)  return NULL; 
     
    for (hl = hdo->scur; hl; hl = hl->next)  { 
if (!strcasecmp(hl->key, hdo->skey) && !hl->rm)  { 
    hdo->scur = hl->next; 
    return hl; 

    } 
    return NULL; 



char *head_fetch(HLin *h) 

    char  *p; 
    struct  head_chain  *hc; 

    if ((p = malloc(h->len + 1)) == NULL)  return NULL; 

    strcpy(p, h->headin); 
    for (hc = h->hc; hc; hc = hc->next)  strcat(p, hc->str); 

    return p; 



char *head_fetch_body(HLin *h) 

    char  *p; 
    struct  head_chain  *hc; 

    if ((p = malloc(h->len + 1)) == NULL)  return NULL; 

    strcpy(p, h->body); 
    for (hc = h->hc; hc; hc = hc->next)  strcat(p, hc->str); 

    return p; 


/* Has the specified class headline existed ?  
   It check the head index (class) first, then search the cache for  
   the same class head */ 

HLin *head_exist(Head *hdo, char *head) 

    char  idx[256]; 
    HLin  *hl; 

    if (head_index(head, idx, 256) == NULL)  return NULL; 
     
    for (hl = hdo->hlin; hl; hl = hl->next)  { 
if (!strcasecmp(hl->key, idx) && !hl->rm)  return hl; 
    } 
    return NULL; 

     
     
void head_dump(Head *hdo, FILE *fout, int fmsp) 

    HLin   *hl; 
    struct head_chain *hc; 

    if (hdo->fmsp && fmsp)  fputs(hdo->fmsp, fout); 
     
    for (hl = hdo->hlin; hl; hl = hl->next)  { 
if (hl->rm)  continue; 

if (hl->headin)  fputs(hl->headin, fout); 

for (hc = hl->hc; hc; hc = hc->next)   
    fputs(hc->str, fout); 
    } 
    fflush(fout); 



char *head_index(char *headline, char *buf, int len) 

    char  *p; 
     
    strncpy(buf, headline, len); 
    buf[len-1] = 0; 
    p = strchr(buf, ':'); 
    if (p == NULL)  return NULL; 
    *p = 0; 
    chop_tail(buf); 
    return buf; 

     

int head_cmp(char *s, char *d) 

    char  sh[256], dh[256]; 

    if (!s || !d)  return 1; 
     
    s = head_index(s, sh, 256); 
    d = head_index(d, dh, 256); 
     
    if (!s && !d)  return 0; /* they are all the same non-heads */ 
    if (!s || !d)  return 1;
     
    return strcasecmp(sh, dh); 


/* 
static int isblankline(char *buf) 

    while (*buf)  { 
       if (isspace(*buf))  buf++; 
       else  return 0; 
    } 
    return 1; 


static int isheadline(char *buf) 

    if (isblankline(buf))  return 0; 
    if (isspace(*buf))  return 1; 
    if (strchr(buf, ':'))  return 1; 
    return 0; 

*/ 


static char *chop_tail(char *p) 

    int  i; 

    if (p == NULL)  return p; 
    for (i = strlen(p); (i >= 0) && (p[i] >= 0) && (p[i] <= ' '); p[i--] = 0); 
    return p; 



#ifdef EXECUTABLE 


int main(int argc, char **argv) 

    FILE  *fp; 
    Head  *head; 
    HLin  *hl; 
    char  buf[512], tmp[512]; 

    if (argc < 2)  { 
printf("usage:  %s folder\n", argv[0]); 
return 0; 
    } 

    head = head_register(4096, 128); 
    if (head == NULL)  return 1; 
     
    fp = fopen(argv[1], "r"); 
    if (fp == NULL)  return 1; 

    while (!feof(fp))  { 
head_of_file(head, fp, buf, 512); 

head_append(head, "myhead1: nothing at all\n"); 
head_append(head, "myhead2: good day\n and bad day\n"); 

printf("> Head %d items, %d bytes in total.\n", head->num, head->len); 
head_dump(head, stdout, 1); 

while (fgets(tmp, 512, stdin))  { 
    chop_tail(tmp); 
    if ((hl = head_check(head, tmp)) != NULL)  { 
printf("## %s", hl->headin); 
head_remove_all(head, tmp); 
head_dump(head, stdout, 1); 
    } 


head_clean(head); 
printf("\n"); 
    } 

    fclose(fp); 
    head_destruct(head); 
    return 0; 


#endif 


[/code:1:f4f229a6fe]

 蓝色键盘 回复于:2003-04-25 13:47:40
消息控制 
[code:1:3e0cea3f47] 


#ifdef HAVE_CONFIG_H 
#include "config.h" 
#endif 

#include  
#include  
#include  
#include  
#include  
#include  
#include  

#if HAVE_UNISTD_H 
  #include  
  #include  
#endif 

#if HAVE_FCNTL_H 
  #include  
#endif 

#include "defs.h" 

#if     !defined(isspace) 
#define isspace(ch)     (((ch) > 0) && ((ch) <= ' ')) 
#endif 
  
/* putting globle variety here is not a good idea. But it's easy to use. 
 * Before the implementation of any kind of thread, I think it's not real 
 * harmful for the program */ 

static Head *head = NULL; 

static MsgObj *msgobj_extension(Mail *m); 
static Mail *fld_split(char *path, char *fldname, int fid, int *err, int beh); 
static char *glob_letter(char *, char *, char *, int , int ); 
static char *mail_body(Mail *m, FILE *fin, FILE *fout, char *buf, int len); 
static char *fill_mail_obj(Mail *m, FILE *fp, char *buf, int len); 
static int pine_start_cmp(char *buf); 


/* load specified folder and create a folder object. 
 * path: the directory for storing these one-message-folders. e.g. /tmp 
 * fldname: the matrix folder. Each child folder uses it as name prefix 
 * fid: the identity allocate to the folder object. 
 * pp:  flag of postpone folder. 
 * return: the Mail object chain or die with NULL. 
 * Note: if the path existed, it should NOT end with path seperator, '/'. 
 */ 

Folder *msg_loader(char *path, char *fldname, int fid, int pp, int beh) 

    Folder  *fo; 
    Mail    *anchor; 
    int     rs, err; 

    if (head == NULL)  { 
head = head_register(HDPAGE, HDIDX); 
if (head == NULL)  { 
    dbgPrintf("Fail to create Head object.\n"); 
    return NULL; 

    } 

    anchor = fld_split(path, fldname, fid, &err, beh); 

    /* Even the folder spliting failed, we still think it to available 
     * due to null folder or zero size folder */ 
     
    if ((err == PM_MSG_BADFILE) || (err == PM_MSG_BINARY))   
return NULL; 

    rs = sizeof(Folder) + strlen(fldname) + 4; 
    if ((fo = (Folder*) malloc(rs)) == NULL)  return NULL; 
    memset(fo, 0, rs); 

    fo->fid  = fid; 
    fo->name = fo->_namebuf; 
    fo->cur  = fo->lst = 1; 
    fo->pp   = pp; 
    fo->mail = anchor; 
    strcpy(fo->name, fldname); 

    msg_statistics(fo); 
    if (fo->num == 0)  fo->cur = 0; 
    return fo; 



/* combine these seperate one-message-folders into one folder. 
 * return: number of stored message. 
 */ 

int msg_combine(Folder *fo) 

    FILE  *fin, *fout; 
    char  buf[SVRBUF]; 
    Mail  *m; 
    int   cnt; 

    if ((fout = fopen(fo->name, "w")) == NULL)  { 
dbgPrintf("msg_combine: cannot write to [%s].\n", fo->name); 
return PM_MSG_BADFILE; 
    } 

    for (cnt = 0, m = fo->mail; m; m = m->next)  { 
if (m->removed)  continue; 

if ((fin = fopen(m->msg->name, "r")) == NULL)  { 
    dbgPrintf("msg_combine: open [%s] failed.\n", m->msg->name); 
    continue; 


if (!fo->pp && m->changed) { 
    while (fgets(buf, SVRBUF, fin))  { 
if (!strncasecmp(buf, "status:", 7))  { 
    fputs("Status: RO\n", fout); 
    break; 
} else if (isblankline(buf))  { 
    fputs("Status: RO\n\n", fout); 
    break; 
} else fputs(buf, fout); 
    }    


/* large block tranfering */ 

dup_stream(fin, fout); 

/* if the message does not end with blank line ... */ 
fputs("\n", fout); 

fclose(fin); 
cnt++; 
    } 
     
    return cnt; 


/* desconstruct the Mail object chain */ 

int msg_clean(Folder *fo) 

    Mail    *tmp, *m; 
    MsgObj  *mo; 

    m = fo->mail; 
    while (m)  { 
     
free(m->from); 
free(m->reply); 
free(m->to); 
free(m->cc); 
free(m->bcc); 
free(m->subject); 
free(m->c_type); 

/* free MsgObj chain and relative temprary folder. 
 * Note that the last MsgObj is derived from Mail object, 
 * so do not free it. */ 

while (m->msg->next)  { 
    mo = m->msg; 
    if (unlink(mo->name) < 0)  perror("unlink"); 
    m->msg = m->msg->next; 
    free(mo); 

if (unlink(m->msg->name) < 0)  perror("unlink"); 

tmp = m; 
m = m->next; 
free(tmp); 
    } 
    return PM_MSG_OK;    


void msg_free_mailobj(Mail *m) 

    MsgObj  *mo; 
     
    free(m->from); 
    free(m->reply); 
    free(m->to); 
    free(m->cc); 
    free(m->bcc); 
    free(m->subject); 
    free(m->c_type); 

    /* free MsgObj chain and relative temprary folder. 
     * Note that the last MsgObj is derived from Mail object, 
     * so do not free it. */ 

    while (m->msg->next)  { 
mo = m->msg; 
if (unlink(mo->name) < 0)  perror("unlink"); 
m->msg = m->msg->next; 
free(mo); 
    } 
    if (unlink(m->msg->name) < 0)  perror("unlink"); 



/* search identified message. */ 

Mail *msg_search_id(Folder *fo, int id) 

    Mail *m; 
     
    for (m = fo->mail; m; m = m->next)   
if (m->id == id)  break; 
    return m; 


int  msg_last_actived(Folder *fo) 

    Mail  *m; 
    int   id; 

//    if (fo == NULL)  return 0; 
    for (id = 0, m = fo->mail; m; m = m->next)  { 
if (!m->removed)  id = m->id; 
    } 
    return id; 


/* dump specified message to screen  
 * m: mail object 
 * pager: external pager.  
 * return: 0, success. 1, no message  
 * Note that this function doest not check removed flag. */ 
  
int msg_dump(Mail *m, char *pager) 

    FILE  *fp; 
    char  buf[SVRBUF]; 
    time_t  dc; 

#ifdef DEBUG 
    if (!m)  { 
     dbgPrintf("msg_dump: No Mail object.\n"); 
     return PM_MSG_INVALID; 
    } 
#endif 

    /* if (!m->oldmail)  m->changed = 1; */ 
     
    /* when there is no pager specified, we just display it */ 
     
    if (pager == NULL)  { 
if ((fp = fopen(m->msg->name, "r")) == NULL)   
    return PM_MSG_BADFILE; 
while (fgets(buf, SVRBUF, fp))   
    printf("%s", buf); 
fclose(fp); 
return PM_MSG_OK; 
    } 
     
    /* or call a external pager. Note that the behavior between  
     * more and less */ 
     
    if (!strcmp(pager, "/bin/more") || !strcmp(pager, "/usr/bin/more"))  { 
sprintf(buf, "%s %s", pager, m->msg->name); 
    } else sprintf(buf, "cat %s | %s", m->msg->name, pager); 
     
    system(buf); 

    /* double check the time stamp of temp folder. If the pager edited 
     * this temp folder, we should mark it as changed */ 
     
    dc = filedate(m->msg->name, &m->msg->msize); 
    if (dc > m->msg->mtime)  { 
m->changed = 1; 
        m->msg->mtime = dc; 

#ifdef DEBUG 
/* printf("message %d [%s] was changed.\n", m->id, m->msg->name); */ 
#endif 
    } 
     
    return PM_MSG_OK; 
}    

/* append a message' body to an external file */ 

int  msg_appendto(Mail *m, char *fname) 

    FILE  *fin, *fout; 

    if ((fin = fopen(m->msg->name, "r")) == NULL)  return PM_MSG_BADFILE; 
    if ((fout = fopen(fname, "a")) == NULL)  { 
dbgPrintf("msg_appendto: cannot open target file [%s]\n", fname); 
fclose(fin); 
return PM_MSG_BADFILE; 
    } 

    dup_stream(fin, fout); 

    fclose(fout); 
    fclose(fin); 
    return PM_MSG_OK; 



static MsgObj *msgobj_extension(Mail *m) 

    MsgObj  *tmp, *tail; 
    char    buf[SVRBUF]; 
    int     len; 
    union   { 
void *p; 
unsigned short s[2]; 
    } mixer; 

#ifdef DEBUG 
    if (m == NULL)  { 
printf("Fatal error at msgobj_extension()\n"); 
return NULL; 
    } 
#endif 
     
    mixer.p = m->msg; 
    for (tail = m->msg; tail->next; tail = tail->next); 
    sprintf(buf, "%s%04x", tail->name, mixer.s[0] ^ mixer.s[1]); 
     
    len = sizeof(MsgObj) + strlen(buf) + 4; 
    tmp = (MsgObj*) malloc(len); 
    if (tmp == NULL)  return NULL; 
     
    memset(tmp, 0, len); 
    tmp->name = tmp->_namebuf; 
    strcpy(tmp->name, buf); 
    //printf("new message folder: %s\n", tmp->name); 

    return tmp; 



int  msg_edit(Mail *m, char *editor) 

    MsgObj  *tmp; 
    time_t  dc; 
    char    buf[SVRBUF]; 

    if (!m || !editor)  return PM_MSG_INVALID; 
     
    tmp = msgobj_extension(m); 
    if (tmp == NULL)  return PM_MSG_NOMEM; 
     
    /* duplicate this message */ 
     
    if (msg_duplicate(tmp->name, m->msg->name) <= 0)  { 
free(tmp); 
return PM_MSG_BADFILE; 
    } 
     
    dc = filedate(tmp->name, &tmp->msize); 
    sprintf(buf, "%s %s", editor, tmp->name); 
    system(buf); 
     
    tmp->mtime = filedate(tmp->name, &tmp->msize); 
    if (tmp->mtime <= dc)  { 
unlink(tmp->name); 
free(tmp); 
    } else { 
m->changed = 1; 
tmp->next = m->msg; 
m->msg = tmp; 
    } 

    return PM_MSG_OK; 


/**************************** pipe routines ***********************/ 

static int  
msg_pipe_disable(MsgObj *mo, FILE *fin, FILE *fout, char *buf, int len) 

    int  ll = 0; 
     
    while (fgets(buf, len, fin))  { 
     
if (isblankline(buf))  ll = 1; 
else  ll = 0; 

fputs(buf, fout); 
mo->len += strlen(buf); 
mo->line++; 
    } 
     
    if (ll == 1)  { 
fputs("\n", fout); 
mo->len++; 
mo->line++; 
    } 
     
    return mo->len; 


static int 
msg_pipe_through(MsgObj *mo, FILE *fin, FILE *fout, char *sig,  
char *buf, int len) 

    char *p; 
    int  ll = 0; 
     
    *buf = '>'; 
    p = buf + 1; 
    while (fgets(p, len - 1, fin))  { 
     
if (isblankline(buf))  ll = 1; 
else  ll = 0; 

if (strncmp(p, "From ", 5))  { 
    mo->len += strlen(p); 
    fputs(p, fout); 
} else { 
    mo->len += strlen(buf); 
    fputs(buf, fout); 

mo->line++; 
    } 

    if ( sig )  { 
mo->len += strlen(sig); 
fputs(sig, fout); 
ll = 1; 
    } 

    if (ll == 1)  { 
fputs("\n", fout); 
mo->len++; 
mo->line++; 
    } 
     
    return mo->len; 


static int  
msg_pipe_do(MsgObj *mo, FILE *fin, FILE *fout, char *piper, int ctl,  
char *sig, char *buf, int len) 

    int    tsub[2], rs; 
    char   *args[128], *p; 
    pid_t  cpid; 

     
    if (pipe(tsub))  return 1; 

    if ((cpid = fork()) == -1)  return 2; 

    if (cpid == 0)  { 
dup2(tsub[0], 0); 
dup2(fileno(fout), 1); 
close(2); 
open("/dev/null", O_RDWR); 
close(tsub[0]); 
close(tsub[1]); 
if (mkargs(piper, args, 128) < 0)  exit(-1); 
execvp(args[0], args); 
exit(-2); 
    } 

    close(tsub[0]); 
     
    *buf = '>'; 
    p = buf + 1; 
    while (fgets(p, len - 1, fin))  { 

if ( ctl && !strncmp(p, "From ", 5))  { 
    rs = write(tsub[1], buf, strlen(buf)); 
} else { 
    rs = write(tsub[1], p, strlen(p)); 


if (rs < 0)  { 
    close(tsub[1]); 
    return 2; 

    } 

    if ( ctl && sig )   
write(tsub[1], sig, strlen(sig)); 

    close(tsub[1]); 
     
    waitpid(cpid, NULL, 0); 
    return 0; 


static void  
msg_pipe_prohead(Mail *m, Head *head, char *buf, int len) 

    char *p; 
     
    head_remove_all(head, HD_ACTION); 
    head_remove_all(head, HD_BCC); 
     
    if ((m->behave & ACT_EHEAD) != 0)  { 
/* appending extra head */ 

for (p = rc_check(RCKEY_HEADER); p; p = rc_check_next())  { 
    if (head_exist(head, p) == NULL)  { 
/* printf("%s", p); */ 
sprintf(buf, "%s\n", p); 
head_append(head, buf); 
    } 

    } 
     
    if (!head_check(head, HD_MAILER))  { 
        sprintf(buf, XMAILER, VERSION); 
        head_append(head, buf); 
    } 


/* pipe message body through an external pipe. 
 * The piped message will occupy a new MsgObj object, then insert it 
 * to the top of the MsgObj chain. So the original message could be  
 * reserved. Note that this function doesn't check removed flag. */ 

int  msg_pipeto(Mail *m, char *piper, int ctl, char *sig) 

    MsgObj  *tmp; 
    FILE    *fin, *fout; 
    char    buf[SVRBUF]; 
     
     
    if (!m || !piper)  return PM_MSG_INVALID; 

    if (ctl == 1)  { 
if (((m->behave & ACT_SUSP) != 0) || 
    ((m->behave & ACT_NORM) == 0))  return PM_MSG_OK; 
    } 
     
    if ((m->behave & ACT_ASIG) == 0)  sig = NULL; 
     
     
      /* make up a piped folder name, then create a new MsgObj */ 
     
    tmp = msgobj_extension(m); 
    if (tmp == NULL)  return PM_MSG_NOMEM; 

     
      /* open the source message and the target, piped message */ 
     
    if ((fin = fopen(m->msg->name, "r")) == NULL)  { 
dbgPrintf("msg_pipeto: cannot open message folder, abort! [%s]\n",  
m->msg->name); 
free(tmp); 
return PM_MSG_BADFILE; 
    } 
     
    if ((fout = fopen(tmp->name, "w")) == NULL)  { 
dbgPrintf("msg_pipeto: cannot open piped folder, abort! [%s]\n",  
tmp->name); 
free(tmp); 
fclose(fin); 
return PM_MSG_BADFILE; 
    } 

     
      /* pre-write the message head, they should not be piped to */ 

    head_clean(head); 
    head_of_file(head, fin, buf, SVRBUF); 
     
    if ( ctl )  { 
msg_pipe_prohead(m, head, buf, SVRBUF); 
    } 
     
    head_dump(head, fout, 1); 
    /* head_dump(head, stdout, 1); */ 
     
    fprintf(fout, "\n"); 
    tmp->boff = ftell(fout); 
    fflush(fout); 

     
    /* create pipe and pipe message body to it */ 
     
    if (!piper || !(m->behave & ACT_PIPE))  { 
     
if ( ctl )  msg_pipe_through(tmp, fin, fout, sig, buf, SVRBUF); 
else  msg_pipe_disable(tmp, fin, fout, buf, SVRBUF); 

    } else { 

if (msg_pipe_do(tmp, fin, fout, piper, ctl, sig, buf, SVRBUF))  { 
    dbgPrintf("msg_pipeto: pipe failed!\n"); 
    free(tmp); 
    fclose(fin); 
    fclose(fout); 
    return PM_MSG_BADPIPE; 

    } 

    fclose(fin); 
    fclose(fout); 
     
    /* check the time stamp for the piped file */ 
     
    if ((tmp->mtime = filedate(tmp->name, &tmp->msize)) < 0)   
tmp->mtime = 0; 
     
    if (tmp->len == 0)   
tmp->len = tmp->msize - tmp->boff; 
     
    /* insert piped message into message object chain */ 

    tmp->next = m->msg; 
    m->msg = tmp; 
    m->changed = 1; 
    m->piped = 1; 
     
    return PM_MSG_OK; 



#ifdef __NO_THAT_DEFINATION 

int  msg_pipe2(Mail *m, char *piper, char *sig) 

    MsgObj  *tmp; 
    FILE    *fin, *fout; 
    char    buf[SVRBUF], *p; 
    pid_t   cpid; 
     
     
    if (!m)  return PM_MSG_INVALID; 
     
    if (((m->behave & ACT_SUSP) != 0) || 
((m->behave & ACT_NORM) == 0))  return PM_MSG_OK; 

    /* make up a piped folder name, then create a new MsgObj */ 
     
    tmp = msgobj_extension(m); 
    if (tmp == NULL)  return PM_MSG_NOMEM; 

    /* open the source message and the target, piped message */ 
     
    if ((fin = fopen(m->msg->name, "r")) == NULL)  { 
dbgPrintf("msg_pipe2: cannot open message folder, abort! [%s]\n",  
m->msg->name); 
free(tmp); 
return PM_MSG_BADFILE; 
    } 
     
    if ((fout = fopen(tmp->name, "w")) == NULL)  { 
dbgPrintf("msg_pipe2: cannot open piped folder, abort! [%s]\n",  
tmp->name); 
free(tmp); 
fclose(fin); 
return PM_MSG_BADFILE; 
    } 

    /* pre-write the message head, they should not be piped to */ 

    head_all_cache(fin, buf, SVRBUF); 
    if (head_check(HD_ACTION) != NULL)  head_remove(HD_ACTION); 
    if (head_check(HD_BCC) != NULL)  head_remove(HD_BCC); 
    if ((m->behave & ACT_EHEAD) != 0)  {  /* appending extra head */ 
for (p = rc_check(RCKEY_HEADER); p; p = rc_check_next())  { 
    if (head_exist(p) == NULL)  head_append(p); 

    } 
    if (!head_check(HD_MAILER))  { 
sprintf(buf, XMAILER, VERSION); 
head_append(buf); 
    } 
    head_dump(fout); 
    head_clean_cache(); 
     
    fprintf(fout, "\n"); 
    tmp->boff = ftell(fout); 
    fclose(fout); 

    /* open external pipe or re-open output message folder */ 
     
    if ((cpid = fork()) == -1)  { 
perror("fork"); 
unlink(tmp->name); 
free(tmp); 
fclose(fin); 
return PM_MSG_BADPIPE; 
    } 
     
    if (cpid == 0)  { /* child */ 
   
if (!piper || !(m->behave & ACT_PIPE))  {  /* no pipe wanted */ 
    fout = fopen(tmp->name, "a"); 
} else { /* create pipe */ 
    sprintf(buf, "%s >> %s", piper, tmp->name); 
    fout = popen(buf, "w"); 
     } 
if (fout == NULL)  { 
    dbgPrintf("msg_pipe2: open external pipe failed.\n"); 
    exit(-1); 

     
*buf = '>'; 
p = buf + 1; 
while (fgets(p, SVRBUF - 1, fin))  { 
    if (strncmp(p, "From ", 5))  tmp->len += fprintf(fout, "%s", p); 
    else  tmp->len += fprintf(fout, "%s", buf); 
    tmp->line++; 


if ((m->behave & ACT_ASIG) && sig)  { 
    tmp->len += fprintf(fout, "%s", sig); 


if (!piper || !(m->behave & ACT_PIPE))  fclose(fout); 
else  pclose(fout); 
exit(0); 
    } 
    waitpid(cpid, NULL, 0); 
    fclose(fin); 

    if ((tmp->mtime = filedate(tmp->name, &tmp->msize)) < 0)   
tmp->mtime = 0; 
     
    /* insert piped message into message object chain */ 

    tmp->next = m->msg; 
    m->msg = tmp; 
    m->changed = 1; 
    m->piped = 1; 
     
    return PM_MSG_OK; 


#endif 


/* undo a pipe message chain. 
 * pick out the toppest message from the MsgObj chain. If there is only 
 * one MsgObj existed, do not touch it: it's original message. */ 

int msg_unpipe(Mail *m) 

    MsgObj  *tmp; 
     
    if (!m || !m->msg->next)  return PM_MSG_INVALID; 

    tmp = m->msg; 
    m->msg = m->msg->next; 

    if (unlink(tmp->name) < 0)  perror("unlink"); 
    free(tmp); 
    if (m->msg->next == NULL)  m->piped = 0; 

    return PM_MSG_OK; 


/* get message statistics data. Do not use this function often. It checks 
 * file status by stat(2) system call.  */ 

void msg_statistics(Folder *fo) 

    Mail *m; 

    fo->num = fo->chg = fo->rm = fo->unrd = 0; 
     
    for (m = fo->mail ; m; m = m->next)  { 
if (m->removed)  fo->rm++; 
if (!m->changed && !m->oldmail)  fo->unrd++; 
if (m->changed || m->piped)  fo->chg++; 
else if (m->msg->mtime < filedate(m->msg->name, &m->msg->msize)) {  
    fo->chg++; 

fo->num++; 
    } 



/* check if there is a chenged message in the message chain. 
   This function do not check the time stamp of message folder. */ 

int  msg_change_flag(Folder *fo) 

    Mail *m; 

    for (m = fo->mail; m; m = m->next)  { 
if (m->removed || m->changed || m->piped)  return 1; 
    } 
    return 0; 

    

/* pick out a specified Mail object from message chain. 
 * This is useful when move a message from one chain to another. 
 * The message will be absolutely removed, no chance to undo.  
 * Note that the removed message cannot be picked up. */ 

Mail *msg_pickout(Folder *fo, int id) 

    Mail  anchor, *m; 
     
#ifdef DEBUG 
    if (fo == NULL)  { 
printf("msg_pickout: invaild pointer.\n"); 
return NULL; 
    } 
#endif 
     
    anchor.id = id + 1; 
    anchor.next = fo->mail; 
     
    for (m = & m->next; m = m->next)  { 
if (m->next->id == id)  break; 
    } 
    if (!m->next || m->next->removed)  return NULL; 

    anchor.next = m->next; 
    if (m->next == fo->mail)  fo->mail = fo->mail->next; 
    else  m->next = m->next->next; 

#ifdef DEBUG 
    if (anchor.next->id != id)  { 
printf("!!!!!!!!!!!!!!!!!!!!!\n"); 
anchor.next = NULL; 
    } 
#endif 

    fo->fchg = 1; 
    fo->num--; 
    if (!anchor.next->oldmail)  fo->unrd--; 
    return anchor.next; 


/* the opposite operation of msg_pickout(). 
 * Insert a message object at the end of message chain.  */ 

void msg_insert(Folder *fo, Mail *m) 

    Mail  *k; 
    int   mid = 0; 

    if (fo->mail == NULL)  fo->mail = m; 
    else  { 
for (k = fo->mail; k->next; k = k->next); 
k->next = m; 
mid = k->id; 
    } 
    m->id = mid + 1; 
    m->next = NULL; 
    fo->fchg = 1; 
    if (!m->oldmail)  fo->unrd++; 
    if (m->removed)  fo->rm++; 
    else  fo->num++; 


/* expand an element in the tail of the specified message chain. 
 * It creates a null Mail object except the id and MsgObj with 
 * relatively folder name, but no message created. 
 * This function is used to reply or follow a message */ 

Mail *msg_expand(Folder *fo, char *path, Mail *ins) 

    Mail  *m, *k; 
    int   len, mid = 0; 
     
#ifdef DEBUG 
    if (fo == NULL)  { 
printf("msg_expand\n"); 
return NULL; 
    } 
#endif 

    /* search for last message and its id number */ 
     
    for (m = fo->mail; m && m->next; m = m->next); 
    if (m)  mid = m->id + 1; 
    else  mid = 1; 

    /* create a new Mail object */ 
     
    len = sizeof(Mail) + strlen(fo->name) + (sizeof(int) << 2) + 4; 
    if (path)  len += strlen(path); 
    if ((k = (Mail*) malloc(len)) == NULL)  return NULL; 
    memset(k, 0, len); 
    k->id = mid; 
    k->msg = k->_msgbuf; 
    k->msg->name = k->msg->_namebuf; 
    glob_letter(k->msg->name, path, fo->name, fo->fid, k->id); 
     
    /* insert it at the end of message chain */ 

    if (m == NULL)  fo->mail = k, fo->cur = 1; 
    else  m->next = k; 

    if (ins)  msg_dup_entry(k, ins); 

    if (k->removed)  fo->rm++; 
    else  fo->num++; 
    if (!k->oldmail)  fo->unrd++; 
    fo->fchg = 1; 
    return k; 


/* duplicate a message entry to another Mail object 
   These items are NOT duplicated: id, flags, link to next object, 
   MsgObjs out of first one, and the name of folder in the MsgObj. */ 

void msg_dup_entry(Mail *dest, Mail *sour) 

    dest->removed = sour->removed; 
    dest->changed = sour->changed; 
    dest->oldmail = sour->oldmail; 
    dest->replied = sour->replied; 
    dest->from    = dup_str(sour->from); 
    dest->reply   = dup_str(sour->reply); 
    dest->to      = dup_str(sour->to); 
    dest->cc      = dup_str(sour->cc); 
    dest->bcc     = dup_str(sour->bcc); 
    dest->subject = dup_str(sour->subject); 
    dest->c_type  = dup_str(sour->c_type); 
    dest->rtime   = sour->rtime; 
    dest->behave  = sour->behave; 

    /* I don't duplicate the folder, just make a hard link to it  
    if (link(sour->msg->name, dest->msg->name) < 0)  perror("link"); */ 

    msg_duplicate(dest->msg->name, sour->msg->name); 
    dest->msg->mtime = filedate(dest->msg->name, &dest->msg->msize); 
    dest->msg->len   = sour->msg->len; 
    dest->msg->line  = sour->msg->line; 
    dest->msg->boff  = sour->msg->boff; 


long msg_duplicate(char *dest, char *sour) 

    FILE *fin, *fout; 
    long len = 0; 

    if ((fin = fopen(sour, "r")) == NULL)  { 
dbgPrintf("Cannot open message folder! [%s]\n", sour); 
return -1; 
    } 
     
    if ((fout = fopen(dest, "w")) == NULL)  { 
dbgPrintf("Cannot open target folder! [%s]\n", dest); 
fclose(fin); 
return -1; 
    } 

    len += dup_stream(fin, fout); 

    fclose(fout); 
    fclose(fin); 
    return len; 

     
/* BUGS: it modifies the original string that contains behavior line */ 

int msg_behave_bind(char *s) 

    char  *idx[16]; 
    int   i, num, rs; 
     
    num = ziptoken(s, idx, 16, DELIMS); 
    for (rs = i = 0; i < num; i++)  { 
if (!strcasecmp(idx[i], "default"))  { 
    rs = ACT_DEFT; 
    break; 

    } 
     
    for (i = 0; i < num; i++)  { 
if (!strcasecmp(idx[i], "pipe"))        rs |= ACT_PIPE; 
else if (!strcasecmp(idx[i], "sign"))   rs |= ACT_ASIG; 
else if (!strcasecmp(idx[i], "exhd"))   rs |= ACT_EHEAD; 
else if (!strcasecmp(idx[i], "dele"))   rs |= ACT_DELE; 
else if (!strcasecmp(idx[i], "bkup"))   rs |= ACT_BACK; 
else if (!strcasecmp(idx[i], "suspd"))  rs |= ACT_SUSP; 
else if (!strcasecmp(idx[i], "pure"))   rs &= ~ACT_NORM; 
else if (!strcasecmp(idx[i], "hold"))   rs &= ~ACT_SMTP; 
else if (!strcasecmp(idx[i], "unpipe")) rs &= ~ACT_PIPE; 
else if (!strcasecmp(idx[i], "nopipe")) rs &= ~ACT_PIPE; 
else if (!strcasecmp(idx[i], "unsign")) rs &= ~ACT_ASIG; 
else if (!strcasecmp(idx[i], "nosign")) rs &= ~ACT_ASIG; 
else if (!strcasecmp(idx[i], "unexhd")) rs &= ~ACT_EHEAD; 
else if (!strcasecmp(idx[i], "noexhd")) rs &= ~ACT_EHEAD; 
    } 
    return rs; 



/* split the message folder into a series of one-message-folder. 
 * path: the directory for storing these one-message-folders. e.g. /tmp 
 * fldname: the matrix folder. Each child folder uses it as name prefix 
 * return: the Mail object chain or die with NULL. 
 * Note: if the path existed, it should NOT end with path seperator, '/'. 
 */ 

static Mail *fld_split(char *path, char *fldname, int fid, int *err, int beh) 

    FILE  *fp; 
    char  buf[SVRBUF]; 
    Mail  *anchor, *tmp, *m; 
    int   i, rs, ch, id, len; 
     
    if ((fp = fopen(fldname, "r")) == NULL)  { 
if (errno == ENOENT)  *err = PM_MSG_NOFILE; 
else  *err = PM_MSG_BADFILE; 
return NULL; 
    } 

    /* double check is this a binary file */ 
     
    if ((rs = fread(buf, 1, SVRBUF, fp)) < 0)  { 
*err = PM_MSG_BADFILE; 
return NULL; 
    } 
     
    for (i = 0; i < rs; i++)  { 
        if (!isspace(buf[i]) && (buf[i] < ' ') && (buf[i] >= 0))  { 
            // printf("%c %d\n", buf[i], buf[i]); 
    *err = PM_MSG_BINARY; 
            return NULL; 
        } 
    } 
    rewind(fp); 

     
    buf[0] = 0; 
    id = ch = 0; 
    anchor = NULL; 
    while (!feof(fp))  { 

while (!ismailstart(buf))  { 
    if (!isblankline(buf))  ch++;  /* counte non-message line */ 
    if (!fgets(buf, SVRBUF, fp))  goto load_ok; 


/* create a Mail object */ 
/* the size of Mail object should be larger than it used to 
 * due to the filename in the MsgObj */ 

len = sizeof(Mail) + strlen(fldname) + (sizeof(int) << 2) + 4; 
if (path)  len += strlen(path); 
if ((tmp = (Mail*) malloc(len)) == NULL)  break; 
memset(tmp, 0, len); 
tmp->id  = ++id; 
tmp->msg = tmp->_msgbuf; 
tmp->behave = beh; 
tmp->msg->name = tmp->msg->_namebuf; 
glob_letter(tmp->msg->name, path, fldname, fid, tmp->id); 

/* If this is anchor message of Pine, mark it as SUSPENDED */ 

if (!pine_start_cmp(buf))  tmp->behave = ACT_SUSP; 

/* insert it into Mail object chain */ 

if (anchor == NULL)  anchor = tmp; 
else  { 
    for (m = anchor; m->next; m = (Mail*) m->next); 
    m->next = (void*) tmp; 


fill_mail_obj(tmp, fp, buf, SVRBUF); 
    } 

load_ok: 
    fclose(fp); 
    if ((id == 0) && (ch > 0))  { /* it's not a message folder */ 
*err = PM_MSG_BADFILE; 
return NULL; 
    } 

    *err = PM_MSG_OK; 
    return anchor; 


/* create a uniqe message folder name according to mailbox name. 
 * path:  target temprary directory for storing messages 
 * fldname: folder name 
 * fid: the uniqe folder identity 
 * id:  the message series number */ 

static char *glob_letter(char *buf, char *path, char *fldname, int fid, int id) 

    int   i; 
    char  *p; 

    p = fldname; 
    for (i = strlen(fldname); i >= 0; i--)  { 
if (fldname[i] == PATHSEP)  { 
    p = &fldname[i] + 1; 
    break; 

    } 
     
    if (path)  { 
sprintf(buf, "%s%c%s%03d_%04x", path, PATHSEP, p, fid, id); 
    } else { 
sprintf(buf, "%s%03d_%04x", p, fid, id); 
    } 
     
//    printf("glob: %s\n", buf); 
    return buf; 


/* duplicate the message body. 
 * The stream pointer shoud have been on the right position. 
 * This routine do some extra works: skip blank lines between message 
 * head and message body, and appand one blank line on the end of message 
 * body while there is not. 
 */ 

static char *mail_body(Mail *m, FILE *fin, FILE *fout, char *buf, int len) 

    int  bflag = 0; 
     
    /* skip leading blank lines */ 

    while (!feof(fin))  { 
if (ismailstart(buf))  break; 
if (!isblankline(buf)) break; 
fgets(buf, len, fin); 
    } 
     
    /* duplicate message body */ 
     
    while (!feof(fin))  { 
if (ismailstart(buf))  break; 

if (isblankline(buf))  bflag = 1; 
else  bflag = 0; 

m->msg->len += fprintf(fout, "%s", buf); 
fgets(buf, len, fin); 
m->msg->line++; 
    } 

    /* appand a blank line while there is not; for some MUA will mess up 
     * when the message body hit the head of next message */ 
     
    if (bflag == 0)  fprintf(fout, "\n"); 

    return buf; 


/* accomplish the message object and create its relatively  
 * temporary folder. Note that there is the last line it read in 'buf' 
 * when it returns. 
 */ 

static char *fill_mail_obj(Mail *m, FILE *fp, char *buf, int len) 

    FILE  *fout; 
    HLin  *hl; 
    char  *p; 

    if ((fout = fopen(m->msg->name, "w")) == NULL)  { 
     
/* when failed by creating temporary folder, it cleans 
 * the FromSps line from caller for avoiding dead loop */ 
     
buf[0] = 0; 
return NULL; 
    } 

    /* process the FromSps line. We just take care of date segment */ 
     
    for (p = buf + 4; isspace(*p); p++);  /* move to date segment */ 
    p = strchr(p, ' ');
    for (p++; isspace(*p); p++); 
    /* printf("date: %s\n", p);*/ 
    if ((m->rtime = strtimet(p)) < 0)  m->rtime = 0; 
    
    /* to cache the heads */ 
     
    head_clean(head); 
    head_to_cache(head, fp, buf, len); 

    /* fill up the mail object */ 

    if (!m->from)  { 
hl = head_check(head, HD_FROM); 
if (hl == NULL)  hl = head_check(head, HD_SENDER); 
if (hl == NULL)  hl = head_check(head, HD_RPLTO); 
if (hl == NULL)  m->from = dup_str("<>"); 
else  { 
    m->from = head_fetch_body(hl); 
    decode_head(m->from, 2); 

    } 
     
    if (!m->reply)  { 
hl = head_check(head, HD_RPLTO); 
if (hl == NULL)  m->reply = dup_str(m->from); 
else  { 
    m->reply = head_fetch_body(hl); 
    decode_head(m->reply, 2); 

    } 
     
    if (!m->to && (hl = head_check(head, HD_TO)) != NULL)  { 
m->to = head_fetch_body(hl); 
decode_head(m->to, 2); 
    } 
     
    if (!m->cc && (hl = head_check(head, HD_CC)) != NULL)  { 
m->cc = head_fetch_body(hl); 
    } 
     
    if (!m->bcc && (hl = head_check(head, HD_BCC)) != NULL)  { 
m->bcc = head_fetch_body(hl); 
    } 
     
    if (!m->subject && (hl = head_check(head, HD_SUBJECT)) != NULL)  { 
m->subject = head_fetch_body(hl); 
decode_head(m->subject, 2); 
compress_space(m->subject); 
    } 

    if (!m->c_type && (hl = head_check(head, HD_CTTYPE)) != NULL)  { 
m->c_type = head_fetch_body(hl); 
    } 

    if ((hl = head_check(head, HD_CTENCODE)) != NULL)  { 
for (p = hl->body; isspace(*p); p++); 
if (*p == '"') p++; 

if (!strncasecmp(p, "7bit", 4))  m->c_encode = CTE_7BIT; 
else if (!strncasecmp(p, "quoted-printable", 16))  m->c_encode = CTE_QP; 
else if (!strncasecmp(p, "base64", 6))  m->c_encode = CTE_BASE64; 
else if (!strncasecmp(p, "8bit", 4))  m->c_encode = CTE_8BIT; 
else if (!strncasecmp(p, "binary", 6))  m->c_encode = CTE_BINARY; 
    } 

    if (!m->rtime && (hl = head_check(head, HD_DATE)) != NULL)  { 
if ((m->rtime = strtimet(hl->body)) < 0)  m->rtime = 0; 
    } 

    if ((hl = head_check(head, HD_STATUS)) != NULL)  { 
if ((*hl->body == 'O') || (*hl->body == 'R'))  m->oldmail = 1; 
    } 

    if ((hl = head_check(head, HD_ACTION)) != NULL)  { 
m->behave = msg_behave_bind(hl->body); 
head_remove_all(head, HD_ACTION); 
    }

    head_dump(head, fout, 1); 
     
    /* set body offset */ 
     
    fprintf(fout, "\n");
    m->msg->boff = ftell(fout); 
     
    /* duplicate mail body */ 
     
    mail_body(m, fp, fout, buf, len); 
    fclose(fout); 

    /* record the last modification time of temporary folder */ 
     
    if ((m->msg->mtime = filedate(m->msg->name, &m->msg->msize)) < 0) 
m->msg->mtime = 0; 

//    printf("id:       %d\n", m->id); 
//    printf("letter:   %s\n", m->msg->name); 
//    printf("from:     %s\n", m->from); 
//    printf("cc:       %s\n", m->cc); 
//    printf("bcc:      %s\n", m->bcc); 
//    printf("To:       %s\n", m->to); 
//    printf("reply:    %s\n", m->reply); 
//    printf("subject:  %s\n", m->subject); 
//    printf("c_type:   %s\n", m->c_type); 
//    printf("date:     %s\n", ctime(&m->rtime)); 
//    printf("lines:    %d\n", m->msg->line); 
//    printf("bodyoff:  %ld\n", m->msg->boff); 
//    printf("length:   %d\n\n", m->msg->len); 


#ifdef DEBUG 
/*    printf("message %s loaded (%d bytes): %s\n",  
    m->msg->name, m->msg->line, m->from);*/ 
#endif 
     
    return buf; 


static int pine_start_cmp(char *buf) 

    char  *pinemark = "MAILER-DAEMON"; 

    return strncmp(buf + 5, pinemark, strlen(pinemark)); 



[/code:1:3e0cea3f47]

 蓝色键盘 回复于:2003-04-25 14:02:57
gmail.c 
[code:1:2e2f71b2d0] 
#ifdef HAVE_CONFIG_H 
#include "config.h" 
#endif 

#include  
#include  
#include  

#if HAVE_UNISTD_H 
  #include  
  #include  
#endif 

#if HAVE_SYS_IOCTL_H 
  #include  
#endif 

#include "defs.h" 
#include "gmail.h" 


static GMAIL *gmail; 
static struct gm_att  *attr; 

static GMAIL *gmail_create(char *s); 
static int  gmail_set_protocal(char *s); 
static Slnk *gmail_set_spam(char *mark); 

#ifdef DEBUG 
static void gmail_dump_att(); 
static void gmail_dump(GMAIL *gm); 
#endif 

static Slnk *slnk_alloc(); 
static Slnk *spam_link_append(Slnk *anch, int id); 
static int  sk_id(Spam *sc, char *p); 
static int  sk_size(Spam *sc, char *p); 
static int  sk_from(Spam *sc, char *p); 
static int  sk_subject(Spam *sc, char *p); 
static int  sk_action(Spam *sc, char *p); 


int  gmail_single(GMAIL *gm, Head *head) 

    int  rs = 0; 
     
    switch (gm->protl) { 
case GP_POP3: 
case GP_APOP: 
    rs = pop3_main(gm, head); 
    break; 
    } 
    return rs; 


int  gmail_main(GMAIL *gm, Head *head) 

    //gmail_dump_att();  
    while (gm)  { 
        //gmail_dump(gm); 
gmail_single(gm, head); 
gm = gm->next; 
    } 
    return OK; 


/* This function is used to create all necessary server objects for accessing 
 * these servers. The server objects should be chained and start with 'gmail'. 
 * Because there is a common structure gm_attr, it fills up this structure 
 * first, then creates echo server object according to the 'fetch' option in 
 * the configure file. All server objects will be chained at last with the  
 * order of first-appear-first-in. */ 

GMAIL *gmail_open() 

    GMAIL *gm, *gtmp; 
    struct winsize ws; 
    char  *p, *idx[3], buf[SVRBUF]; 
    int   i, rs; 

    /* if no default mailbox specified, we use 'mbox' in the current dir */ 
     
    if ((p = rc_check(RCKEY_MBOX)) == NULL)   
strcpy(buf, HOMEBOX); 
    else   
fullpath(p, buf); 

    /* There are three items which need extra space: cmd_auth, defbox and  
     * headmask. The plan is to combine the defbox and cmd_auth, then to  
     * append the headmask buffer at the tail of the combination. Therefore  
     * these is a pointer, named hdbuf, that points to the start position of  
     * the headmask buffer. */ 
     
    if (cmd_auth)   
rs = strlen(cmd_auth) + strlen(buf); 
    else   
rs = strlen(buf); 

    if ((p = rc_check(RCKEY_HEADMASK)) == NULL) 
rs += strlen(HMDEF); 
    else 
rs += strlen(p); 
     
    rs += sizeof(struct gm_att) + 5; 

    if ((attr = malloc(rs)) == NULL)   
return NULL; 
     
    memset(attr, 0, rs); 
     
    /* the extra space starts with 'buf' in the gm_att structure. we  
     * concatenate defbox and cmd_auth first and then split them */ 
     
    strcpy(attr->buf, buf); 
    if (cmd_auth)  { 
strcat(attr->buf, ":"); 
strcat(attr->buf, cmd_auth); 
    } 
     
    attr->hdbuf = attr->buf + strlen(attr->buf) + 1; 
    if (p == NULL) 
strcpy(attr->hdbuf, HMDEF); 
    else 
strcpy(attr->hdbuf, p); 
    ziptoken(attr->hdbuf, attr->hdmsk, HMMAX, ":"); 
     
    rs = fixtoken(attr->buf, idx, 3, ":"); 
    for (i = 0; i < rs; i++)  { 
if (!strcmp(idx[i], "*"))   
    idx[i] = NULL; 
else if (!strcmp(idx[i], "\\*"))   
    idx[i]++; 
    } 
    attr->defbox = idx[0]; 
    attr->user = idx[1]; 
    attr->pass = idx[2]; 

    attr->act = cmd_action; 
    attr->cp_set = cmd_cp_set; 
    attr->mbox = cmd_mbox; 

     
    if ((p = rc_check(RCKEY_TOPSLY)) != NULL)  { 
StrnCpy(buf, p, SVRBUF); 
ziptoken(buf, idx, 2, DELIMS); 
if (idx[0]) { 
    if (!strcmp(idx[0], "smart"))  
attr->tops = TOP_SMART; 
    else if (!strcmp(idx[0], "all"))  
attr->tops = TOP_ALL; 
    else if (!strcmp(idx[0], "brief")) 
        attr->tops = TOP_BRIEF; 

if (idx[1])   
    attr->topl = atonum(idx[1]); 
else   
    attr->topl = 0; 
    } 

    if ((p = rc_check(RCKEY_LDELAY)) != NULL)   
attr->delay = atoi(p); 

    if (ioctl(1, TIOCGWINSZ, (char *) &ws) >= 0)   
attr->cols = ws.ws_col; 
    else { 
attr->cols = atoi(getenv("COLUMNS")); 
if (attr->cols == 0)  attr->cols = 80; 
    } 
     
    spam_queue_open(); 

    /* now creates the chain of server objects according to the relative 
     * options in the configure file */ 
     
    for (p = rc_check(RCKEY_FETCH); p; p = rc_check_next())  { 
gm = gmail_create(p); 
if (gmail == NULL)   
    gmail = gm; 
else { 
    for (gtmp = gmail; gtmp->next; gtmp = gtmp->next); 
    gtmp->next = gm; 

    } 
     
    return gmail; 


/* This function is used to insert an extra server object into the server 
 * object chain. The argument, arg, comes from command line, usually by 
 * -h option. Although it has the same form as the 'fetch' option in the  
 * configure file, the 'arg' often appears just a server address.  
 * NOTE that, if it is given with the form of "@number", such as "@2",  
 * it does not mean to create and insert a server object but to choose a 
 * server object that has been created already in the chain with the series 
 * number of 'number', in this case it's 2.  */ 
  
GMAIL  *gmail_cmdarg(char *arg) 

    GMAIL *gm; 
    int   i, rs; 

    if (*arg == '@')  { 
rs = atoi(arg + 1); 
for (i = 1, gm = gmail; gm; i++, gm = gm->next)  { 
    if (i == rs)  
return gm; 

    } else {
gm = gmail_create(arg); 
if (gm != NULL)  { 
    gm->next = gmail; 
    gmail = gm; 

    } 
     
    return gm; 

  
void gmail_close() 

    GMAIL *gm, *tmp; 

    for (gm = gmail; gm; )  { 
     
free(gm->time_stamp); 
free(gm->mlist); 

if (gm->socket)   
    close(gm->socket); 
        if (gm->fp)   
    fclose(gm->fp); 

tmp = gm; 
gm = gm->next; 
free(tmp); 
    } 
    spam_queue_free(); 
     
    if (attr)   
free(attr); 
     
    attr = NULL; 
    gmail = NULL; 



void gmail_host_list() 

    GMAIL *gm; 
    char  buf[SVRBUF]; 
    int   i; 

    conPrintf("Post offices list:\n"); 
     
    for (i = 1, gm = gmail; gm; gm = gm->next, i++)  { 
ssprintf(buf, SVRBUF, "%4d %-25s %-25s %s:%s\n",  
i, gm->host, gm->mbox, gm->lid, gm->pass); 
conPrintf(buf); 
    } 
    conPrintf("\n"); 


int gmail_set_action(char *s) 

    int  rs = 0; 
     
    switch (*s)  { 
    case 'c':  
break; 
       
    case 't': /* for TOP */  
    case 'l': 
rs |= GMAIL_LIST; 
break; 

    case 'd': 
rs |= GMAIL_FETCH | GMAIL_DELE;  
break; 

    case 'f': 
rs |= GMAIL_FETCH; 
break; 

    case 'r': 
rs |= GMAIL_DELE;  
break; 
    } 
    return rs; 


/* host.name:protocol:operation:spam:mailbox:id:passwd */ 

static GMAIL *gmail_create(char *s) 

    GMAIL *gm; 
    char  *idx[16]; 
    int   i, rs; 

    if (s == NULL)   
return NULL; 
     
    /* becase the mailbox item is expanding to absolute path, I have to 
     * increase another space about 256 bytes for it */ 
     
    rs = strlen(s) + sizeof(GMAIL) + PATHMAX + 2; 
    if ((gm = malloc(rs)) == NULL)   
return NULL; 
    memset(gm, 0, rs); 
     
    gm->attr = attr; 
    gm->mbox = gm->buf; 
    strcpy(gm->buf + PATHMAX + 1, s); 
     
    rs = fixtoken(gm->buf + PATHMAX + 1, idx, 16, ":"); 
    for (i = 0; i < rs; i++)  { 
if (!strcmp(idx[i], "*"))   
    idx[i] = NULL; 
else if (!strcmp(idx[i], "\\*"))   
    idx[i]++; 
    } 
     
    if (cmd_host && *cmd_host != '@' && !isblankline(cmd_host)) 
gm->host = cmd_host; 
    else if (idx[0] && !isblankline(idx[0]))   
gm->host = idx[0]; 
    else  { 
free(gm); 
return NULL; 
    } 
     
    gm->host = idx[0]; 
     
    /* specified the protocal to access server, POP3 is default */ 
     
    if (idx[1])  
gm->protl = gmail_set_protocal(idx[1]); 
    if (gm->protl == 0)   
gm->protl = GP_POP3; 
     
    /* command line specified action could override the predefined one */ 
     
    if (idx[2])  
gm->act   = gmail_set_action(idx[2]); 
    if (attr->act != ID_NULL)   
gm->act = attr->act; 
     
    if (idx[3])  
gm->slnk  = gmail_set_spam(idx[3]); 
    gm->topspam = spam_need_top(gm->slnk); 
     
    /* mailbox: command line specified > predefined > default */ 
     
    if (attr->mbox)   
gm->mbox = attr->mbox; /* should be expanded */ 
    else if (idx[4] && !isblankline(idx[4]))   
fullpath(idx[4], gm->mbox); 
    else  
gm->mbox = attr->defbox; 
     
    if (attr->user)   
gm->lid = attr->user; 
    else   
gm->lid  = idx[5]; 

    if (attr->pass)   
gm->pass = attr->pass; 
    else   
gm->pass = idx[6]; 
     
    return gm; 


static int gmail_set_protocal(char *s) 

    if (!strcasecmp(s, "pop3"))        
return GP_POP3; 
    else if (!strcasecmp(s, "apop"))   
return GP_APOP; 
    return 0; 


static Slnk *gmail_set_spam(char *mark) 

    Slnk  *anch = NULL; 
    char  buf[128], *idx[32]; /* this buffer might be overflow attacked */ 
    int   i, id; 

    if ((*mark == 'y') || (*mark == 'Y'))  { 
anch = spam_link_append(anch, 0); 
    } else if ((*mark != 'n') && (*mark != 'N'))  { 
StrnCpy(buf, mark, sizeof(buf)); 
ziptoken(buf, idx, 32, ","); 
for (i = 0; idx[i]; i++)  { 
    id = atoi(idx[i]); 
    anch = spam_link_append(anch, id); 

    } 
    return anch; 


/********************** process spam routine ********************/ 

static Spam  *spam; 

static Slnk  slnk[SLPOOL]; 
static int   slidx = 0; 


static Slnk  *slnk_alloc() 

    if (slidx >= SLPOOL)  return NULL; 
    slidx++; 
    return &slnk[slidx - 1]; 


/* 
static char *strcasestr(const char *haystack, const char *needle) 

    char  *p; 
    int   nlen; 

    if (!needle || !haystack)  return (char*) haystack; 

    nlen = strlen(needle); 
    for (p = (char*) haystack; *p; p++)  { 
        if (!strncasecmp(p, (char *) needle, nlen))  return p; 
    } 
    return NULL; 

*/ 

static Slnk *spam_link_append(Slnk *anch, int id) 

    Spam  *sc; 
    Slnk  *sl; 

    for (sc = spam; sc; sc = sc->next)  { 
if (sc->id == id)  { 
    if ((sl = slnk_alloc()) == NULL)  break; 
    sl->sc = sc; 
    sl->next = anch; 
    anch = sl; 

    } 
    return anch; 


/***************************************************************** 
 * spam_check_xxxx()  and spam_regex_xxxx() 
 * return: 
 * 0: nothing matched;  
 * 1: matched something 
 **/ 

static char *allfrom[] = { "from", "reply", "sender", NULL }; 

/* 
static int spam_check_from(Head *head, char *from) 

    struct head_chain  *hc; 
    HLin   *hl; 
    int    i, rs; 
     
    for (i = rs = 0; allfrom[i]; i++)  { 
     
if ((hl = head_check(head, allfrom[i])) != NULL)  { 
    if (strcasestr(hl->body, from))  rs++; 
    for (hc = hl->hc; !rs && hc; hc = hc->next)  { 
if (strcasestr(hc->str, from))  rs++; 
    } 


if (rs)  break; 
    } 
    return rs; 


static int spam_check_subject(Head *head, char *subject) 

    struct head_chain  *hc; 
    HLin   *hl; 
    int    rs = 0; 
     
    if ((hl = head_check(head, "subject")) != NULL)  { 
if (strcasestr(hl->body, subject))  rs++; 
for (hc = hl->hc; !rs && hc; hc = hc->next)  { 
    if (strcasestr(hc->str, subject))  rs++; 

    } 
    return rs; 

*/ 


static int spam_regex_from(Head *head, regex_t *from) 

    regmatch_t  pmatch[1]; 
    struct head_chain  *hc; 
    HLin   *hl; 
    int    i, rs; 
     
    for (i = rs = 0; allfrom[i]; i++)  { 
     
if ((hl = head_check(head, allfrom[i])) != NULL)  { 
    if (!regexec(from, hl->body, 1, pmatch, 0))  rs++; 
    for (hc = hl->hc; !rs && hc; hc = hc->next)  { 
if (!regexec(from, hc->str, 1, pmatch, 0))  rs++; 
    } 


if (rs)  break; 
    } 
    return rs; 


static int spam_regex_subject(Head *head, regex_t *subject) 

    regmatch_t  pmatch[1]; 
    struct head_chain  *hc; 
    HLin   *hl; 
    int    rs = 0; 
     
    if ((hl = head_check(head, "subject")) != NULL)  { 
if (!regexec(subject, hl->body, 1, pmatch, 0))  rs++; 
for (hc = hl->hc; !rs && hc; hc = hc->next)  { 
    if (!regexec(subject, hc->str, 1, pmatch, 0))  rs++; 

    } 
    return rs; 



/* 1 spam message, 0 good message */ 

static int  spam_cmp(Spam *sc, Head *head, int msize) 

    if (!sc || !head)  return 0; 
     
    if (sc->quota && (msize < sc->quota))  goto trigr; 

    if (sc->from_reg)  { 
if (spam_regex_from(head, sc->from_reg) == 0)  goto trigr; 
    } 
    if (sc->sub_reg)  { 
if (spam_regex_subject(head, sc->sub_reg) == 0)  goto trigr; 
    } 

    /* if acknowleged all tests ... */ 

    if (sc->logic == 0)  return 1; 
    else return 0; 

trigr: /* any one unmatch */ 
    return sc->logic; 


Spam *spam_match_chain(Slnk *sl, Head *head, int msize) 

    while (sl)  { 
if (spam_cmp(sl->sc, head, msize))  return sl->sc; 
sl = sl->next; 
    } 
    return NULL; 


/* this funtion is used to check spam mails by their size only */ 

Spam *spam_match_size(Slnk *sl, int size) 

    Spam  *sc; 
     
    while (sl)  { 
sc = sl->sc; 
if (!sc->quota || sc->from_reg || sc->sub_reg)  continue; 

if (size > sc->quota) { 
    if (sc->logic == 0) 
return sc; 
} else { 
    if (sc->logic != 0) 
return sc; 
}  

sl = sl->next; 
    } 
    return NULL; 
}

int  spam_need_top(Slnk *sl) 

    int  rs = 0; 

    while (sl)  { 
if (sl->sc->from_reg || sl->sc->sub_reg)  rs++; 
sl = sl->next; 
    } 
    return rs; 

     

/**********************************************************************/ 

static int sk_id(Spam *sc, char *p) 

    sc->id = atoi(p); 
    return 0; /* this is identity, not an entry. so count free */ 


static int sk_size(Spam *sc, char *p) 

    sc->quota = atonum(p); 
    return 1; 


static int sk_from(Spam *sc, char *p) 

    if (isblankline(p))  return 0; 
    sc->from = dup_str(p); 
     
    sc->from_reg = &sc->preg[sc->ireg]; 
    if (regcomp(sc->from_reg, p, REG_EXTENDED | REG_ICASE))  { 
dbgPrintf("sk_from: cannot compile filter pattern.\n"); 
sc->from_reg = NULL; 
    } else sc->ireg++; 

    return 1; 


static int sk_subject(Spam *sc, char *p) 

    if (isblankline(p))  return 0; 
    sc->subject = dup_str(p); 
     
    sc->sub_reg = &sc->preg[sc->ireg]; 
    if (regcomp(sc->sub_reg, p, REG_EXTENDED | REG_ICASE))  { 
dbgPrintf("sk_subject: cannot compile filter pattern.\n"); 
sc->sub_reg = NULL; 
    } else sc->ireg++; 

    return 1; 


static int sk_action(Spam *sc, char *p) 

    sc->logic = 0; 
    if (!strcasecmp(p, SA_YES_DELE))       
sc->action = SPAM_DELE; 
    else if (!strcasecmp(p, SA_YES_KEEP))  
sc->action = SPAM_KEEP; 
    else if (!strcasecmp(p, SA_YES_ASK))   
sc->action = SPAM_ASK; 
    else if (!strcasecmp(p, SA_NO_DELE))   
sc->action = SPAM_DELE, sc->logic = 1; 
    else if (!strcasecmp(p, SA_NO_KEEP))   
sc->action = SPAM_KEEP, sc->logic = 1; 
    else if (!strcasecmp(p, SA_NO_ASK))    
sc->action = SPAM_ASK, sc->logic = 1; 
    return 0; /* action is count free either */ 


static struct spam_func { 

char *key; 
int (*func)(Spam *sc, char *p); /* successed: 1, fail: 0 */ 

} sf[] = { 
{ SK_ID, sk_id }, 
{ SK_SIZE, sk_size }, 
{ SK_FROM, sk_from }, 
{ SK_SUBJECT, sk_subject }, 
{ SK_ACTION,  sk_action }, 
{ NULL, NULL } 
}; 


Spam *spam_queue_open() 

    Spam  *sc; 
    char  *p, *s, *tmp = NULL, *idx[16]; 
    int   rs, i, k, cnt; 

#ifdef DEBUG 
    if (spam)  { 
printf("spam queue has existed.\n"); 
return NULL; 
    } 
#endif 

    for (p = rc_check(RCKEY_SPAM); p; p = rc_check_next())  { 

p += strlen(p) + 1; /* move to extension part */ 
//puts(p); 

tmp = dup_str(p); 
if (tmp == NULL)  break; 

rs = ziptoken(tmp, idx, 16, "#");  

if ((sc = malloc(sizeof(Spam))) == NULL)  { 
    free(tmp); 
    break; 

memset(sc, 0, sizeof(Spam)); 

for (cnt = 0, i = 1; i < rs - 1; i++)  { 
    for (k = 0; sf[k].key; k++)  { 
if (!strncasecmp(idx[i], sf[k].key, strlen(sf[k].key))) { 
    s = skip_space(idx[i] + strlen(sf[k].key)); 
    cnt += sf[k].func(sc, s); 
    break; 

    } 


if (cnt == 0)  free(sc); 
else if (spam == NULL)  spam = sc; 
else { 
    sc->next = spam; 
    spam = sc; 

free(tmp); 
    } 
    return spam; 



void spam_queue_free() 

    Spam  *tmp, *sc; 

    sc = spam; 
    while (sc)  { 
tmp = sc; 
sc = sc->next; 

if (tmp->from_reg) regfree(tmp->from_reg); 
if (tmp->sub_reg)  regfree(tmp->sub_reg); 

free(tmp->from); 
free(tmp->subject); 
free(tmp); 
    } 



#ifdef DEBUG 

static void gmail_dump_att() 

    int  i = 0; 
     
    printf("Top lines:   %d\n", attr->topl); 
    printf("Top style:   %d\n", attr->tops); 
//    printf("quota:       %d\n", attr->quota); 
    printf("login delay: %d\n", attr->delay); 
    printf("screen cols: %d\n", attr->cols); 
    printf("deft action: %d\n", attr->act); 
    printf("set mbox:    %s\n", attr->mbox); 
    printf("deft mbox:   %s\n", attr->defbox); 
    printf("set user:    %s\n", attr->user); 
    printf("set pass:    %s\n", attr->pass); 
    printf("cp_set: "); 
    for (i = 0; attr->cp_set && attr->cp_set[i]; i++) 
printf("%d,", attr->cp_set[i]); 
    printf("\n"); 
    printf("headmask: "); 
    for (i = 0; attr->hdmsk[i]; i++) 
printf("%s ", attr->hdmsk[i]); 
    printf("\n\n"); 


static void gmail_dump(GMAIL *gm) 

    Slnk  *sl; 

    printf("GMAIL object %p\n", gm); 
    printf("Remote host: %s\n", gm->host); 
    printf("login id:    %s\n", gm->lid); 
    printf("login pass:  %s\n", gm->pass); 
    printf("set mbox:    %s\n", gm->mbox); 
    printf("set action:  %d\n", gm->act); 
    printf("protocol:    %d\n", gm->protl); 
    printf("topspam:     %d\n", gm->topspam); 
    for (sl = gm->slnk; sl; sl = sl->next)  { 
printf("spam id:     %d\n", sl->sc->id); 
printf("  quota:     %d\n", sl->sc->quota); 
printf("  from:      %s\n", sl->sc->from); 
printf("  subject:   %s\n", sl->sc->subject); 
printf("  logic:     %d\n", sl->sc->logic); 
printf("  action:    %d\n", sl->sc->action); 
    } 
    printf("\n"); 


int  spam_test(char *file) 

    GMAIL *gm; 
    Head  *head; 
    FILE  *fp; 
    char  buf[SVRBUF]; 
    Spam  *sp; 

    gmail_dump_att(); 
    for (gm = gmail; gm; gm = gm->next)  gmail_dump(gm); 
     
    file = line_refine(file, '#'); 
    fp = fopen(file, "r"); 
    if (fp == NULL)  return 1; 

    head = head_register(HDPAGE, HDIDX); 
     
    while (!feof(fp))  { 

head_clean(head); 
if (head_of_file(head, fp, buf, SVRBUF) == -1)  break; 

printf("-> %s\n", head->fmsp); 
for (gm = gmail; gm; gm = gm->next)  { 
    sp = spam_match_chain(gm->slnk, head, 0); 
    if (sp == NULL)  printf("test OK!\n"); 
    else { 
printf("triggered! (%s)(%s)(%d)\n",  
sp->from, sp->subject, sp->quota); 
    } 

    }
     
    head_destruct(head); 
    fclose(fp); 
    return 0; 


#endif     
[/code:1:2e2f71b2d0] 
main.c 

[code:1:2e2f71b2d0] 


#ifdef HAVE_CONFIG_H 
#include "config.h" 
#endif 

#include  
#include  
#include  
#include  
#include  

#if HAVE_UNISTD_H 
  #include  
  #include  
#endif 

#if HAVE_GETOPT_H 
  #include  
#else 
  #include "getopt.h" 
#endif 

#if HAVE_FCNTL_H 
  #include  
#endif 

#include "defs.h" 
#include "gmail.h" 


/* these variables are set against command line arguments */ 

char  *cmd_auth = NULL; /* authorization pair */ 
char  *cmd_host = NULL; 
char  *cmd_mbox = NULL; 
int   *cmd_cp_set = NULL; /* download set */ 
int   cmd_action = 0; 

static char  *cmd_subject = NULL; 
static char  *cmd_cc = NULL; 
static char  *cmd_bcc = NULL; /* blind carbon copy */ 

/* these variables are set against option file */ 

int timeout = 90; 
int verbose = 0; 

static int defbeh = ACT_DEFT; /* index use default behave */ 


static int  parse_command_line(int argc, char **argv, char *abuf, int alen); 
static int  *set_download_set(char *s); 
static int  set_default(char *s, int *tasks, int tlen); 
static int  open_quota_log(char *s); 
static void signal_quit(int sig); 
static void append_template(); 
static void usage(int flag); 


static char *rcpath[] = { 
NULL, 
"/etc/pmailrc", 
"/usr/lib/pmailrc", 
"/usr/local/etc/pmailrc", 
"/usr/local/lib/pmailrc", 
NULL 
}; 

int main(int argc, char **argv) 

    Folder *fo = NULL; 
    SMTP   *sm; 
    GMAIL  *gm; 
    Head   *head; 
    int    i, rs, tasks[TASK_NR]; 
    char   *abuf, *p; 
     
    umask(077); 
     
    signal(SIGHUP, signal_quit); 
    signal(SIGINT, signal_quit); 
    signal(SIGQUIT, signal_quit); 
    signal(SIGTERM, signal_quit); 
    signal(SIGPIPE, signal_quit); 
    signal(SIGALRM, signal_quit); 
     
    //progress_test(); 
    progress_init(0); 
     
    /* create a buffer for gathering command line arguments */ 
     
    abuf = malloc(BLKBUF); 
    if (abuf == NULL)   
return -1; 
     
    /* get the home directory, then open default RC file. */ 
     
    sprintf(abuf, "%s/.pmailrc", get_home()); 
    rcpath[0] = abuf; 

    /* if DEBUG is on, Pmail should search in the current directory first 
     * for the configuration file. It makes debugging life easier since we can 
     * test options in working directory. 
     * A distribution version should disable it. */ 
     
    for (i = 0; rcpath[i] != NULL; i++)  { 
if (rc_open(rcpath[i]) >= 0)   
    break; 
    } 
     
    if ((p = rc_check(RCKEY_TIMEOUT)) != NULL)   
timeout = atoi(p); 
    if ((p = rc_check(RCKEY_VERBOSE)) != NULL)   
verbose = 1; 
    if ((p = rc_check(RCKEY_SMBEHV)) != NULL) 
defbeh  = msg_behave_bind(p); 
    if ((p = rc_check(RCKEY_DEBUG)) != NULL) 
open_quota_log(p); 
     
    /* now parsing command line arguments. 
     * It is supposed that you can list a series of tasks in the config file,  
     * in the 'default' option. You can also overwhelm this task queue by an 
     * alternative instruction in the command line. In that case, the task 
     * queue is fixed to one element, the instruction. */ 
     
    rs = parse_command_line(argc, argv, abuf, BLKBUF); 
    if (rs != ID_NULL)  { 
tasks[0] = rs, rs = 1; 
    } else if ((p = rc_check(RCKEY_DEFAULT)) != NULL)  { 
rs = set_default(p, tasks, TASK_NR); 
    } else rs = 0; 
     
    /* process the task queue */ 
     
    for (i = 0; i < rs; i++)  { 
/* printf("Task %d/%d: %d\n", i, rs, tasks[i]); */ 
     
switch(tasks[i])  { 
case ID_HELP: 
    usage(ID_HELP); 
    break; 

case ID_VERSION: 
    usage(ID_VERSION); 
    break; 

case ID_TEMPLATE: 
    append_template(); 
    break; 

case ID_GMAIL: 
    //progress_init(0); 
    head = head_register(HDPAGE, HDIDX); 
    if (head == NULL) 
break; 
    gm = gmail_open(); 
     
    if (cmd_host)  { 
gm = gmail_cmdarg(cmd_host); 
if (gm)   
    gmail_single(gm, head); 
    } else   
gmail_main(gm, head); 

    gmail_close(); 
    head_destruct(head); 
    break; 

case ID_SMTP: 
    if (*abuf)  { 
fo = folder_open(abuf, defbeh); 
    } 
    if (cmd_mbox)  { 
fo = folder_open(cmd_mbox, defbeh); 
    } 
    if (fo == NULL)  { 
p = rc_check(RCKEY_OUTBOX); 
if (p != NULL)  { 
    fo = folder_open(p, defbeh); 

    } 
     
    rs = folder_number(); 
    if (rs < 0)  { 
conPrintf("Warning: No postpone message folder specified.\n"); 
    } else if (rs == 0)  { 
conPrintf("No message is ready for sending.\n"); 
    } else { 
conPrintf("%d %s ready for sending.\n",  
    rs, rs < 2 ? "message is" : "messages are"); 

sm = smtp_host_chain(cmd_host, cmd_auth); 
smtp_main(fo, sm); 
smtp_host_clean(); 
    } 
     
    folder_close(rc_check(RCKEY_BACKUP), defbeh); 
    break; 

case ID_STREAM: 
    fo = folder_online(abuf, cmd_cc, cmd_bcc, cmd_subject, defbeh); 
    if (fo == NULL)   
break; 
    sm = smtp_host_chain(cmd_host, cmd_auth); 
    smtp_main(fo, sm); 
    smtp_host_clean(); 
    folder_close_online(rc_check(RCKEY_BACKUP), defbeh); 
    break; 

case ID_HOSTLIST: 
    gmail_open(); 
    gmail_host_list(); 
    gmail_close(); 
     
    sm = smtp_host_chain(cmd_host, cmd_auth); 
    smtp_host_list(); 
    smtp_host_clean(); 
    break; 

case ID_DUMPTMP: 
    if (*abuf)  { 
fo = folder_open(abuf, defbeh); 
    }  
    if (cmd_mbox)  { 
fo = folder_open(cmd_mbox, defbeh); 
    } 
    if (fo == NULL)  { 
p = rc_check(RCKEY_OUTBOX); 
if (p != NULL)  { 
    fo = folder_open(p, defbeh); 

    } 
     
    folder_dump(fo); 
    /* getchar(); */ 

    folder_close(NULL, ACT_HOLD); 
    break; 

case ID_DUMPINFO: 
    if (*abuf)  { 
fo = folder_open(abuf, defbeh); 
    } 
    if (cmd_mbox)  { 
fo = folder_open(cmd_mbox, defbeh); 
    } 
    if (fo == NULL)  { 
p = rc_check(RCKEY_OUTBOX); 
if (p != NULL)  { 
    fo = folder_open(p, defbeh); 

    } 
     
    folder_list(fo); 

    folder_close(NULL, ACT_HOLD); 
    break; 

#ifdef DEBUG 
case ID_SPAMTEST: 
    gm = gmail_open(); 
    if (cmd_host)   
gm = gmail_cmdarg(cmd_host); 

    spam_test(abuf); 
    gmail_close(); 
    break; 
#endif 
     

    } 
     
    free(abuf); 
    ReleaseResource(); 
    return 0; 



static int parse_command_line(int argc, char **argv, char *abuf, int alen) 

    int   oidx, c, rs; 
    char  *sopt="pPvotf:h:d:s:c:b:l:e:u:"; 
    struct option lopt[] = { 
     { "verbose", 0, NULL, 'v' }, 
     { "behave", 1, NULL, 'e' }, 
     { "host", 1, NULL, 'h' }, 
     { "download", 1, NULL, 'd' }, 
     { "list", 1, NULL, 'l' }, 
{ "auth", 1, NULL, 'u' }, 
     { "template", 0, NULL, 't' }, 
     { "help", 0, NULL, ID_HELP }, 
     { "version", 0, NULL, ID_VERSION }, 
{ "spamtest", 0, NULL, ID_SPAMTEST }, 
{ "server", 0, NULL, ID_HOSTLIST }, 
{ "progress", 1, NULL, ID_PROGRESS }, 
     { 0, 0, 0, 0 } 
    }; 

    rs = ID_NULL; 
    while (1)  { 
     c = getopt_long(argc, argv, sopt, lopt, &oidx); 
     if (c == -1)  break; 
     switch (c)  { 
         case ID_HELP: 
     return ID_HELP; 
    
         case ID_VERSION: 
     return ID_VERSION; 

    case ID_HOSTLIST: 
rs = ID_HOSTLIST; 
break; 

#ifdef DEBUG 
    case ID_SPAMTEST: 
rs = ID_SPAMTEST; 
break; 
#endif 

    case ID_PROGRESS: 
progress_init(atoi(optarg)); 
break; 
    
         case 'v': 
     verbose = YES; 
     break; 

    case 'a': 
defbeh = msg_behave_bind(optarg); 
break; 
    
         case 't': 
     rs = ID_TEMPLATE; 
break; 
    
    case 'P': 
rs = ID_DUMPTMP; 
break; 

    case 'p': 
rs = ID_DUMPINFO; 
break; 

         case 'o': 
     rs = ID_SMTP; 
     break; 
    
         case 'h': 
if (cmd_host == NULL)  cmd_host = dup_str(optarg); 
     break; 
    
         case 'f': 
if (cmd_mbox == NULL)  cmd_mbox = dup_str(optarg); 
     break; 
    
         case 's': 
if (cmd_subject == NULL)  cmd_subject = dup_str(optarg); 
     break; 
    
         case 'c': 
if (cmd_cc == NULL)  cmd_cc = dup_str(optarg); 
     break; 
    
         case 'b': 
if (cmd_bcc == NULL)  cmd_bcc = dup_str(optarg); 
     break; 
    
    case 'u': 
if (cmd_auth == NULL)  cmd_auth = dup_str(optarg); 
break; 

         case 'd': 
rs = ID_GMAIL; 
cmd_action = gmail_set_action(optarg); 
break; 
    
         case 'l': 
     cmd_cp_set = set_download_set(optarg); 
     break; 
    
         default: 
     return ID_HELP; 
     } 
    }
  
    *abuf = '\0'; 
    if (optind < argc)  { 
for (c = optind; c < argc; c++)  { 
    if (strlen(abuf) + strlen(argv[c]) + 1 < alen)  { 
strcat(abuf, argv[c]); 
strcat(abuf, " "); 
    } 

if (rs == ID_NULL)  rs = ID_STREAM; 
    } 
    return rs;     



/* store and adjust the mail download/handle set of which starts with 1. e.g. 
   sour:          1,2,4-9,10,12         --> 
   download set:  [1,1], [2,2], [4,9], [10,10], [12,12], [-1,-1]    (int array) 
*/ 
static int *set_download_set(char *s) 

    char *idx[PARMAX], *p; 
    int  *dl, max, i; 
     
    /* first it acknowleges the number of ',' */ 
     
    for (max = 0, p = s; (p = strchr(p, ',')) != NULL;  p++, max++); 
     
    max = ((max + 2) * sizeof(int)) << 1; 
    if ((dl = malloc(max)) == NULL)  return NULL; 
     
    max = ziptoken(s, idx, PARMAX, ","); 
    for (i = 0; i < max; i++)  { 
     dl[i*2] = atoi(idx[i]); 
     if ((p = strchr(idx[i], '-')) == NULL)  dl[i*2+1] = dl[i*2]; 
else dl[i*2+1] = atoi(p+1); 
    } 
    dl[i*2] = dl[i*2+1] = EOF; /* -1, end flag */ 
    return dl; 


static int set_default(char *s, int *tasks, int tlen) 

    char *idx[TASK_NR]; 
    int i, num; 
     
    /* this function read a option, 'default xxx,xxx,...', from  
       RC file. If there were another action specified by command 
       line arguments, the 'default' option should be ignored. */ 

    num = ziptoken(s, idx, TASK_NR, DELIMS); 
     
    for (i = 0; (i < num) && (i < tlen); i++)  { 

     if (!strcasecmp(idx[i], "get"))           tasks[i] = ID_GMAIL; 
     else if (!strcasecmp(idx[i], "sent"))     tasks[i] = ID_SMTP; 
     else if (!strcasecmp(idx[i], "template")) tasks[i] = ID_TEMPLATE; 
else if (!strcasecmp(idx[i], "dump"))     tasks[i] = ID_DUMPTMP; 
else if (!strcasecmp(idx[i], "info"))     tasks[i] = ID_DUMPINFO; 
     else if (!strcasecmp(idx[i], "version"))  tasks[i] = ID_VERSION; 
     else if (!strcasecmp(idx[i], "help"))     tasks[i] = ID_HELP; 
else i--; 
     
/* printf("default: %s = %d\n", idx[i], tasks[i]); */ 
    } 
    return i; 


static int  open_quota_log(char *s) 

    char *idx[2]; 
    char buf[SVRBUF]; 
    int  rs, quota; 

    quota = 0; 
    rs = ziptoken(s, idx, 2, DELIMS); 
    if (idx[1] && *idx[1])  { 
        quota = atoi(idx[1]); 
        switch (idx[1][strlen(idx[1]) - 1])  { 
        case 'k': 
        case 'K': 
            quota *= 1024; 
            break; 

        case 'm': 
        case 'M': 
            quota *= 1024 * 1024; 
            break; 
        } 
    } 
    fullpath(idx[0], buf); 
    //printf("open log: %s %d\n", buf, quota); 
    return log_open(buf, quota); 



static void signal_quit(int sig) 

    ReleaseResource(); 
    switch(sig)  { 
     case SIGHUP: 
         printf("\nEncountered signal SIGHUP (%d)\n", sig); 
         break; 
    
     case SIGINT: 
         printf("\nEncountered signal SIGINT (%d)\n", sig); 
         break; 
    
     case SIGQUIT: 
         printf("\nEncountered signal SIGQUIT (%d)\n", sig); 
         break; 
    
     case SIGTERM: 
         printf("\nEncountered signal SIGTERM (%d)\n", sig); 
         break; 
    
     case SIGALRM: 
         printf("\nEncountered timeout signal (%d)\n", sig); 
         break; 
    
     case SIGPIPE: 
         printf("\nEncountered signal SIGPIPE (%d)\n", sig); 
         break; 
    } 
    exit(sig); 



static void append_template() 

    FILE  *fp = NULL; 
    char  obox[SVRBUF], *tmp; 
     
    if ((tmp = cmd_mbox) == NULL)  { 
tmp = rc_check(RCKEY_OUTBOX); 
    } 
    if (tmp != NULL)  { 
fullpath(tmp, obox); 
fp = fopen(obox, "a"); 
    } 
    if (fp == NULL)  fp = stdout; 

    tmp = rc_check(RCKEY_REPLY); 
    if (tmp == NULL)  { 
     fprintf(fp, "\nFrom - %s\n", timenow()); 
     fprintf(fp, "From:\n"); 
    } else { 
     fprintf(fp, "\nFrom %s %s\n", email_pure(tmp), timenow()); 
     fprintf(fp, "From: %s\n", tmp); 
    } 
    fprintf(fp, "To: \n"); 
    fprintf(fp, "X-behave: pipe,sign,exhd\n"); 
    fprintf(fp, "Subject: \n\n"); 
    if (fp != stdout)  fclose(fp); 
    printf("Simple template is appended into %s.\n", 
     obox ? obox : "stdout"); 

     


/**************************************************************/ 
    
static void usage(int flag) 

    char *ver="pmail %s, by Xuming \n"; 

    char *msg = "\ 
Usage:\n\ 
 pmail [-v] [-e smtp-beh] [-u auth-pair] [-f mailbox] [-h host] [-l ...]\n\ 
\n\ 
 pmail -dd [...]  download mails and remove them in the server\n\ 
 pmail -df [...]  fetch mails and reserve them in the server\n\ 
 pmail -dc [...]  check mailbox status in the server\n\ 
 pmail -dl [...]  list message heads or other informations\n\ 
 pmail -dr [...]  remove mails in the server end\n\ 
                  You can instruct more than one POP3 server in [...]\n\ 
\n\ 
 pmail -o [...]   send mails stored in the postpone folder\n\ 
 pmail -p [...]   preview the&npmsages'''' head in the postpone folder\n\ 
 pmail -P [...]   dump the postpone folder to screen\n\ 
                  You can instruct more than one postpone folder in [...]\n\ 
\n\ 
 pmail [-s subject] [-c cc-addr] [-b bcc-addr] to-addr [...]\n\ 
                  You can instruct more than one receiver in [...]\n\ 
\n\ 
 pmail -t         appends a template to the postpone mailbox (obsolete)\n\ 
\n\ 
"; 
    
    if (flag == ID_VERSION)  printf(ver, VERSION); else  printf(msg); 

     
/**********************************************************/ 


/* this procedure used to release all of the source which pmail ever 
   occured. It also is looked on the last defend line as signal  
   encountered or other urgent affair occured */ 

void ReleaseResource() 

    log_close(); 
    rc_close(); 
    folder_close(NULL, ACT_HOLD); 
   // clear_gmail(); 
     
    xfree(cmd_host); 
    xfree(cmd_mbox); 
    xfree(cmd_subject); 
    xfree(cmd_cc); 
    xfree(cmd_bcc); 
    xfree(cmd_cp_set); 

[/code:1:2e2f71b2d0]

 蓝色键盘 回复于:2003-04-25 14:18:58
folder.c 
[code:1:0568ea60bc] 

  
#ifdef HAVE_CONFIG_H 
#include "config.h" 
#endif 

#include  
#include  
#include  
#include  

#if HAVE_UNISTD_H 
  #include  
  #include  
#endif 

#if HAVE_SYS_IOCTL_H 
  #include  
#endif 

#include "defs.h" 


static Folder  *rootfld; 
static char    gdir[] = PMTMP; 
static int     fid = 1; 
static char    *signature = NULL; 


static void folder_insert(Folder *tar) 

    Folder *fo; 
     
    if (rootfld == NULL)  { 
rootfld = tar; 
rootfld->next = NULL; 
rootfld->prev = NULL; 
    } else { 
for (fo = rootfld; fo->next; fo = fo->next); 
fo->next = tar; 
tar->next = NULL; 
tar->prev = fo; 
    } 


static Folder *check_loaded(char *fname) 

    Folder *fo; 

    for (fo = rootfld; fo; fo = fo->next)  { 
        if (!strcmp(fo->name, fname))  break; 
    } 
    return fo; 



static void load_signature(char *s) 

    FILE *fsig; 
    char buf[SVRBUF], *sig; 
    int len; 
     
    if (signature)  return; 

    fullpath(s, buf); 
    if ((fsig = fopen(buf, "r")) == NULL)  { 
logPrintf(LOG_WARN,  
"can not open signature file. [%s]\n", buf); 
return; 
    } 
     
    fseek(fsig, 0, SEEK_END); 
    if ((len = ftell(fsig)) > MAX_SIG)  { 
logPrintf(LOG_WARN,  
"Too large the signature file is. [%d]\n", len); 
fclose(fsig); 
return; 
    } 
     
    /*fprintf(stderr, "%s [%d]\n", buf, len);*/ 
     
    rewind(fsig); 
    if ((signature = (char*) malloc(len + len / 5)) == NULL)  { 
fclose(fsig); 
logPrintf(LOG_WARN,  
"Insufficent memory for signature built. [%d]\n", len); 
return; 
    } 

   &b;b =ns;''''>''''; 
    sig = buf + 1; 
    *iar&nbp=nsp;''''\0''''; 
     
    while (fgets(sig, SVRBUF - 1, fsig))  { 
if (!strncmp(sig, "From ", 5))  strcat(signature, buf); 
else  strcat(signature, sig); 
    } 
    fclose(fsig); 
}         
     

int folder_number() 

    Folder *fo; 
    int    num; 

    if (rootfld == NULL)  return -1; 
     
    for (num = 0, fo = rootfld; fo; fo = fo->next)  { 
num += fo->num; 
    } 
    return num; 



Folder *folder_open(char *mailbox, int beh) 

    Folder  *fo; 
    Mail    *m; 
    char    buf[SVRBUF], *idx[PARMAX], *pipeto; 
    int     i, rs; 

    if (rootfld == NULL)  { 
umask(0077); 
if (mktmpdir(gdir) == NULL) 
    return NULL; 
    }
     
    if (mailbox == NULL)  return NULL; 

    if ((pipeto = rc_check(RCKEY_SIG)) != NULL)  { 
load_signature(pipeto); 
    } 

    pipeto = rc_check(RCKEY_PIPE); 
    rs = ziptoken(mailbox, idx, PARMAX, DELIMS); 
    for (i = 0; i < rs; i++)  { 
fullpath(idx[i], buf); 
// printf("folder: %s\n", buf); 
if (check_loaded(buf))  continue;  /* message folder loaded already */ 

if ((fo = msg_loader(gdir, buf, fid, 1, beh)) != NULL)  { 
    logPrintf(LOG_INFO, "[%s] loaded, %d messagesd\n", buf, fo->num); 
    folder_insert(fo); 
    fid++; 
     
    for (m = fo->mail; m; m = m->next)  { 
//printf("pipe message: %s (%X)\n", pipeto, m->behave); 
msg_pipeto(m, pipeto, 1, signature); 
    } 

    } 

    return rootfld; 



static char blkbuf[BLKBUF]; 

static int folder_backup(char *backup) 

    Folder *fo; 
    Mail   *m; 
    FILE   *fin, *fout; 
    int    cnt, rs; 

    if (!backup)  return -1; 
     
    fullpath(backup, blkbuf); 
    fout = fopen(blkbuf, "a"); 
    if (fout == NULL)  { 
logPrintf(LOG_WARN, "folder_backup: open [%s] failed.\n", blkbuf); 
return -2; 
    } 

    for (cnt = 0, fo = rootfld; fo; fo = fo->next)  { 
for (m = fo->mail; m; m = m->next)  { 
    if (m->removed == 0)  continue; 
     
    /* pick up removed messages, then backup them */ 
     
    if ((fin = fopen(m->msg->name, "r")) == NULL)  { 
logPrintf(LOG_WARN, "folder_backup: open [%s] failed.\n",  
m->msg->name); 
continue; 
    } 

    while ((rs = fread(blkbuf, 1, BLKBUF, fin)) > 0) 
fwrite(blkbuf, 1, rs, fout); 
    fputs("\n", fout); 
    fclose(fin); 
    cnt++; 

    } 
    logPrintf(LOG_INFO, "folder_backup: %d messages backuped.\n", cnt); 
    return cnt; 



static int folder_compress() 

    Folder *fo; 
    Mail   *m; 
    int    cnt; 

    for (cnt = 0, fo = rootfld; fo; fo = fo->next)  { 

/* unpipe undelivered messages */ 
     
for (m = fo->mail; m; m = m->next)  { 
    if (m->removed == 0)  { 
msg_unpipe(m); 
cnt++; 
    } 


msg_combine(fo); 
    } 
    logPrintf(LOG_INFO, "folder_compress: %d messages undelivered.\n", cnt); 
    return cnt; 



int folder_close(char *backup, int beh) 

    Folder *fo, *tmp; 

    if (backup && (beh & ACT_BACK))   
folder_backup(backup); 
     
    if (beh & ACT_DELE)   
folder_compress(); 
     
    fo = rootfld; 
    while (fo)  { 
msg_clean(fo); 
tmp = fo; 
fo = fo->next; 
free(tmp); 
    } 

    rmdir(gdir); 
    rootfld = NULL; 
    return OK; 



static char *ddmsg = "dead.letter"; 

Folder *folder_online(char *to, char *cc, char *bcc, char *sub, int beh) 

    Folder  *fo; 
    Mail    *m; 
    FILE    *fp; 
    char    buf[SVRBUF], *p; 
    //int     rs; 

    if (rootfld == NULL)  { 
umask(0077); 
if (mktmpdir(gdir) == NULL) 
    return NULL; 
    } 

    if ((fo = msg_loader(gdir, ddmsg, fid, 1, beh)) == NULL)   
return NULL; 
     
    folder_insert(fo); 
    m = msg_expand(fo, gdir, NULL); 

    p = rc_check(RCKEY_REPLY); 
    if (p == NULL)  { 
sprintf(buf, "%s@%s", get_user(), get_hostname()); 
p = buf; 
logPrintf(LOG_WARN, "folder_online: system address %s\n", p); 
    } 
    m->from    = dup_str(p); 
    m->reply   = dup_str(p); 
    m->to      = dup_str(to); 
    m->cc      = dup_str(cc); 
    m->bcc     = dup_str(bcc); 
    m->subject = dup_str(sub); 
    m->behave  = beh; 
     
    fp = fopen(m->msg->name, "w"); 
    if (fp == NULL)  { 
msg_free_mailobj(m); 
msg_clean(fo); 
rmdir(gdir); 
rootfld = NULL; 
return NULL; 
    } 
     
    fprintf(fp, "From %s %s\n", email_pure(m->from), timenow()); 
     
    if (isatty(0))  { 
     if (sub == NULL)  { 
         fprintf(stderr, "Subject: "); 
         fgets(buf, SVRBUF, stdin); 
         chop(buf); 
         if (!isblankline(buf))  m->subject = dup_str(buf); 
     } 
     fprintf(stderr, "Use CTRL-D to terminate letter\n"); 
    } 
     
    fprintf(fp, "From: %s\n", m->reply); 
    if (m->to)  fprintf(fp, "To: %s\n", m->to); 
    if (m->cc)  fprintf(fp, "Cc: %s\n", m->cc); 
    if (m->subject)  fprintf(fp, "Subject: %s\n", m->subject); 
    
    /*if ((m->behave & ACT_EHEAD) != 0)  { 
rs = 0; 
for (p = rc_check(RCKEY_HEADER); p; p = rc_check_next())  { 
    if (head_cmp(p, HD_MAILER))  rs++; 
    fprintf(fp, "%s\n", p); 

if (rs == 0)  fprintf(fp, XMAILER, VERSION); 
    }*/ 
    fprintf(fp, "\n"); 

    m->msg->boff = ftell(fp); 
    while (fgets(buf, SVRBUF, stdin))  { 
if (!strncmp(buf, "From ", 5))  { 
    m->msg->len += fprintf(fp, ">%s", buf); 
} else { 
    m->msg->len += fprintf(fp, "%s", buf); 

m->msg->line++; 
    } 

    if ((m->behave & ACT_ASIG) && signature)  { 
m->msg->len += fprintf(fp, "%s", signature); 
    } 

    fclose(fp); 
    m->msg->mtime = filedate(m->msg->name, &m->msg->msize); 

    if ((p = rc_check(RCKEY_PIPE)) != NULL)  msg_pipeto(m, p, 1, signature); 
    /*if (p && (m->behave & ACT_PIPE))   
msg_pipe2(m, p, signature);*/ 
     
    return fo; 



int folder_close_online(char *backup, int beh) 

    int  rs = rootfld->num; 
     
    if (backup && (beh & ACT_BACK))   
folder_backup(backup); 
     
    if (beh & ACT_DELE)   
rs = folder_compress(); 
     
    msg_clean(rootfld); 
    free(rootfld); 
    rootfld = NULL; 

    rmdir(gdir); 
    if (rs == 0) 
unlink(ddmsg); 
     
    return OK; 



void folder_dump(Folder *fld) 

    Folder *fo; 
    Mail   *m; 
    FILE   *fp; 
    char   buf[SVRBUF]; 

    for (fo = fld; fo; fo = fo->next)  { 
for (m = fo->mail; m; m = m->next)  {
    fp = fopen(m->msg->name, "r"); 
    if (fp == NULL)  continue; 
     
    while (fgets(buf, SVRBUF, fp))  { 
fputs(buf, stdout); 
    } 
     
    fclose(fp); 
    printf("\n"); 

    } 



void folder_list(Folder *fld) 

    struct winsize ws; 
    Folder *fo; 
    Mail   *m; 
    char   buf[SVRBUF], ad[80]; 
    int    i, addr; 

    if (ioctl(1, TIOCGWINSZ, (char *) &ws) < 0)  { 
ws.ws_col = atoi(getenv("COLUMNS")); 
ws.ws_row = atoi(getenv("LINES")); 
if (ws.ws_col == 0)  ws.ws_col = 80; 
    } 
    addr = ws.ws_col / 3;    /* 1/3 column for target address */ 

    for (fo = fld; fo; fo = fo->next)  { 
     
printf("[%s]: %d messages.\n", fo->name, fo->num); 

for (m = fo->mail; m; m = m->next)  { 

    i = sprintf(ad, "%s", m->to ? m->to : ""); 
    for ( ; i < addr; i++)  ad&9;&bsp;=ns;'''' ''''; 
    ad[addr] = 0; 
     
    i = sprintf(buf, "%5d# %-s %6d \"%s\"", m->id, ad, m->msg->len,  
    m->subject ? m->subject : ""); 
     
    if (i >= ws.ws_col)  { 
buf[ws.ws_col -&nbp&9;&bsp;=ns;''''"''''; 
buf[ws.ws_col - 1] = 0; 
    } 
    printf("%s\n", buf); 

    }      


[/code:1:0568ea60bc] 
memo.c 
[code:1:0568ea60bc] 


#ifdef HAVE_CONFIG_H 
#include "config.h" 
#endif 

#include  
#include  
#include  
#include  

#include "defs.h" 
#include "memo.h" 


Memo *memo_open(char *memo) 

    Memo  *mm; 
    char  buf[SVRBUF]; 

#ifdef DEBUG 
    if (!memo)  return NULL; 
#endif 

    if ((mm = malloc(sizeof(Memo))) == NULL)  { 
dbgPrintf("memo_open: out of memory.\n"); 
return NULL; 
    } 
    mm->num = 0; 
     
    if ((mm->fp = fopen(memo, "a+")) == NULL)  { 
dbgPrintf("memo_open: Cannot open address memo. [%s]\n", memo); 
free(mm); 
return NULL; 
    } 

    if ((mm->pm = pm_handler(PGIDX, PGSIZE)) == NULL)  { 
dbgPrintf("memo_open: No PMAL handle allocated.\n"); 
fclose(mm->fp); 
free(mm); 
return NULL; 
    } 

    rewind(mm->fp); 
    while (fgets(buf, SVRBUF, mm->fp))  { 
lineri&40bf&bsp;''''#''''); 
if (isblankline(buf))  continue; 

if (mm->num >= MMIDX)  break; 
mm->idx[mm->num] = pm_dup_str(mm->pm, buf); 
if (mm->idx[mm->num])  mm->num++; 
    } 
     
    return mm; 


void memo_close(Memo *mm) 

#ifdef DEBUG 
    if (!mm)  return; 
#endif 
     
    fclose(mm->fp); 
    pm_close(mm->pm); 
    free(mm); 



int memo_add_addr(Memo *mm, char *addr) 

    int   i; 

#ifdef DEBUG 
    if (!mm || !addr)  return 1; 
#endif 
     
    if (isblankline(addr))  return 0; 

    for (i = 0; i < mm->num; i++)  { 
if (!email_cmp(mm->idx[i], addr))  return 0;  /* existed already */ 
    } 
     
    if (mm->num >= MMIDX)  return 0; 
    mm->idx[mm->num] = pm_dup_str(mm->pm, addr); 
    if (mm->idx[mm->num])  mm->num++; 
     
    fseek(mm->fp, 0, SEEK_END); 
    fprintf(mm->fp, "%s\n", addr); 
    fflush(mm->fp); 

    return 1; 



char *memo_choose(Memo *mm, int col, int line) 

    char  buf[SVRBUF]; 
    int   i, k, len; 
     
#ifdef DEBUG 
    if (!mm)  return NULL; 
#endif 

    i = 0; 
    line--; 
    while(1) { 
for (k = 0; (i < mm->num) && (k < line); i++, k++)  { 
    len = sprintf(buf, "%4d- ", i + 1); 
    StrnCpy(buf + len, mm->idx[i], SVRBUF - len); 
    len = strlen(buf); 
    if (len > col)  { 
buf[col -&nbp&3&ns;&bsp;''''-''''; 
buf[col -&nbp&3&nbp=nsp;''''\0''''; 
    } 
    printf("%s\n", buf); 

b it&4;quot;'''''''bp;ak&bsp;''''f''''b;owr,nbsp;'''''''bp;ut&bsp;''''a'''' abort, choose: "); 
fgets(buf, SVRBUF, stdin); 
lineri&40bf&bsp;''''#''''); 

if (!strcasecmp(buf, "q"))  return NULL; 
else if (!strcasecmp(buf, "a"))  return (char*) memo_choose; 
else if (!strcasecmp(buf, "b")) { 
    i -= line; 
    if (i < 0)  i = 0; 
} else if (isdigit(buf[0]))  { 
    i = atoi(buf) - 1; 
    if (i < 0)  return NULL; 
    else  return mm->idx[i]; 
} else if (i == mm->num)  { 
    i -= line; 
    if (i < 0)  i = 0; 

    } 
    return NULL; 

     
     
[/code:1:0568ea60bc] 
strdate.c 
[code:1:0568ea60bc] 


#include  
#include  
#include  

#if TIME_WITH_SYS_TIME 
  #include  
  #include  
#else 
  #if HAVE_SYS_TIME_H 
    #include  
  #else 
    #include  
  #endif 
#endif 


extern int ziptoken(char *sour, char **idx, int ids, char *delim); 

static char *week[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; 
static char *mon[] = { "Jan", "Feb", "Mar",  "Apr", "May", "Jun", 
                       "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; 

static int get_week(char *s) 

    int  i; 

    for (i = 0; i < 7; i++)  if (!strncmp(week[i], s, 3))  break; 
    if (i == 7)  return -1; 
    return i; 


static int get_month(char *s) 

    int  i; 

    for (i = 0; i < 12; i++)  if (!strncmp(mon[i], s, 3))  break; 
    if (i == 12)  return -1; 
    return i; 


static int get_mday(char *s) 

    int  i; 

    i = atoi(s); 
    if ((i < 1) || (i > 31))  return -1; 
    return i; 


static int get_year(char *s) 

    int  i; 

    /* The number of years since 1900 */ 
     
    i = atoi(s); 
     
#ifdef Y2K_FORCED 
    if ((i >= 0) && (i < 70))  i += 2000; /* for Y2K problem */ 
    else if ((i > 70) && (i < 100))  i+= 1900; 
    else if (i > 1900)  i -= 1900; 
#else 
    if (i > 1900)  i -= 1900; 
#endif 
     
    return i; 


/*  
    Time zone may be indicated in several ways.  "UT" is Universal   
    Time  (formerly called "Greenwich Mean Time"); "GMT" is permitted  
    as a reference to Universal Time.  The  military  standard uses   
    a  single  character for each zone.  "Z" is Universal Time. "A"  
    indicates one hour earlier, and "M" indicates 12  hours  earlier;   
    "N"  is  one  hour  later, and "Y" is 12 hours later.  The letter  
    "J" is not used.  The other remaining two forms are  taken from  
    ANSI standard X3.51-1975.  One allows explicit indication of the  
    amount of offset from UT; the other uses  common  3-character  
    strings for indicating time zones in North America. 
*/ 

static int get_zone(char *s) 

    int  z; 

    if (!strcmp(s, "UT") || !strcmp(s, "GMT") || !strcmp(s, "Z"))  z = 0; 
    else if (!strcmp(s, "EST"))  z = 500; 
    else if (!strcmp(s, "EDT"))  z = 400; 
    else if (!strcmp(s, "CST"))  z = 600; 
    else if (!strcmp(s, "CDT"))  z = 500; 
    else if (!strcmp(s, "MST"))  z = 700; 
    else if (!strcmp(s, "MDT"))  z = 600; 
    else if (!strcmp(s, "PST"))  z = 800; 
    else if (!strcmp(s, "PDT"))  z = 700; 
    else if (!strcmp(s, "A"))  z = -100; 
    else if (!strcmp(s, "M"))  z = -1200; 
    else if (!strcmp(s, "N"))  z = 100; 
    else if (!strcmp(s, "Y"))  z = 1200; 
    else if (&0snbp=&bsp;''''+'''') || &0snbp=&bsp;''''-''''))  z = atoi(s); 
    else z = 10000; /* mark as parse error */ 

    return z; 


static int get_time(char *s, struct tm *t) 

    char  *idx[3]; 

    if (ziptoken(s, idx, 3, ":") < 2)  return -1; 
    if (idx[0])  t->tm_hour = atoi(idx[0]); 
    if (idx[1])  t->tm_min  = atoi(idx[1]); 
    if (idx[2])  t->tm_sec  = atoi(idx[2]); 
    return 0; 


static int get_mday_rfc850(char *s, struct tm *t) 

    char  *idx[3]; 

    ziptoken(s, idx, 3, "-"); 
    if (idx[0])  t->tm_mday = atoi(idx[0]); 
    if (idx[2])  t->tm_year = atoi(idx[2]); 
    if ((t->tm_mon = get_month(idx[1])) == -1)  return -1; 
    return 0; 


int strdate(char *s, struct tm *t) 

    char  *idx[10], buf[80]; 
    int   zone, rs = 0; 

    strncpy(buf, s, 80); 
    buf &3&nbp=nsp;''''\0''''; 
    memset(t, 0, sizeof(struct tm)); 
    rs = ziptoken(buf, idx, 10, ", "); 
     
    if �th�s&bsp;''''-'''') && (rs == 4))  { 

/* rfc850 date style */ 
/* Weekday, DD-Mon-YY HH:MM:SS TIMEZONE */ 
/* Is this style Y2K compalient ? */ 

rs = 0; 
if ((t->tm_wday = get_week(idx[0])) == -1)  rs++; 
if (get_mday_rfc850(idx[1], t) == -1)  rs++; 
if (get_time(idx[2], t) == -1)  rs++; 
if ((zone = get_zone(idx[3])) == 10000)  rs++; 

    } else if (s #;nbp=&bsp;'''','''')  { 
     
/* rfc822 date style */ 
/* [WDY,] DD Mon YY HH:MM[:SS] TIMEZONE */ 

rs = 0; 
if ((t->tm_wday = get_week(idx[0])) == -1)  rs++; 
if ((t->tm_mday = get_mday(idx[1])) == -1)  rs++; 
if ((t->tm_mon = get_month(idx[2])) == -1)  rs++; 
if ((t->tm_year = get_year(idx[3])) == -1)  rs++; 
if (get_time(idx[4], t) == -1)  rs++; 
if ((zone = get_zone(idx[5])) == 10000)  rs++; 

    } else if (*idx[0#;bp;l;&bsp;''''9'''')  { 

/* rfc822 date style */ 
/* [WDY,] DD Mon YY HH:MM[:SS] TIMEZONE */ 

rs = 0; 
if ((t->tm_mday = get_mday(idx[0])) == -1)  rs++; 
if ((t->tm_mon = get_month(idx[1])) == -1)  rs++; 
if ((t->tm_year = get_year(idx[2])) == -1)  rs++; 
if (get_time(idx[3], t) == -1)  rs++; 
if ((zone = get_zone(idx[4])) == 10000)  rs++; 

    } else  if ((rs == 5) || (rs == 6)) { 

/* ctime date style */ 
/* Note in particular that ctime format: 

Wdy Mon DD HH:MM:SS [TIMEZONE] YYYY 

   is not acceptable because it is not a valid ARPANET  date. 
   However, since older software still generates this format, 
   news implementations are encouraged to accept this  format 
   and translate it into an acceptable format. */ 
     
rs = 0; 
if ((t->tm_wday = get_week(idx[0])) == -1)  rs++; 
if ((t->tm_mon = get_month(idx[1])) == -1)  rs++; 
if ((t->tm_mday = get_mday(idx[2])) == -1)  rs++; 
if (get_time(idx[3], t) == -1)  rs++; 

if (*idx[&3nsp&t&bsp;''''9'''')  { 
    if ((zone = get_zone(idx[4])) == 10000)  rs++; 
    if ((t->tm_year = get_year(idx[5])) == -1)  rs++; 
} else if ((t->tm_year = get_year(idx[4])) == -1)  rs++; 
    } 
     
    return rs; 



time_t strtimet(char *s) 

    struct tm t; 

    strdate(s, &t); 
    return mktime(&t); 
}    
     

#ifdef EXECUTABLE 

int main(int argc, char **argv) 

    struct tm t; 
    int  rs = 0; 
     
    if (argc < 2)  { 
printf("usage: %s \"date string\"\n", argv[0]); 
return 0; 
    } 

    if ((rs = strdate(argv[1], &t)) > 0) { 
printf("parse error\n"); 
    } else { 
printf("%s\n", asctime(&t)); 
    } 
    return rs; 


#endif 

[/code:1:0568ea60bc] 
mime.c 
[code:1:0568ea60bc] 
#ifdef HAVE_CONFIG_H 
#include "config.h" 
#endif 

#include  
#include  
#include  
#include  

#if HAVE_UNISTD_H 
  #include  
  #include  
#endif 

#include "defs.h" 


/* For example: 
------=_NextPart_000_008A_01C0B63E.41DCF080 
Content-Type: text/plain; 
         charset="gb2312" 
Content-Disposition: attachment; 
        filename="E:\dirhtml2m.txt" 
Content-Transfer-Encoding: base64 
*/ 

typedef struct { 
char *name;     /* filename="E:\dirhtml2m.txt" */ 
char *bndry;     /* ------=_NextPart_000_008A_01C0B63E.41DCF080 */ 
int type;     /* text/plain 1:text; 0:saving file */ 
int encode;     /* base64 */ 
int chset;     /* "gb2312" 0:ignore; 1: HZ encoded */ 
char buff[256]; 
} MMARK; 

#define MAXMK 12 


static char *get_boundary(char *sour, char *bndry, int len) 

    char *p; 

    p = th#0;or&bsp;''''=''''); 
    if (p == NULL)   
return NULL; 

    for (p++; isspace(*p); p++); 
    if &0*&nsp;==ns;''''"'''')   
p++; 

    *d+&ns;&bsp;''''-''''; 
    *d+&ns;&bsp;''''-''''; 
    StrnCpy(bndry, p, len); 

    for (p = bndry + strlen(bndry) - 1; p > bndry; p--)  { 
if (isspace(*p) || &0*&nsp;==ns;''''"''''))   
    *p = 0; 
else  
    break; 
    } 

    /* printf("BOUNDARY EXTRACT: %s\n", bndry - 2); */ 
    return bndry - 2; 



static void parse_ctype(MMARK *mm, char *ctype) 

    char  *idx[32], *p; 
    int   i, rs; 

    rs = ziptoken(ctype, idx, 32, ";"); 
     
    for (i = 0; i < rs; i++)  { 
p = skip_space(idx[i]); 
if (!strncasecmp(p, "text/", 5))   
    mm->type = 1; 
else if (!strncasecmp(p, "charset", 7))  { 

    p += 7; 
    if (isalpha(*p))   
continue; 
    while (*p && !isalpha(*p))   
p++; 
    if (!strncasecmp(p, "hz-gb-2312", 10))  
mm->chset = 1; 
     
} else if (!strncasecmp(p, "boundary", 8))  { 

    p += 8; 
    if (isalpha(*p)) 
continue; 
    mm->bndry = &mm->buff[128]; 
    get_boundary(p, mm->bndry, 120); 
     
} else if (!strncasecmp(p, "name", 4))  { 
     
    p += 4; 
    if ((p =&nbpth�p&bsp;''''='''')) == NULL) 
continue; 
    p++; 
    p = skip_space(p); 
    if &0*&nsp;==ns;''''"'''') 
p++; 
    /* conPrintf(p); */ 

    mm->name = mm->buff; 
    strncpy(mm->name, p, 128); 
    for (p = mm->name + strlen(mm->name) - 1; p >= mm->name; p--)  { 
if (!isspace(*p) && &0*&nsp;!=ns;''''"'''')) 
    break; 
else 
    *p = 0; 
    } 

    } 


static void parse_disposit(MMARK *mm, char *disp) 

    char  *idx[32], *p; 
    int   i, rs; 

    rs = ziptoken(disp, idx, 32, ";"); 

    for (i = 0; i < rs; i++)  { 
p = skip_space(idx[i]); 
if (!strncasecmp(p, "filename", 8))  { 

    p += 8; 
    if ((p =&nbpth�p&bsp;''''='''')) == NULL) 
continue; 
    p++; 
    p = skip_space(p); 
    if &0*&nsp;==ns;''''"'''') 
p++; 
    /* conPrintf(p); */ 

    mm->name = mm->buff; 
    strncpy(mm->name, p, 128); 
    for (p = mm->name + strlen(mm->name) - 1; p >= mm->name; p--)  { 
if (!isspace(*p) && &0*&nsp;!=ns;''''"'''')) 
    break; 
else 
    *p = 0; 
    } 

    } 
}

static void get_mime_mark(FILE *fp, FILE *fout, MMARK *mm, char *buf, int len) 

    char  *p; 
    int   status; 

    status = 0; 
    memset(mm, 0, sizeof(MMARK)); 
     
    while (fgets(buf, len, fp))  { 

fputs(buf, fout); 
if (isblankline(buf)) 
    break; 

p = buf; 
if (!isspace(buf[0]))  { 
    status = 0; 
    if (!strncasecmp(buf, "Content-Type:", 13))  { 
status = 1; 
p = buf + 13; 
    } else if (!strncasecmp(buf, "Content-Transfer-Encoding:", 26))  { 
status = 2; 
p = buf + 26; 
    } else if (!strncasecmp(buf, "Content-Disposition:", 20))  { 
status = 3; 
p = buf + 20; 
    } 

p = skip_space(p); 
/* printf("--COntent:> %s", p); */ 

switch (status)  { 
case 1: 
    parse_ctype(mm, p); 
    break; 

case 2: 
    if (!strncasecmp(p, "7bit", 4))   
    mm->encode = CTE_7BIT; 
    else if (!strncasecmp(p, "quoted-printable", 16))   
    mm->encode = CTE_QP; 
    else if (!strncasecmp(p, "base64", 6))   
    mm->encode = CTE_BASE64; 
    else if (!strncasecmp(p, "8bit", 4))   
    mm->encode = CTE_8BIT; 
    else if (!strncasecmp(p, "binary", 6))   
    mm->encode = CTE_BINARY; 
    break; 

case 3: 
    parse_disposit(mm, p); 
    break; 
     
default: 
    break; 

    } 



static void 
mime_extract(FILE *fin, FILE *fout, char *bndry, int ctl, char *buf, int len) 

    MMARK  mm; 
    FILE   *ftmp; 
    char   *p; 
     
    while (!feof(fin))  { 

fputs(buf, fout); 
chop(buf); 

if (strncmp(buf, bndry, strlen(bndry)))  { 
    fgets(buf, len, fin); 
} else { 
    get_mime_mark(fin, fout, &mm, buf, len); 
     
    /*printf("mime type:   %d\n", mm.type); 
    printf("mime name:   %s\n", mm.name); 
    printf("mime bndry:  %s\n", mm.bndry); 
    printf("mime encode: %d\n", mm.encode); 
    printf("mime chset:  %d\n", mm.encode);*/ 
     
    if (mm.bndry && *mm.bndry)  { 
fgets(buf, len, fin); 
mime_extract(fin, fout, mm.bndry, ctl, buf, len);  
    } else if (mm.type == 1)  { 
     
if (mm.encode == CTE_BASE64)  { 
  npnsp;pt&40;''''\n'''', fout); 
    debase64_bndry(fin, fout, bndry, buf, len); 
  npnsp;pt&40;''''\n'''', fout); 
} else if (mm.encode == CTE_QP)  { 
  npnsp;pt&40;''''\n'''', fout); 
    deqp_bndry(fin, fout, bndry, buf, len); 
  npnsp;pt&40;''''\n'''', fout); 
} else { 
    fgets(buf, len, fin); 


    } else if (mm.name)  { 
     
conPrintf("Extract file [%s]? (Yes/No/Rename) ", 
mm.name); 
tcflush(0, TCIFLUSH); 
read(0, buf, len); 
p = skip_space(buf); 

switch (*p) &1;b> cs&bsp;''''y''''#;b> cs&bsp;''''Y'''': 
    strcpy(buf, mm.name); 
    break;<>b> cs&bsp;''''r''''#;b> cs&bsp;''''R'''': 
    conPrintf("Input filename: "); 
    tcflush(0, TCIFLUSH); 
    read(0, buf, len); 
    chop(buf); 
    if (isblankline(buf))   
strcpy(buf, mm.name); 
    break; 

default#;b> cs&bsp;''''n''''#;b> cs&bsp;''''N'''': 
    fgets(buf, len, fin); 
    continue; 


if ((ftmp = fopen(buf, "w")) == NULL)  { 
    fgets(buf, len, fin); 
    continue; 

if (mm.encode == CTE_BASE64) { 
    debase64_bndry(fin, ftmp, bndry, buf, len); 
} else if (mm.encode == CTE_QP) { 
    deqp_bndry(fin, ftmp, bndry, buf, len); 
} else { 
    while (fgets(buf, len, fin))  { 
if (!strncmp(buf, bndry, strlen(buf) - 1))   
    break; 
fputs(buf, ftmp); 
    } 

fclose(ftmp); 

    } else  
fgets(buf, len, fin); 

    } 
    conPrintf("Mime message extracted.\n"); 



static int mime_multi(char *file, char *bndry, int ctl, char *buf, int len) 

    FILE  *fin, *fout; 

    if ((fin = fopen(file, "r")) == NULL)  
return -1; 

    unlink(file); 
    if ((fout = fopen(file, "w")) == NULL)  { 
fclose(fin); 
return -1; 
    } 

    fgets(buf, len, fin); 
    mime_extract(fin, fout, bndry, ctl, buf, len); 

    fclose(fin); 
    fclose(fout); 

    return 0; 



static int decode_hzgb(char *file) 

    FILE  *fin, *fout; 

    if ((fin = fopen(file, "r")) == NULL) 
return -1; 

    unlink(file); 
    if ((fout = fopen(file, "w")) == NULL)  { 
fclose(fin); 
return -1; 
    } 

    dehz_file(fin, fout); 

    fclose(fin); 
    fclose(fout); 
    return 0; 



/* ctl=0: decode attached file; ctl=1: decode text only */ 

int mime_body(Mail *m, FILE *fin, char *outfile, int ctl) 

    FILE  *fout; 
    char  buf[SVRBUF], bndry[128], *idx[32], *p; 
    int   i, rs; 

    /* 
    if (fin == NULL)  { 
fin = fopen(m->msg->name, "r"); 
if (fin == NULL)  { 
    dbgPrintf("mime_body: cannot open input file\n"); 
    return -1; 

fseek(fin, m->msg->boff, SEEK_SET); 
    }*/ 

    if ((fout = fopen(outfile, "w")) == NULL)  { 
dbgPrintf("mime_body: cannot open output file. [%s]\n", outfile); 
return -1; 
    } 

    if (m->c_encode == CTE_QP) 
deqp_file(fin, fout); 
    else if (m->c_encode == CTE_BASE64) 
debase64_file(fin, fout); 
    else 
dup_stream(fin, fout); 

    fclose(fout); 
     
    if (m->c_type) { 
     
StrnCpy(buf, m->c_type, SVRBUF); 
rs = ziptoken(buf, idx, 32, ";"); 

/* 
printf("Type: "); 
for (i = 0; i < rs; i++)  printf("@ %s ", idx[i]); 
printf("\n"); */ 

for (i = 0; i < rs; i++)  { 

    p = skip_space(idx[i]); /* skip leading white spaces */ 
     
    if (!strncasecmp(p, "charset", 7))  { 
p += 7; 
if (isalpha(*p)) 
    continue; /* avoid of "charsetxxx" */ 

while (!isalpha(*p)) 
    p++; 
if (!strncasecmp(p, "hz-gb-2312", 10))  { 
    decode_hzgb(outfile); 
    break; 

    } else if (!strncasecmp(p, "boundary", 8))  { 
p += 8; 
if (isalpha(*p)) 
    continue; 

p = get_boundary(p, bndry, 128); 

/* no code now */ 
mime_multi(outfile, p, 0, buf, SVRBUF); 

break; 
    } 

    } 

    return 0; 



/******************************************************************/ 

/* 
    abc =?gb2312?B?xxxxxxx?= hello 
        | |      | |      | | 
| |      | |      | +--- tail 
| |      | |      +----- bodyend 
| |      | +--- body 
| |      +----- encode 
| +--- codepage 
+----- start point 
*/ 

struct code_mark  { 
char *codepage; 
char *encode; 
char *body; 
char *bodyend; 
char *tail; 
}; 

#define ISSPACE(p) ((#;nbs;=nsp;''''\n'''') || (#;nbs;=nsp;''''\r'''') || (#;nbs;=nsp;''''\f'''')) 

static struct code_mark *check_code_mark(char *sour) 

    static struct code_mark cm; 
    char  *p = sour; 

    if (&0pnbp!&bsp;''''='''') || (*(+#;nbp!&bsp;''''?'''')) 
return NULL; 
    cm.codepage = p + 2; 
     
    for (p += 2; *p && &0pnbp!&bsp;''''?''''); p++)  { 
if (ISSPACE(*p)) 
   &s;p&bsp;=ns;'''' ''''; 
    } 
    if (*p == 0)  
return NULL; 
    cm.encode = p + 1; 
     
    for (p++; *p && &0pnbp!&bsp;''''?''''); p++)  { 
if (ISSPACE(*p)) 
   &s;p&bsp;=ns;'''' ''''; 
    } 
    if (*p == 0)  
return NULL; 
    cm.body = p + 1; 
     
    for (p++; *p; p++)  { 
if (&0pnbp=&bsp;''''?'''') && (*(+#;nbp=&bsp;''''=''''))  
    break; 
if (ISSPACE(*p))  
   &s;p&bsp;=ns;'''' ''''; 
    } 
    if (*p == 0)  
cm.tail = cm.bodyend = p; 
    else  { 
cm.bodyend = p; 
cm.tail = p + 2; 
    } 

    return & 
}    

/* de-code all kinds format if I know in just a single comment  
 * and keep newline char out. Such as "abc =?gb2312?B?xxxxxxx?= hello" 
 * There are 3 control style in the variety ctl: 
 * 0: No decode, just pass though the original head and keep the newline out 
 * 1: decode and remain the leading char like "=?gb2312?B?" 
 * 2: decode and get rid of the leading char  
 * Note: the result will replace the original string */ 

char *decode_head(char *sour, int ctl) 

    struct code_mark *cm; 
    char *p, *k, tmp; 
    int  cnt, i, hzflag; 

    p = k = sour; 
    hzflag = 0; 
    while (*k)  { 
if (ctl && ((cm = check_code_mark(k)) != NULL)) { 
    if (ctl == 1)  { 
for ( ; k < cm->body; *p++ = *k++); 
k = cm->bodyend; 
    } else 
k = cm->tail; 
     
    tmp = *cm->bodyend; 
    *cm->bodyend = 0; 
     
    if (!strncasecmp(cm->codepage, "hz-gb-2312", 10)) 
hzflag++; 
     
    switch (*cm->encode) { 
  npnspcs&bsp;''''b'''': 
  npnspcs&bsp;''''B'''': 
/* puts(cm->body); */ 
cnt = debase64_str(cm->body, p); 
for (i = 0; i < cnt; i++, p++)  { 
    if (ISSPACE(*p)) b p&bsp;=ns;'''' ''''; 

break; 

  npnspcs&bsp;''''q'''': 
  npnspcs&bsp;''''Q'''': 
cnt = deqp_str(cm->body, p); 
for (i = 0; i < cnt; i++, p++)  { 
    if (ISSPACE(*p)) b p&bsp;=ns;'''' ''''; 

break; 

    default: 
p = k; 
    } 
    *cm->bodyend = tmp; 

} else if (ISSPACE(*k)) 
   &b;p+&bsp;=ns;'''' '''', k++; 
else 
    *p++ = *k++; 
    } 
    *p = 0; 
     
    /* specially encode: HZ-GB code */ 

    if (hzflag)  { 
/* printf("Sub: %s\n", sour); */ 
dehz_str(sour, sour); 
    } 
     
    return sour; 




[/code:1:0568ea60bc]

 蓝色键盘 回复于:2003-04-25 14:46:40
defs.h 
[code:1:bd1926abc9] 

#ifndef DEFS_PMAIL_H 
#define DEFS_PMAIL_H 


#include  
#include "message.h" 
#include "mhead.h" 
#include "libsupp.h" 


#define HOMEBOX "mbox" 
#define OUTFOLDER "postpone" 
#define PAGER "/bin/more" 
#define EDITOR "/bin/vi" 
#define TMPPATH "/usr/tmp/mailzXXXXXX" 
#define PMTMP "/usr/tmp/pmailXXXXXX" 
#define DEFQUOTA "Last time you wrote:\n" 
#define DELIMS ",:; " /* delimiters for parsing RC file */ 


#define RCKEY_DEBUG "log" /* define log file */ 
#define RCKEY_DEFAULT "default" /* default operation */ 
#define RCKEY_VERBOSE "verbose"
#define RCKEY_TIMEOUT "timeout" 
#define RCKEY_SPAM "spam" /* incoming mail filter */ 
#define RCKEY_FETCH "fetch" /* fetch mail from incoming server */ 
#define RCKEY_TOPSLY "topstyle" 
//#define RCKEY_SIZELMT "quota" /* download message size quota */ 
#define RCKEY_LDELAY "popdelay" /* pop3 server login delay */ 
#define RCKEY_SMTP "smtp" 
#define RCKEY_SMBEHV "smtpbeh" /* default behavior of outgoing mail */ 
#define RCKEY_MBOX "mbox" /* default folder */ 
#define RCKEY_OUTBOX "postpone" 
#define RCKEY_BACKUP "bakbox" 
//#define RCKEY_SENDER "sender" /* act as ISP message sender */ 
#define RCKEY_REPLY "reply-to" /* act as From: */ 
#define RCKEY_SIG "signature" 
#define RCKEY_PIPE "pipeto" /* external pipe */ 
#define RCKEY_HEADER "header" 
#define RCKEY_PAGER "pager" 
#define RCKEY_EDITOR "editor" 
//#define RCKEY_DISHEAD "showhead" /* specify heads for displaying */ 
#define RCKEY_ADMEMO "memo" /* address memo file */ 
#define RCKEY_HEADMASK "headmask" /* Note 64 head classes limited */ 
  

#ennspCMDLIM ''''#'''' /* start mark of commentory */ 
#ennspPTDLIM ''''/'''' /* delimiter of directory */ 
#define MAX_DBG 16 /* specify the maximum debug and log device */ 
#define MAX_SIG 65535 /* the maximun size of signature file */ 
#define QUOTA_DBG 10240 /* default log file quota */ 
#define PATHDEP 32 /* maximum depth of relative file */ 
#define TASK_NR 32 /* maximum work classes limitation */ 
#define SVRBUF 256 
#define EX_HEAD 128 
#define MAXFOLDS 256 
#define PARMAX   100     /* maximum parameters in a command */ 
#define BLKBUF          4096 


#define HMMAX   64              /* head mask limitation */ 
#define HMDEF   "From:To:Cc:Bcc:Subject:Date:Sender:Reply-To:X-Mailer" 


#define YES 1 
#define NO 0 

#define OK 0 
#define WARNING -1 
#define FAILURE -2 
#define NOSMTPHOST -3 
#define LOWMEMORY -6 
#define OPENFILERR -7 
#define CREATEFAIL -8 
#define MISANSWER -9 
#define LOGIN_FAIL -10 
#define SPAM_MSG -20 
#define SPAM_FETCH -21 


#define LOG_ERR 9 
#define LOG_INFO 2 
#define LOG_WARN 1 
#define LOG_ALL 0

#define ID_NULL 0 
#define ID_GMAIL 1 
#define ID_STREAM 2 
#define ID_HELP 3 
#define ID_VERSION 4 
#define ID_TEMPLATE 5 
#define ID_DUMPTMP 6 
#define ID_DUMPINFO 7 
#define ID_SMTP 8 
#define ID_HOSTLIST 9 
#define ID_SPAMTEST 10 
#define ID_PROGRESS 11 

#define SMTP_PORT       25 
#define POP3_PORT       110 


/* this structure should be filled up acdnnbsp;ons;''''smtp'''' option in the 
 * config file. There are 4 entries&b;nbsp;tens;''''smtp'''' option: 
 *     host:reply_address:id:passwd 
 * Pmail read the config file and chains all smtp structures. But only  
 * the first one, or the specified one, will be available. If there is 
 * another smtp server specified in the command line, it should be the  
 * first item inserted to the chain. */ 

typedef struct _SMTP { 
char *host; 
char *reply; 
char *id; 
char *passwd; 
struct _SMTP *next; 
char buf[1]; 
} SMTP; 


#define pfclose(ptr)  { \ 
  if ((ptr) != NULL)  fclose(ptr); \ 
  (ptr) = NULL; \ 


#define xfree(ptr)  {\ 
  free(ptr); \ 
  (ptr) = NULL; \ 


#define chop(buf) ((buf)[strlen(u#;1&bp;= ''''\0'''') 
  
#if !defined(isspace) 
#define isspace(ch) (((ch) > 0) && (&4c&41 &t=nbsp;'''' '''')) 
#endif 

/* stupid strncpy cannot null-terminate oversized string, so I do it */ 

#define StrnCpy(d,s,l) (strncpy((d),(s),(l)), (d)[(l)-1] = 0) 


/* see main.c */ 

extern int  timeout; 
extern int  verbose; 
extern char *cmd_auth; 
extern char *cmd_host; 
extern char *cmd_mbox; 
extern int  *cmd_cp_set; 
extern int  cmd_action; 
extern int  cmd_protocol; 

int  act_bind(char *s); 
void ReleaseResource(); 

/* see smtp.c */ 

int smtp_main(Folder *rootfld, SMTP *sm); 
SMTP *smtp_host_chain(char *host, char *auth); 
void smtp_host_list(); 
void smtp_host_clean(); 

/* see folder.c */ 

Folder *folder_open(char *mailbox, int beh); 
Folder *folder_online(char *to, char *cc, char *bcc, char *sub, int beh); 
int folder_close(char *backup, int beh); 
int folder_close_online(char *backup, int beh); 
int folder_number(); 
void folder_dump(Folder *fld); 
void folder_list(Folder *fld); 

/* mime.c */ 

char *decode_head(char *sour, int ctl); 
int mime_body(Mail *m, FILE *fin, char *outfile, int ctl); 

/* see strdate.c */ 

time_t strtimet(char *s); 
int strdate(char *s, struct tm *t); 

#endif 

[/code:1:bd1926abc9] 
mhead.h 
[code:1:bd1926abc9] 

#ifndef _MHEAD_H 
#define _MHEAD_H 


#include "pmalloc.h" 


#define HDPAGE 4096 /* for PMAL buffer */ 
#define HDIDX 64 

struct head_chain { 
char *str; 
void *next; 
}; 

typedef struct { 

int len;   /* length of the entire head line */ 
int rm;   /* removed marking */ 
char *key;   /* duplication of the head key */ 
char *body;   /* head body, no key started with. Note */ 
struct head_chain  *hc;  /* the remain parts of this head */ 
void *next; 

} HLin; 

typedef struct { 

int len; /* length of entire head part */ 
int num; /* number of head title */ 
char *fmsp; /* the copy of FromSps line */ 
HLin *hlin; /* start of head line chain */ 
HLin *last; /* last item in the head line chain */ 
PMAL *pm; 
void *this; /* point to current Head object itself */ 

char *skey; /* use fro searching next head title */ 
HLin *scur; 

} Head; 

Head *head_register(int page, int idx); 
void head_destruct(Head *hdo); 
char *head_loading(Head *hdo, char *s); 
void head_clean(Head *hdo); 
int  head_to_cache(Head *hdo, FILE *fin, char *buf, int len); 
int  head_of_file(Head *hdo, FILE *fin, char *buf, int len); 
char *head_append(Head *hdo, char *head); 
void head_remove_first(Head *hdo, char *key); 
void head_remove_all(Head *hdo, char *key); 
void head_mask(Head *hdo, char *mask, int rm); 
HLin *head_check(Head *hdo, char *key); 
HLin *head_check_next(Head *hdo); 
char *head_fetch(HLin *h); 
char *head_fetch_body(HLin *h); 
HLin *head_exist(Head *hdo, char *head); 
void head_dump(Head *hdo, FILE *fout, int fmsp); 
char *head_index(char *headline, char *buf, int len); 
int  head_cmp(char *s, char *d); 

#endif 

[/code:1:bd1926abc9] 
message.h 
[code:1:bd1926abc9] 

#ifndef _MESSAGE_H 
#define _MESSAGE_H 

#include  rdfn PATHSEP ''''/'''' 

#define HD_FROM "from" 
#define HD_RPLTO "reply-to" 
#define HD_SENDER "sender" 
#define HD_TO "to" 
#define HD_CC "cc" 
#define HD_BCC "bcc" 
#define HD_SUBJECT "subject" 
#define HD_DATE "date" 
#define HD_STATUS "status" 
#define HD_ACTION "X-behave" 
#define HD_MAILER "X-Mailer" 
#define HD_CTENCODE "Content-Transfer-Encoding" 
#define HD_CTTYPE "Content-Type" 

#define PM_MSG_OK 0 
#define PM_MSG_NOFILE 1 
#define PM_MSG_BADFILE 2 
#define PM_MSG_BINARY 3 
#define PM_MSG_INVALID 4 
#define PM_MSG_NOMEM 5 
#define PM_MSG_BADPIPE 6 


/* encoding mechanism in the Content-Transfer-Encoding field */ 

#define CTE_7BIT 0 
#define CTE_QP 1 
#define CTE_BASE64 2 
#define CTE_8BIT 3 
#define CTE_BINARY 4 



#define     XMAILER \ 
"X-Mailer: pmail %s (Linux). Report bugs to \n" 
  

/* instruct the operation of individual letters in the postpone folder */ 

#define ACT_PIPE        1       /* use external pipe */ 
#define ACT_ASIG        2       /* append signature from file */ 
#define ACT_EHEAD       4       /* enable extra header line */ 
#define ACT_SUSP        0x80 &s;nsp; /* don''''t touch this letter! for pine only */ 
#define ACT_STDIN       0x100   /* The letter comes from standard input. */ 
#define ACT_HOLD 0x1000  /* do not touch original message folder */ 
#define ACT_DELE 0x2000 /* delete successfully sent message */ 
#define ACT_BACK 0x4000 /* backup successfully sent message */ 

#define ACT_NORM  (ACT_PIPE | ACT_ASIG | ACT_EHEAD) 
#define ACT_SMTP  (ACT_DELE | ACT_BACK) 
#define ACT_DEFT  (ACT_PIPE | ACT_ASIG | ACT_EHEAD | ACT_DELE | ACT_BACK) 
  

typedef struct  _MsgObj { 

char    *name;          /* filename of temperary folder */ 
int     len;            /* mail length of body */ 
int     line;           /* mail lines of body */ 
        long    boff;           /* body offset in the temporary letter */ 
int msize; /* size of entire message, include head */ 
time_t  mtime;          /* time of last modification */ 
struct _MsgObj *next; 
char _namebuf[1]; /* room for temperary folder name */ 

} MsgObj; 

/* Note about "from" field and "reply" field: 
   According to RFC822, The "From:" field contains the identity of the  
   person(s) who wished this message to be sent. If this is not done,  
   the "Sender:" field must be present and act as the redundant with the 
   "From:" field. The "Reply-To" field is added by the message originator  
   and is intended to direct replies.  */ 
    
typedef struct _Mail { 

int     id; 
int removed : 1; /* marked as been removed */ 
int changed : 1; /* be dumped, edited */ 
int piped : 1; 
int oldmail : 1; /* false means unread yet */ 
int replied : 1; /* has been replyed */ 

char    *from; /* From: Sender: Reply-To: */ 
        char    *reply; /* Reply-To: From: Sender: */ 
        char    *to; 
        char    *cc; 
char *bcc; 
        char    *subject; 
char *c_type; /* Content-Type: */ 
int c_encode; /* Content-Transfer-Encoding: */ 
        time_t  rtime;          /* time of message reception */ 
int behave; /* from "x-action:" head item */ 

        MsgObj  *msg; 
        struct _Mail *next; 

MsgObj _msgbuf[1]; /* it must be the last item. */ 

} Mail; 


typedef struct _Folder { 

int fid; /* folder identity */ int cur; /* point to current letter in the folder */ 
int lst; /* start point from last lists */ 

int num; /* number of active letter in this folder */ 
int chg; /* changed letters */ 
int rm; /* removed letters */ 
int unrd; /* unread letters */ 

int pp : 1; /* used for postpone folder */ 
int fchg : 1; /* the change status of the folder */ 

Mail *mail; 
struct _Folder *next; 
struct _Folder *prev; 

char _namebuf[1]; 

} Folder; 


/* see message.c */ 

Folder *msg_loader(char *path, char *fldname, int fid, int pp, int beh); 
int  msg_combine(Folder *fo); 
int  msg_clean(Folder *fo); 
void msg_free_mailobj(Mail *m); 
int  msg_block_dup(FILE *fin, FILE *fout); 
Mail *msg_search_id(Folder *fo, int id); 
int  msg_last_actived(Folder *fo); 
int  msg_dump(Mail *m, char *pager); 
int  msg_appendto(Mail *m, char *fname); 
int  msg_edit(Mail *m, char *editor); 
int  msg_pipeto(Mail *m, char *piper, int ctl, char *sig); 
int  msg_unpipe(Mail *m); 
void msg_statistics(Folder *fo); 
int  msg_change_flag(Folder *fo); 
Mail *msg_pickout(Folder *fo, int id); 
void msg_insert(Folder *fo, Mail *m); 
Mail *msg_expand(Folder *fo, char *path, Mail *ins); 
void msg_dup_entry(Mail *dest, Mail *sour); 
long msg_duplicate(char *dest, char *sour); 
int  msg_behave_bind(char *p); 

#endif 
[/code:1:bd1926abc9] 

gmail.h 
[code:1:bd1926abc9] 

#ifndef _GETMAIL_H 
#define _GETMAIL_H 


#if HAVE_REGEX_H 
  #include  
#else 
  #include "regex.h" 
#endif 


#define SPAM_IGNORE 0 
#define SPAM_DELE 1 
#define SPAM_KEEP 2 
#define SPAM_ASK 3 


#define SA_YES_DELE "true-delete" 
#define SA_YES_KEEP "true-keep" 
#define SA_YES_ASK "true_ask" 
#define SA_NO_DELE "false_delete" 
#define SA_NO_KEEP "false_keep" 
#define SA_NO_ASK "false_ask" 

#define SK_ID "id:" 
#define SK_SIZE "quota:" 
#define SK_FROM "from:" 
#define SK_SUBJECT "subject:" 
#define SK_ACTION "action:" 

#define SLPOOL 256 /* pool for Slnk structure */ 
#define PATHMAX 256 /* maximem length of path */  

typedef struct _Spam { 

struct _Spam *next;

int id; /* 0 is general identity */ 
int quota; /* message size quota */ 
char *from; 
char *subject; 

int logic; /* 0: normal logic, 1: minus logic */ 
int action; /* procession of matcher */ 

/* private structure area */ 

regex_t *from_reg; 
regex_t *sub_reg; 

int ireg; /* index of "preg" buffer */ 
regex_t preg[2]; /* by now for "from" and "subject" */ 

} Spam; 


typedef struct { 

Spam *sc; 
void *next; 
} Slnk; 


#define GP_POP3 1 
#define GP_APOP 2 

#define GMAIL_CHECK     1 
#define GMAIL_FETCH     2 
#define GMAIL_LIST      4 
#define GMAIL_DELE      8 

#define TOP_SMART 0 
#define TOP_ALL 1 
#define TOP_BRIEF 2 


/* when operating on remote, this structure owns high priority that GMAIL */ 

struct gm_att { 

int topl; /* lines of mailbody for TOP check */ 
int tops; /* style of mailhead, 0 smart, 1 all */ 
//int quota; /* maximum mail size when retrieving it */ 
int delay; /* a short delay after logging in */ 
int cols; /* current columns in the screen */ 

/* in below come from command line */ 

int *cp_set; /* current processing set */ 
char *mbox; /* message box from command line */ 
int     act; /* download action from command line */ 
char *user; 
char *pass; 
char *defbox; /* default mailbox if no mailbox specified */ 

char *hdmsk[HMMAX]; 
char *hdbuf; /* point to headmask&b;uer&ns;nide ''''buf'''' */ 
char buf[1]; 
}; 


typedef struct  _GMAIL { 

/* read only part, looks on as attribution of POP3 connection  
   Note that if there are same entries between this structure  
   and attribution structure, use the attribution entries. 
   They are mbox, act, user and pass.  */ 

struct _GMAIL *next;
char    *host;
char    *lid; /* login id */ 
char  &nbs&bp*pass; /* user''''s password */ 
char    *mbox; /* mailbox for saving retrieved mails */ 
int     act; /* operation in this session */ 
int protl; 
Slnk *slnk; /* spam filter chain */ 
int topspam; /* set if anti-spam need TOP command */ 
struct  gm_att  *attr; 

/* working varible */ 

int socket; /* put these here for close-convenient */ 
FILE *fp; /*   against signal */ 
int *mlist; /* structure list of mails */ 
char *time_stamp; 
int msgs; /* number of messages */ 
int volm; /* volumn of messages */ 
int distop; /* 1: disable all TOP commmand relative */ 
char buf[1]; 

} GMAIL; 

#include "mhead.h" 

int  gmail_main(GMAIL *gm, Head *head); 
int  gmail_single(GMAIL *gm, Head *head); 
GMAIL *gmail_open(); 
GMAIL *gmail_cmdarg(char *arg); 
void gmail_close(); 
void gmail_host_list(); 
int  gmail_set_action(char *s); 

Spam *spam_match_chain(Slnk *sl, Head *, int); 
Spam *spam_match_size(Slnk *sl, int size); 
int  spam_need_top(Slnk *sl); 
Spam *spam_queue_open(); 
void spam_queue_free(); 

#ifdef DEBUG 
int  spam_test(char *file); 
#endif 

/* see pop3.h */ 

int  pop3_main(GMAIL *gm, Head *head); 


#endif 

[/code:1:bd1926abc9] 
Makefile.in 
[code:1:bd1926abc9] 
#export DEBUG = -g -DDEBUG 
VERSION = -DVERSION=\"0.9.16\" 

PREFIX = @prefix@ 
BINDIR = @prefix@/bin  
MANDIR = @prefix@/man/man1 
CC = @CC@ 
INSTALL = install 
#DEFINES = -DOS_@OS_TYPE@ -DARCH_@ARCH_TYPE@ -D__USE_READLINE__ -DHAVE_CONFIG_H 
DEFINES = -DHAVE_CONFIG_H ${VERSION} 
CFLAGS = @CFLAGS@ -Ilib ${DEBUG} ${DEFINES}  
LDFLAGS = @LDFLAGS@ 
LIBS = -Llib -lsupp @LIBS@ 

OBJMZ = mailz.o mhead.o message.o memo.o mime.o strdate.o @LIBOBJS@ 
OBJPL = main.o mhead.o message.o folder.o smtp.o gmail.o pop3.o mime.o \ 
strdate.o @LIBOBJS@ 

DEBEXE = header strdate 

all: libsupp.a mailz pmail 

libsupp.a: 
(cd lib; make all) 

debug: $(DEBEXE) 

mailz: $(OBJMZ) 
$(CC) $(CFLAGS) -o $@ $(OBJMZ) $(LIBS) 

pmail:  $(OBJPL) 
$(CC) $(CFLAGS) -o $@ $(OBJPL) $(LIBS) 

header: mhead.c  
$(CC) $(CFLAGS) -DEXECUTABLE -o $@ $< $(LIBS) 

strdate: strdate.c 
$(CC) $(CFLAGS) -DEXECUTABLE -o $@ $< $(LIBS) 

install: 
$(INSTALL) -s -o root -g root -m 0755 mailz $(BINDIR) 
$(INSTALL) -s -o root -g root -m 0755 pmail $(BINDIR) 
$(INSTALL) -o root -g root -m 0644 pmail.1 $(MANDIR) 

.PHONY: clean 
clean: 
rm -f *.o mailz pmail $(DEBEXE) core 
(cd lib; make clean) 

folder.o: folder.c defs.h 
getopt.o: getopt.c 
getopt1.o: getopt1.c 
gmail.o: gmail.c defs.h gmail.h 
mailz.o: mailz.c defs.h message.h 
main.o: main.c defs.h 
memo.o: memo.c defs.h  
message.o: message.c message.h defs.h 
mhead.o: mhead.c defs.h 
mime.o: mime.c defs.h 
smtp.o: smtp.c defs.h
strdate.o: strdate.c 
阅读(5574) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~