Back to index

courier  0.68.2
Classes | Defines | Functions | Variables
pop3dserver.c File Reference
#include <sys/types.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <signal.h>
#include <errno.h>
#include "numlib/numlib.h"
#include "maildir/config.h"
#include "maildir/maildirmisc.h"
#include "maildir/maildirquota.h"
#include "maildir/maildirgetquota.h"
#include "maildir/maildircreate.h"
#include "maildir/loginexec.h"
#include "courierauth.h"
#include <unistd.h>

Go to the source code of this file.

Classes

struct  msglist
struct  msglist.uid

Defines

#define dirent   direct
#define NAMLEN(dirent)   (dirent)->d_namlen
#define POP3DLIST   "courierpop3dsizelist"
#define printed(c)
#define printchar(ch)   do { putchar((ch)); printed(1); } while(0);

Functions

void pop3dcapa ()
static void acctout (const char *disc)
static void calcsize (struct msglist *m)
static FILE * openpop3dlist ()
static int cmpmsgs (const void *a, const void *b)
static struct msglist ** readpop3dlist (unsigned long *uid)
static int savepop3dlist (struct msglist **a, size_t cnt, unsigned long uid)
static int scancur ()
static void sortmsgs ()
static void mkupper (char *p)
static void cleanup ()
static void do_stat ()
static unsigned getmsgnum (const char *p)
static void do_list (const char *msgnum)
static void do_retr (unsigned i, unsigned *lptr)
static void print_uidl (unsigned i)
static void do_uidl (const char *msgnum)
static RETSIGTYPE bye (int signum)
static void loop ()
static void purgetmp ()
int main (int argc, char **argv)

Variables

static const char * authaddr
static const char * remoteip
static const char * remoteport
static struct msglistmsglist_l
static struct msglist ** msglist_a
static unsigned msglist_cnt
static struct stat
static int enomem_1msg
static unsigned long top_count = 0
static unsigned long retr_count = 0
static unsigned long bytes_sent_count = 0
static unsigned long bytes_received_count = 0
static unsigned long uidv = 0
static int convert_v0 = 0
static time_t start_time

Class Documentation

struct msglist

Definition at line 66 of file pop3dserver.c.

Collaboration diagram for msglist:
Class Members
char * filename
int isdeleted
int isnew
struct msglist * next
off_t size
struct msglist uid
struct msglist.uid

Definition at line 73 of file pop3dserver.c.

Class Members
unsigned long n
unsigned long uidv

Define Documentation

#define dirent   direct

Definition at line 15 of file pop3dserver.c.

#define NAMLEN (   dirent)    (dirent)->d_namlen

Definition at line 16 of file pop3dserver.c.

#define POP3DLIST   "courierpop3dsizelist"

Definition at line 59 of file pop3dserver.c.

#define printchar (   ch)    do { putchar((ch)); printed(1); } while(0);

Definition at line 596 of file pop3dserver.c.

#define printed (   c)
Value:
do {int cnt=(c); if (cnt > 0)                    \
                                      bytes_sent_count += cnt; \
       } while(0)

Definition at line 592 of file pop3dserver.c.


Function Documentation

static void acctout ( const char *  disc) [static]

Definition at line 815 of file pop3dserver.c.

{
       static const char msg2[]=", user=";
       static const char msg3[]=", ip=[";
       static const char msgport[]="], port=[";
       static const char msg4[]="], top=";
       static const char msg5[]=", retr=";
       static const char msg6[]=", time=";
       static const char msg7[]=", stls=1";
       static const char msgAR[]=", rcvd=";
       static const char msgAS[]=", sent=";

       char num1[NUMBUFSIZE];
       char num2[NUMBUFSIZE];
       char num3[NUMBUFSIZE];
       char numAR[NUMBUFSIZE];
       char numAS[NUMBUFSIZE];

       char *p;
       const char *q;

       libmail_str_size_t(top_count, num1);
       libmail_str_size_t(retr_count, num2);
       libmail_str_time_t(time(NULL)-start_time, num3);
       libmail_str_size_t(bytes_received_count, numAR);
       libmail_str_size_t(bytes_sent_count, numAS);

       p=malloc(strlen(authaddr)+strlen(remoteip)+strlen(remoteport)+strlen(disc)+
               strlen(num1)+strlen(num2)+strlen(num3)+
               strlen(numAR)+strlen(numAS)+200); /* Should be enough */

       strcpy(p, disc);
       strcat(p, msg2);
       strcat(p, authaddr);
       strcat(p, msg3);
       strcat(p, remoteip);
       strcat(p, msgport);
       strcat(p, remoteport);
       strcat(p, msg4);
       strcat(p, num1);
       strcat(p, msg5);
       strcat(p, num2);
       strcat(p, msgAR);
       strcat(p, numAR);
       strcat(p, msgAS);
       strcat(p, numAS);
       strcat(p, msg6);
       strcat(p, num3);

       if ((q=getenv("POP3_TLS")) && atoi(q))
              strcat(p, msg7);

       strcat(p, "\n");
       if (write(2, p, strlen(p)) < 0)
              ; /* make gcc shut up */
       free(p);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static RETSIGTYPE bye ( int  signum) [static]

Definition at line 873 of file pop3dserver.c.

{
       acctout("INFO: TIMEOUT");
       exit(0);
#if    RETSIGTYPE != void
       return (0);
#endif
}

Here is the call graph for this function:

static void calcsize ( struct msglist m) [static]

Definition at line 121 of file pop3dserver.c.

{
FILE   *f=fopen(m->filename, "r");
int    c, lastc;

       m->size=0;
       if (f == 0)
       {
              perror("calcsize fopen");
              return;
       }
       lastc='\n';
       while ((c=getc(f)) >= 0)
       {
              if (c == '\n')       ++m->size;
              ++m->size;
              lastc=c;
       }
       if (lastc != '\n')   m->size += 2;

       if (ferror(f))
       {
              perror("calcsize ferror");
              return;
       }
       fclose(f);
}

Here is the caller graph for this function:

static void cleanup ( ) [static]

Definition at line 543 of file pop3dserver.c.

{
       unsigned i;
       const char *cp=getenv("POP3_LOG_DELETIONS");
       int log_deletions= cp && *cp != '0';

       int64_t deleted_bytes=0;
       int64_t deleted_messages=0;

       for (i=0; i<msglist_cnt; i++)
              if (msglist_a[i]->isdeleted)
              {
                     unsigned long un=0;

                     const char *filename=msglist_a[i]->filename;

                     if (maildirquota_countfile(filename))
                     {
                            if (maildir_parsequota(filename, &un))
                            {
                                   struct stat stat_buf;

                                   if (stat(filename, &stat_buf) == 0)
                                          un=stat_buf.st_size;
                            }
                     }

                     if (log_deletions)
                            fprintf(stderr, "INFO: DELETED, user=%s, ip=[%s], filename=%s\n",
                                   getenv("AUTHENTICATED"),
                                   getenv("TCPREMOTEIP"),
                                   msglist_a[i]->filename);

                     if (unlink(msglist_a[i]->filename))
                            un=0;

                     if (un)
                     {
                            deleted_bytes -= un;
                            deleted_messages -= 1;
                     }
              }

       if (deleted_messages < 0)
              maildir_quota_deleted(".", deleted_bytes, deleted_messages);

       return;
}

Here is the call graph for this function:

static int cmpmsgs ( const void *  a,
const void *  b 
) [static]

Definition at line 397 of file pop3dserver.c.

{
       const char *aname=(*(struct msglist **)a)->filename;
       const char *bname=(*(struct msglist **)b)->filename;
       const char *ap=strrchr(aname, '/');
       const char *bp=strrchr(bname, '/');
       long   na, nb;

       if (ap)
              ++ap;
       else
              ap=aname;

       if (bp)
              ++bp;
       else
              bp=bname;
 
       na=atol(ap);
       nb=atol(bp);

       if (na < nb)  return (-1);
       if (na > nb)  return (1);

       while (*ap || *bp)
       {
              if (*ap == MDIRSEP[0] && *bp == MDIRSEP[0])
                     break;

              if (*ap < *bp)
                     return -1;
              if (*ap > *bp)
                     return 1;
              ++ap;
              ++bp;
       }

       return 0;
}

Here is the caller graph for this function:

static void do_list ( const char *  msgnum) [static]

Definition at line 634 of file pop3dserver.c.

{
unsigned i;
char   buf[NUMBUFSIZE];

       if (msgnum)
       {
              if ((i=getmsgnum(msgnum)) != 0)
              {
                     printed(printf("+OK %u %s\r\n", i,
                                   libmail_str_off_t(msglist_a[i-1]->size,
                                                  buf)));
                     fflush(stdout);
              }
              return;
       }

       printed(printf("+OK POP3 clients that break here, they violate STD53.\r\n"));
       for (i=0; i<msglist_cnt; i++)
       {
              if (msglist_a[i]->isdeleted)       continue;
              printed(printf("%u %s\r\n", i+1, libmail_str_off_t(msglist_a[i]->size, buf)));
       }
       printed(printf(".\r\n"));
       fflush(stdout);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void do_retr ( unsigned  i,
unsigned *  lptr 
) [static]

Definition at line 663 of file pop3dserver.c.

{
FILE   *f=fopen(msglist_a[i]->filename, "r");
char   *p;
int    c, lastc='\n';
int    inheader=1;
char   buf[NUMBUFSIZE];
unsigned long *cntr;

       if (!f)
       {
              printed(printf("-ERR Can't open the message file - it's gone!\r\n"));
              fflush(stdout);
              return;
       }
       printed(printf( (lptr ? "+OK headers follow.\r\n":"+OK %s octets follow.\r\n"),
                     libmail_str_off_t(msglist_a[i]->size, buf)));

       cntr= &retr_count;
       if (lptr)
              cntr= &top_count;

       for (lastc=0; (c=getc(f)) >= 0; lastc=c)
       {
              if (lastc == '\n')
              {
                     if (lptr)
                     {
                            if (inheader)
                            {
                                   if (c == '\n')       inheader=0;
                            }
                            else if ( (*lptr)-- == 0)   break;
                     }

                     if (c == '.')
                            printchar('.');
              }
              if (c == '\n')       printchar('\r');
              printchar(c);
              ++*cntr;
       }
       if (ferror(f)) {
              /* Oops! All we can do is drop the connection */
              fprintf(stderr, "ERR: I/O error while reading message file %s: %s\n",
                     msglist_a[i]->filename, strerror(errno));
              acctout("INFO: I/O error disconnect");
              exit(1);
       }
       if (lastc != '\n')   printed(printf("\r\n"));
       printed(printf(".\r\n"));
       fflush(stdout);
       fclose(f);
       if (lptr)     return;

       if ((p=strchr(msglist_a[i]->filename, MDIRSEP[0])) != 0 &&
              (p[1] != '2' || p[2] != ',' || strchr(p, 'S') != 0))
              return;

       if ((p=malloc(strlen(msglist_a[i]->filename)+5)) == 0)
              return;

       strcpy(p, msglist_a[i]->filename);
       if (strchr(p, MDIRSEP[0]) == 0)    strcat(p, MDIRSEP "2,");
       strcat(p, "S");

       if (lptr      /* Don't mark as seen for TOP */
           || rename(msglist_a[i]->filename, p))
       {
              free(p);
              return;
       }
       free(msglist_a[i]->filename);
       msglist_a[i]->filename=p;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void do_stat ( ) [static]

Definition at line 600 of file pop3dserver.c.

{
off_t  n=0;
unsigned i, j;
char   buf[NUMBUFSIZE];

       j=0;
       for (i=0; i<msglist_cnt; i++)
       {
              if (msglist_a[i]->isdeleted)       continue;
              n += msglist_a[i]->size;
              ++j;
       }

       printed(printf("+OK %u %s\r\n", j, libmail_str_off_t(n, buf)));
       fflush(stdout);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void do_uidl ( const char *  msgnum) [static]

Definition at line 790 of file pop3dserver.c.

{
unsigned i;

       if (msgnum)
       {
              if ((i=getmsgnum(msgnum)) != 0)
              {
                     printed(printf("+OK %u ", i));
                     print_uidl(i-1);
                     fflush(stdout);
              }
              return;
       }
       printed(printf("+OK\r\n"));
       for (i=0; i<msglist_cnt; i++)
       {
              if (msglist_a[i]->isdeleted)       continue;
              printed(printf("%u ", i+1));
              print_uidl(i);
       }
       printed(printf(".\r\n"));
       fflush(stdout);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static unsigned getmsgnum ( const char *  p) [static]

Definition at line 618 of file pop3dserver.c.

{
unsigned i;

       if (!p || (i=atoi(p)) > msglist_cnt || i == 0 ||
              msglist_a[i-1]->isdeleted)
       {
              printed(printf("-ERR Invalid message number.\r\n"));
              fflush(stdout);
              return (0);
       }
       return (i);
}

Here is the caller graph for this function:

static void loop ( ) [static]

Definition at line 882 of file pop3dserver.c.

{
char   buf[BUFSIZ];
char   *p;
int    c;

       signal(SIGALRM, bye);
       while (alarm(300), fgets(buf, sizeof(buf), stdin))
       {
              bytes_received_count += strlen(buf);

              alarm(0);
              if ((p=strchr(buf, '\n')) != 0)
                     *p=0;
              else while ((c=getc(stdin)) >= 0 && c != '\n')
                     ;
              p=strtok(buf, " \t\r");
              if (!p)       p="";

              mkupper(p);
              if (strcmp(p, "QUIT") == 0)
              {
                     printed(printf("+OK Bye-bye.\r\n"));
                     fflush(stdout);
                     cleanup();
                     acctout("INFO: LOGOUT");
                     return;
              }

              if (strcmp(p, "STAT") == 0)
              {
                     do_stat();
                     continue;
              }

              if (strcmp(p, "LIST") == 0)
              {
                     do_list(strtok(NULL, " \t\r"));
                     continue;
              }

              if (strcmp(p, "RETR") == 0)
              {
              unsigned      i;

                     if ((i=getmsgnum(strtok(NULL, " \t\r"))) == 0)
                            continue;

                     do_retr(i-1, 0);
                     continue;
              }

              if (strcmp(p, "CAPA") == 0)
              {
                     pop3dcapa();
                     continue;
              }

              if (strcmp(p, "DELE") == 0)
              {
              unsigned      i;

                     if ((i=getmsgnum(strtok(NULL, " \t\r"))) == 0)
                            continue;

                     msglist_a[i-1]->isdeleted=1;
                     printed(printf("+OK Deleted.\r\n"));
                     fflush(stdout);
                     continue;
              }

              if (strcmp(p, "NOOP") == 0)
              {
                     printed(printf("+OK Yup.\r\n"));
                     fflush(stdout);
                     continue;
              }

              if (strcmp(p, "RSET") == 0)
              {
              unsigned i;

                     for (i=0; i<msglist_cnt; i++)
                            msglist_a[i]->isdeleted=0;
                     printed(printf("+OK Resurrected.\r\n"));
                     fflush(stdout);
                     continue;
              }

              if (strcmp(p, "TOP") == 0)
              {
              unsigned      i, j;
              const  char *q;

                     if ((i=getmsgnum(strtok(NULL, " \t\r"))) == 0)
                            continue;

                     q=strtok(NULL, " \t\r");

                     if (!q)       goto error;

                     j=atoi(q);
                     do_retr(i-1, &j);
                     continue;
              }

              if (strcmp(p, "UIDL") == 0)
              {
                     do_uidl(strtok(NULL, " \t\r"));
                     continue;
              }

error:
              printed(printf("-ERR Invalid command.\r\n"));
              fflush(stdout);
       }
       acctout("INFO: DISCONNECTED");
}

Here is the call graph for this function:

Here is the caller graph for this function:

int main ( int  argc,
char **  argv 
)

Definition at line 1031 of file pop3dserver.c.

{
char   *p;

#ifdef HAVE_SETVBUF_IOLBF
       setvbuf(stderr, NULL, _IOLBF, BUFSIZ);
#endif
       time(&start_time);

       if ((authaddr=getenv("AUTHADDR")) == NULL ||
           *authaddr == 0)
       {
              authaddr=getenv("AUTHENTICATED");
              if (authaddr == NULL || *authaddr == 0)
                     authaddr="nobody";
       }

       if ((remoteip=getenv("TCPREMOTEIP")) == NULL)
              remoteip="127.0.0.1";

       if ((remoteport=getenv("TCPREMOTEPORT")) == NULL)
              remoteport="0";

       {
       struct stat   buf;

              if ( stat(".", &buf) < 0 || buf.st_mode & S_ISVTX)
              {
                     fprintf(stderr, "INFO: LOCKED, user=%s, ip=[%s], port=[%s]\n",
                                                 authaddr, remoteip, remoteport);
                     printed(printf("-ERR Your account is temporarily unavailable (+t bit set on home directory).\r\n"));
                     exit(0);
              }
       }

       if (argc > 1)
              p=argv[1];
       else
              p=getenv("MAILDIR");

       if (!p)
              p="./Maildir";

       if (chdir(p))
       {
              fprintf(stderr, "chdir %s: %s\n", p, strerror(errno));
              printed(printf("-ERR chdir %s failed\n", p));
              fflush(stdout);
              exit(1);
       }
       
       maildir_loginexec();

       if (auth_getoptionenvint("disablepop3"))
       {
              printed(printf("-ERR POP3 access disabled for this account.\r\n"));
              fflush(stdout);
              exit(1);
       }

       if (    auth_getoptionenvint("disableinsecurepop3")
           && ((p=getenv("POP3_TLS")) == NULL || !atoi(p)))
       {
              printed(printf("-ERR POP3 access disabled via insecure connection.\r\n"));
              fflush(stdout);
              exit(1);
       }

       fprintf(stderr, "INFO: LOGIN, user=%s, ip=[%s], port=[%s]\n",
                     authaddr,
                                   remoteip,
                                   remoteport);
       fflush(stderr);

       msglist_cnt=0;
       msglist_l=0;
       msglist_a=0;
       purgetmp();
       maildir_getnew(".", INBOX, NULL, NULL);
       if (scancur())
       {
              printed(printf("-ERR Maildir invalid (no 'cur' directory)\r\n"));
              return (0);
       }
       sortmsgs();
       printed(printf("+OK logged in.\r\n"));
       fflush(stdout);
       loop();
       return (0);
}

Here is the call graph for this function:

static void mkupper ( char *  p) [static]

Definition at line 534 of file pop3dserver.c.

{
       while (*p)
       {
              *p=toupper(*p);
              p++;
       }
}

Here is the caller graph for this function:

static FILE* openpop3dlist ( ) [static]

Definition at line 150 of file pop3dserver.c.

{
       int tries;
       FILE *fp;

       tries = 0;
       do {
              fp = fopen(POP3DLIST, "r");
              if (fp != NULL)
                     return (fp);
              if (errno != ESTALE) {
                     if (errno != ENOENT)
                            perror("failed to open " POP3DLIST " file");
                     return (NULL);
              }
              ++tries;
       } while (tries < 3); /* somewhat arbitrary */
       fprintf(stderr, "failed to open pop3dlist file after retries\n");
       return NULL;
}

Here is the caller graph for this function:

void pop3dcapa ( )

Definition at line 57 of file pop3dcapa.c.

{
       const char *p;
       const char *external=pop3_externalauth();

       printf("+OK Here's what I can do:\r\n");

       if ((p=getenv("POP3_TLS")) != 0 && atoi(p) &&
           (p=getenv("POP3AUTH_TLS")) != 0 && *p)
              ;
       else
              p=getenv("POP3AUTH");

       if ((p && *p) || external)
       {
              if (!p)
                     p="";

              if (!external)
                     external="";

              printf("SASL %s%s%s\r\n", p, *p && *external ? " ":"",
                     *external ? "EXTERNAL":"");
       }
              
       if (have_starttls())
              printf("STLS\r\n");

       printf("TOP\r\nUSER\r\nLOGIN-DELAY 10\r\nPIPELINING\r\nUIDL\r\nIMPLEMENTATION Courier Mail Server\r\n.\r\n");
       fflush(stdout);
}
static void print_uidl ( unsigned  i) [static]

Definition at line 743 of file pop3dserver.c.

{
       const char *p;

       if (enomem_1msg)
              /* Error recovery - out of disk space, see comments
              ** at the beginning of this file.
              */
       {
              char dev_buf[NUMBUFSIZE];
              char ino_buf[NUMBUFSIZE];
              char mtime_buf[NUMBUFSIZE];

              printed(printf("ENOMEM-%s-%s-%s\r\n",
                            libmail_strh_time_t(enomem_stat.st_mtime, mtime_buf),
                            libmail_strh_dev_t(enomem_stat.st_dev, dev_buf),
                            libmail_strh_ino_t(enomem_stat.st_ino, ino_buf))
                     );
              return;
       }

       if (msglist_a[i]->uid.n != 0)
       {
              /* VERSION 1 and VERSION 2 UIDL */

              printed(printf((msglist_a[i]->uid.uidv ?
                            "UID%lu-%lu\r\n":"UID%lu\r\n"),
                            msglist_a[i]->uid.n, msglist_a[i]->uid.uidv));
              return;
       }

       /* VERSION 0 UIDL */

       p=strchr(msglist_a[i]->filename, '/')+1;

       while (*p && *p != MDIRSEP[0])
       {
              if (*p < 0x21 || *p > 0x7E || *p == '\'' || *p == '"' ||
                     *p == '+')
                     printed(printf("+%02X", (int)(unsigned char)*p));
              else
                     printchar(*p);
              ++p;
       }
       printed(printf("\r\n"));
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void purgetmp ( ) [static]

Definition at line 1003 of file pop3dserver.c.

{
DIR    *p=opendir("tmp");
time_t t;
struct dirent *de;
struct stat   stat_buf;
char   *n;

       if (!p)       return;
       time (&t);
       t -= 48L * 60L * 60L;

       while ((de=readdir(p)) != 0)
       {
              if (de->d_name[0] == '.')   continue;
              n=malloc(strlen(de->d_name)+5);
              if (!n)       continue;
              strcat(strcpy(n, "tmp/"), de->d_name);
              if (stat(n, &stat_buf) == 0 && stat_buf.st_mtime < t)
                     unlink(n);
              free(n);
       }
       closedir(p);
}

Here is the caller graph for this function:

static struct msglist** readpop3dlist ( unsigned long *  uid) [static, read]

Definition at line 177 of file pop3dserver.c.

{
       struct msglist **a;
       struct msglist *list=NULL;
       size_t mcnt=0;

       char linebuf[1024];

       FILE *fp=openpop3dlist();

       size_t i;
       int vernum=0;

       uidv=time(NULL);

       convert_v0=0;

       if (fp == NULL ||
           fgets(linebuf, sizeof(linebuf)-1, fp) == NULL ||
           linebuf[0] != '/' || sscanf(linebuf+1, "%d %lu %lu", &vernum,
                                   uid, &uidv)
           < 2 || (vernum != 1 && vernum != 2))
       {
              if (fp == NULL)
                     convert_v0=1;

              if (vernum == 0 && fp && fseek(fp, 0L, SEEK_SET) >= 0)
              {
                     /* Old version 0 format courierpop3dsizelist file */
              }
              else
              {
                     if (fp)
                            fclose(fp);
                     fp=NULL;
              }
       }

       if (fp)
       {
              struct msglist *m;

              char *p, *q;

              size_t n=0;
              int ch;

              while ((ch=getc(fp)) != EOF)
              {
                     unsigned long sz;

                     if (ch != '\n')
                     {
                            if (n < sizeof(linebuf)-3)
                                   linebuf[n++]=ch;
                            continue;
                     }
                     linebuf[n]=0;
                     n=0;

                     if (vernum == 0)
                            strcat(linebuf, " 0");
                     /* Convert version 0 to version 1 format - PRESTO! */

                     if ((p=strrchr(linebuf, ' ')) == NULL)
                            continue;
                     *p=0;
                     if ((q=strrchr(linebuf, ' ')) == NULL)
                            continue;
                     *p=' ';
                     p=q;
                     *p++=0;

                     if (linebuf[0] == 0)
                            continue;

                     if ((m=(struct msglist *)malloc(sizeof(struct
                                                        msglist))) == 0)
                     {
                            perror("malloc");
                            exit(1);
                     }

                     if ((m->filename=strdup(linebuf)) == NULL)
                     {
                            perror("malloc");
                            exit(1);
                     }

                     switch (sscanf(p, "%lu %lu:%lu", &sz,
                                   &m->uid.n, &m->uid.uidv)) {
                     case 2:
                            m->uid.uidv=0;
                            /* FALLTHROUGH */
                     case 3:
                            m->size=sz;
                            m->next=list;
                            list=m;
                            ++mcnt;
                            break;
                     default:
                            free(m->filename);
                            free(m);
                     }
              }
              fclose(fp);
       }
       if ((a=(struct msglist **)malloc((mcnt+1)
                                    *sizeof(struct msglist *))) == 0)
       {
              perror("malloc");
              exit(1);
       }

       for (i=0; list; list=list->next)
              a[i++]=list;

       a[i]=NULL;
       qsort(a, i, sizeof(*a), cmpmsgs);

       return a;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int savepop3dlist ( struct msglist **  a,
size_t  cnt,
unsigned long  uid 
) [static]

Definition at line 300 of file pop3dserver.c.

{
       FILE *fp;
       size_t i;

       struct maildir_tmpcreate_info createInfo;

       maildir_tmpcreate_init(&createInfo);

       createInfo.uniq="pop3";
       createInfo.doordie=1;

       if ((fp=maildir_tmpcreate_fp(&createInfo)) == NULL)
       {
              maildir_tmpcreate_free(&createInfo);
              return -1;
       }

       fprintf(fp, "/2 %lu %lu\n", uid, uidv);

       for (i=0; i<cnt; i++)
       {
              char *p=a[i]->filename;
              char *q;

              if ((q=strrchr(p, '/')) != NULL)
                     p=q+1;

              fprintf(fp, "%s %lu %lu:%lu\n", p, (unsigned long)a[i]->size,
                     a[i]->uid.n, a[i]->uid.uidv);
       }

       if (fflush(fp) || ferror(fp))
       {
              fclose(fp);
              unlink(createInfo.tmpname);
              maildir_tmpcreate_free(&createInfo);
              return -1;
       }

       if (fclose(fp) ||
           rename(createInfo.tmpname, POP3DLIST) < 0)
       {
              unlink(createInfo.tmpname);
              maildir_tmpcreate_free(&createInfo);
              return -1;
       }

       maildir_tmpcreate_free(&createInfo);
       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int scancur ( ) [static]

Definition at line 355 of file pop3dserver.c.

{
DIR    *dirp;
struct dirent *de;
struct msglist *m;

       if ((dirp=opendir("cur")) == 0)
       {
              perror("scancur opendir(\"cur\")");
              return 1;
       }

       while ((de=readdir(dirp)) != 0)
       {
              if ( de->d_name[0] == '.' ) continue;

              if ((m=(struct msglist *)malloc(sizeof(struct msglist))) == 0)
              {
                     perror("malloc");
                     exit(1);
              }
              if ((m->filename=(char *)malloc(strlen(de->d_name)+5)) == 0)
              {
                     free( (char *)m);
                     perror("malloc");
                     exit(1);
              }
              strcat(strcpy(m->filename, "cur/"), de->d_name);
              m->isdeleted=0;
              m->next=msglist_l;
              msglist_l=m;
              msglist_cnt++;
       }
       closedir(dirp);
       return 0;
}

Here is the caller graph for this function:

static void sortmsgs ( ) [static]

Definition at line 437 of file pop3dserver.c.

{
       size_t i, n;
       struct msglist *m;
       struct msglist **prev_list;
       int savesizes=0;

       unsigned long nextuid;

       if (msglist_cnt == 0)       return;

       if ((msglist_a=(struct msglist **)malloc(
                     msglist_cnt*sizeof(struct msglist *))) == 0)
       {
              perror("malloc");
              msglist_cnt=0;
              return;
       }

       for (i=0, m=msglist_l; m; m=m->next, i++)
       {
              m->isnew=0;
              msglist_a[i]=m;
       }
       qsort(msglist_a, msglist_cnt, sizeof(*msglist_a), cmpmsgs);

       nextuid=1;

       prev_list=readpop3dlist(&nextuid);

       n=0;

       for (i=0; i<msglist_cnt; i++)
       {
              while (prev_list[n] &&
                     cmpmsgs(&prev_list[n], &msglist_a[i]) < 0)
              {
                     ++n;
                     savesizes=1;
              }

              if (prev_list[n] &&
                  cmpmsgs(&prev_list[n], &msglist_a[i]) == 0)
              {
                     msglist_a[i]->size=prev_list[n]->size;
                     msglist_a[i]->uid=prev_list[n]->uid;
                     n++;
              }
              else
              {
                     msglist_a[i]->uid.n=nextuid++;
                     msglist_a[i]->uid.uidv=uidv;
                     msglist_a[i]->isnew=1;
                     if (convert_v0)
                            msglist_a[i]->uid.n=0;

                     calcsize(msglist_a[i]);
                     savesizes=1;
              }      
       }

       if (prev_list[n])
              savesizes=1;

       for (i=0; prev_list[i]; i++)
       {
              free(prev_list[i]->filename);
              free(prev_list[i]);
       }

       free(prev_list);

       if (savesizes && savepop3dlist(msglist_a, msglist_cnt, nextuid) < 0)
       {
              fprintf(stderr, "ERR: Error while saving courierpop3dsizelist"
                     ", user=%s\n", authaddr);

              for (i=n=0; i<msglist_cnt; i++)
              {
                     if (msglist_a[i]->isnew)
                            continue;

                     msglist_a[n]=msglist_a[i];
                     ++n;
              }

              if (n == 0 && n < msglist_cnt &&
                  stat(msglist_a[0]->filename, &enomem_stat) == 0)
              {
                     enomem_1msg=1;
                     ++n;
              }
              msglist_cnt=n;

       }
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

const char* authaddr [static]

Definition at line 64 of file pop3dserver.c.

unsigned long bytes_received_count = 0 [static]

Definition at line 109 of file pop3dserver.c.

unsigned long bytes_sent_count = 0 [static]

Definition at line 108 of file pop3dserver.c.

int convert_v0 = 0 [static]

Definition at line 112 of file pop3dserver.c.

int enomem_1msg [static]

Definition at line 84 of file pop3dserver.c.

struct msglist** msglist_a [static]

Definition at line 80 of file pop3dserver.c.

unsigned msglist_cnt [static]

Definition at line 81 of file pop3dserver.c.

struct msglist* msglist_l [static]

Definition at line 79 of file pop3dserver.c.

const char * remoteip [static]

Definition at line 64 of file pop3dserver.c.

const char * remoteport [static]

Definition at line 64 of file pop3dserver.c.

unsigned long retr_count = 0 [static]

Definition at line 106 of file pop3dserver.c.

time_t start_time [static]

Definition at line 114 of file pop3dserver.c.

struct stat [static]

Definition at line 83 of file pop3dserver.c.

unsigned long top_count = 0 [static]

Definition at line 105 of file pop3dserver.c.

unsigned long uidv = 0 [static]

Definition at line 111 of file pop3dserver.c.