Linux 版 (精华区)

发信人: netiscpu (说不如做), 信区: Unix
标  题: FireBirdBBS(2.5) pop3d (tested AIX/SUN/Linux)
发信站: 紫 丁 香 (Fri Jul 17 08:20:34 1998), 转信


发信人: Leeward (X 14% completed), 信区: Linux
标  题: FireBirdBBS(2.5) pop3d (tested AIX/SUN/Linux)
发信站: BBS 水木清华站 (Sun Jun 14 16:25:00 1998)

补充说明:该程序启动成功后,自动脱离终端,以守护进程方式运行。

/* Leeward: usage: bbspop3d [port]
   Note: 
         1. If no port given, I use 110 (in fact, using macro POP3PORT)
         2. If atoi(port) returns zero, I use 110  (the same as above)
         3. Using port 110 needs starting by root 
            If started by bbsroot, try port over 1023
         4. Three macros defined below: BBSHOME, POP3PORT and BBSNAME
            You may need modify these three macros to fit your BBS settings
         5. I added codes to support two functions: 
            (1) Top // extended POP3 function
            (2) nextwordX // enable passwords including space character(s)
         6. While making bbspop3d, you might encounter linker errors
            Try to pass the linker some libraries 
            (For example: link under SUNOS, you may need add -lnsl and -lsocket)
         7. bbspop3d.c is put in the same directory as bbs.h
         8. Client settings:
            (1) pop3 server  : Your BBS server
            (2) pop3 port    : 110(POP3PORT) or the argv[1] while starting pop3d
            (3) pop3 account : BBSID.bbs (For example: mine is "Leeward.bbs")
            (4) pop3 password: The same as the client's BBSID's password
  Last modified: 98.06.14 
*/
         
#include <sys/ioctl.h>
#include "bbs.h"

#include <sys/wait.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <netdb.h>

#include <sys/time.h>
#include <sys/stat.h>

#define BBSUID 9999
#define BBSGID 99
#define BUFSIZE         1024
#define BBSHOME "/home0/bbs"
#define BBSNAME ".bbs@bbs.net.tsinghua.edu.cn"
#define POP3PORT 110

struct fileheader currentmail;
struct userec currentuser;

char LowUserid[20];
char genbuf[BUFSIZE];

#define QLEN            5

#define S_CONNECT       1
#define S_LOGIN         2


#define STRN_CPY(d,s,l) { strncpy((d),(s),(l)); (d)[(l)-1] = 0; }
#define ANY_PORT        0
#define RFC931_PORT     113
#define RFC931_TIMEOUT         5
/*#define POP3_TIMEOUT         60*/
/* Leeward 98.05.06 Increases TIMEOUT value for slow modem users */
#define POP3_TIMEOUT         180

static jmp_buf timebuf;

int     State;
int     msock,sock;    /* master server socket */
static int reaper();
char    fromhost[ STRLEN ];
char    inbuf[ BUFSIZE ];
char    remote_userid[ STRLEN ];
FILE    *cfp;
char    *msg,*cmd;
int     fd;
struct  fileheader *fcache;
int     totalnum, totalbyte, markdel, idletime;
int     *postlen;

void    log_usies();
int     Quit(), User(), Pass(), Noop(), Stat(), List(), Retr(), Rset();
int     Last(), Dele(), Uidl();
int     Top(); /* Leeward adds, 98.01.21 */

struct commandlist {
    char        *name;
    int         (*fptr)();
} cmdlists[] = {
        "retr",       Retr,
        "dele",       Dele,
        "user",       User,
        "pass",       Pass,
        "stat",       Stat,
        "list",       List,
        "uidl",       Uidl,
        "quit",       Quit,
        "rset",       Rset,
        "last",       Last,
        "noop",       Noop,
        "top",        Top,  /* Leeward adds, 98.01.21 */
        NULL,         NULL
};

char *crypt();

int
checkpasswd(passwd, test)
char *passwd, *test;
{
    static char pwbuf[14];
    char *pw;
        
    strncpy(pwbuf, test, 14);
    pw = crypt(pwbuf, passwd);  
    return (!strcmp(pw, passwd));
}

static int
abort_server()
{
    log_usies("ABORT SERVER");
    close(msock);
    close(sock);
    exit(1);
}

int dokill()
{
   kill(0,SIGKILL);
}

static FILE *fsocket(domain, type, protocol)
int     domain;
int     type;  
int     protocol;
{
    int     s;
    FILE   *fp;
        
    if ((s = socket(domain, type, protocol)) < 0) {
      return (0);
    } else {
      if ((fp = fdopen(s, "r+")) == 0) {
        close(s);
      }
      return (fp);
    }
}

void
outs(str)
char *str;
{
  char sendbuf[BUFSIZE];

  (void)bzero(sendbuf, sizeof(sendbuf));
  (void)sprintf(sendbuf, "%s\r\n", str);
  (void)write(sock, sendbuf, strlen(sendbuf));
}

void
outfile(filename, linenum)
char *filename;
int linenum;
{
     FILE *fp;
     char linebuf[ 256 ];
     
     if (linenum && (fp = fopen(filename,"r")) != NULL) {
       while ( fgets( linebuf, 256, fp )!=NULL && linenum > 0) {
         linebuf[ strlen(linebuf)-1 ] = '\0';
         if (strcmp( linebuf, ".")==0) outs("..");
         else outs(linebuf);
         linenum--;
       }
       fclose(fp);
     }
     outs(".");
}


/* timeout - handle timeouts */
static void timeout(sig)
int     sig;
{
    longjmp(timebuf, sig);
}


void    rfc931(rmt_sin, our_sin, dest)
struct sockaddr_in *rmt_sin;
struct sockaddr_in *our_sin;
char   *dest;
{
    unsigned rmt_port;
    unsigned our_port;
    struct sockaddr_in rmt_query_sin;
    struct sockaddr_in our_query_sin;
    char    user[256];
    char    buffer[512];
    char   *cp;
    FILE   *fp;
    char   *result = "unknown";
    struct hostent *hp;

    /*
     * Use one unbuffered stdio stream for writing to and for reading from
     * the RFC931 etc. server. This is done because of a bug in the SunOS 
     * 4.1.x stdio library. The bug may live in other stdio implementations,
     * too. When we use a single, buffered, bidirectional stdio stream ("r+"
     * or "w+" mode) we read our own output. Such behaviour would make sense
     * with resources that support random-access operations, but not with   
     * sockets.
     */
    if ((fp = fsocket(AF_INET, SOCK_STREAM, 0)) != 0) {
        setbuf(fp, (char *) 0);
        
        /*
         * Set up a timer so we won't get stuck while waiting for the server.
         */

        if (setjmp(timebuf) == 0) {
            signal(SIGALRM, timeout);
            alarm(RFC931_TIMEOUT);

            /*
             * Bind the local and remote ends of the query socket to the same
             * IP addresses as the connection under investigation. We go
             * through all this trouble because the local or remote system
             * might have more than one network address. The RFC931 etc.  
             * client sends only port numbers; the server takes the IP    
             * addresses from the query socket.
             */
                                                                                                       
            our_query_sin = *our_sin;
            our_query_sin.sin_port = htons(ANY_PORT);
            rmt_query_sin = *rmt_sin;
            rmt_query_sin.sin_port = htons(RFC931_PORT);

            if (bind(fileno(fp), (struct sockaddr *) & our_query_sin,
                     sizeof(our_query_sin)) >= 0 &&
                connect(fileno(fp), (struct sockaddr *) & rmt_query_sin,
                        sizeof(rmt_query_sin)) >= 0) {

                /*
                 * Send query to server. Neglect the risk that a 13-byte
                 * write would have to be fragmented by the local system and
                 * cause trouble with buggy System V stdio libraries.
                 */

                fprintf(fp, "%u,%u\r\n",
                        ntohs(rmt_sin->sin_port),
                        ntohs(our_sin->sin_port));
                fflush(fp);

                /*
                 * Read response from server. Use fgets()/sscanf() so we can
                 * work around System V stdio libraries that incorrectly
                 * assume EOF when a read from a socket returns less than
                 * requested.
                 */

                if (fgets(buffer, sizeof(buffer), fp) != 0
                    && ferror(fp) == 0 && feof(fp) == 0
                    && sscanf(buffer, "%u , %u : USERID :%*[^:]:%255s",
                              &rmt_port, &our_port, user) == 3
                    && ntohs(rmt_sin->sin_port) == rmt_port   
                    && ntohs(our_sin->sin_port) == our_port) {

                    /*
                     * Strip trailing carriage return. It is part of the
                     * protocol, not part of the data.
                     */

                    if (cp = strchr(user, '\r'))
                        *cp = 0;  
                    result = user;
                }
            }
            alarm(0);
        }
        fclose(fp);
    }
    STRN_CPY(dest, result, 60);

    if (strcmp(dest,"unknown")==0) strcpy(dest,"");
    else strcat( dest, "@" );

    hp = gethostbyaddr((char *) &rmt_sin->sin_addr, sizeof (struct in_addr),
            rmt_sin->sin_family);
    if (hp)
            strcat(dest, hp->h_name);
    else
            strcat(dest, (char *)inet_ntoa(rmt_sin->sin_addr));
                                                                        
}

int
Isspace(ch)
char ch;   
{
    return (ch == ' ' || ch =='\t' || ch == 10 || ch == 13);
}
    
char *
nextwordlower(str)
char **str;
{
    char *p;

    while (Isspace(**str))
      (*str)++;
    p = (*str);

    while (**str && !Isspace(**str)) {
      **str = tolower(**str);
      (*str)++;
    }

    if (**str) {
      **str = '\0';
      (*str)++;
    }
    return p;
}

char *
nextword(str)
char **str;
{
    char *p;

    while (Isspace(**str))
      (*str)++;
    p = (*str);

    while (**str && !Isspace(**str))
      (*str)++;

    if (**str) {
      **str = '\0';
      (*str)++;
    }
    return p;
}

char *
nextwordX(str) /* Leeward: 97.12.27: enable password include space(s) */  
char **str;
{
    char *p;

    while (Isspace(**str))
      (*str)++;
    p = (*str);

    while (**str && '\t' != **str && 10 != **str && 13 != **str)
      (*str)++;

    if (**str) {
      **str = '\0';
      (*str)++;
    }
    return p;
}               

void
Init()
{
     State = S_CONNECT;
     LowUserid[0] = '\0';
     markdel = 0;
     idletime = 0;
}

void
Login_init()
{
     int fd, i;
     char *ptr;
     struct stat st;
          
     totalnum = totalbyte = 0;
     sprintf(genbuf, "mail/%c/%s/.DIR", toupper(*LowUserid), LowUserid);
     if (stat(genbuf, &st) == -1 || st.st_size == 0) {
       return;
     }
     totalnum = st.st_size / sizeof(struct fileheader);
     fcache = (struct fileheader *)malloc(st.st_size);
     postlen = (int *)malloc(sizeof(int) * totalnum);
     fd = open(genbuf, O_RDONLY);
     read(fd, fcache, st.st_size);
     close(fd);

     for (i = 0; i < totalnum; i++) {
       if (index(fcache[i].owner, '@') == NULL) {
         if (ptr = strchr(fcache[i].owner, ' '))
           *ptr = '\0';
         strcat(fcache[i].owner, BBSNAME);
       }
       sprintf(genbuf, "mail/%c/%s/%s", toupper(*LowUserid), LowUserid, fcache[i].filename);
       if (stat(genbuf, &st) == -1)
         st.st_size = 0;
       postlen[i] = st.st_size + strlen(fcache[i].owner) + 10 + strlen(fcache[i].title)
                      + 10 + 40;
       totalbyte += postlen[i];
       fcache[i].accessed[0] = ' ';
     }
}

void
pop3_timeout()
{
    idletime++;
    if (idletime > 5) {
      log_usies("ABORT - TIMEOUT");
      fclose(cfp);
      close(sock);
      exit(1);
    }
    alarm(POP3_TIMEOUT);
}


main(argc,argv)
int argc;
char **argv;
{

        struct sockaddr_in fsin,our;
        int on,alen,len,i, n;
        char *str, flag;
        int portnum = POP3PORT;
        int childpid;


        if (2 == argc) portnum = atoi(argv[1]);
       
        if (0 == portnum) portnum = POP3PORT;


        if(fork()) 
          exit(0);
        for (n = 0; n<10; n++)
          close(n);
        open("/dev/null", O_RDONLY);
        dup2(0,1);
        dup2(0,2);
        if((n=open("/dev/tty",O_RDWR)) > 0) {
          ioctl(n, TIOCNOTTY, 0) ; 
          close(n);
        }
        
        if ((msock = socket(AF_INET,SOCK_STREAM,0)) < 0) {
          exit(1);
        }
        setsockopt(msock,SOL_SOCKET,SO_REUSEADDR, (char *) &on, sizeof(on));
        bzero((char *)&fsin,sizeof(fsin));
        fsin.sin_family = AF_INET;
        fsin.sin_addr.s_addr = htonl(INADDR_ANY);
        fsin.sin_port = htons(portnum);
                                                        
        if (bind(msock,(struct sockaddr *)&fsin,sizeof(fsin))<0) {
          exit(1);
        }

        signal(SIGHUP, (void *)abort_server) ;
        signal(SIGCHLD, reaper);
        signal(SIGINT,dokill);
        signal(SIGTERM,dokill);

        listen(msock,QLEN);
       
        while (1) {

          alen=sizeof(fsin);
          sock = accept(msock,(struct sockaddr *)&fsin,&alen);
          if (sock < 0) {
            if (errno != EINTR) 
            continue;
          }

          if ((childpid = fork()) < 0) {
            exit(1);
          }  

          switch (childpid) {
          case 0:  /* child process */
            close(msock);

            setgid(BBSGID);
            setuid(BBSUID);

            strcpy(fromhost, (char *)inet_ntoa(fsin.sin_addr));
            len = sizeof our;
            getsockname(sock, (struct sockaddr *) &our,&len);

            Init();

            rfc931( &fsin, &our, remote_userid );
    
            cfp = fdopen(sock, "r+");
            setbuf(cfp, (char *) 0);
            
            sprintf(genbuf, "+OK FireBird BBS Pop3 server at %s starting.", strchr(BBSNAME, '@') + 1);
            outs(genbuf);

            chdir(BBSHOME);

            log_usies("CONNECT");
            alarm(0);
            signal(SIGALRM, pop3_timeout);
            alarm(POP3_TIMEOUT);
            
            while (fgets(inbuf, sizeof(inbuf), cfp)!=0) {
            
               idletime = 0;
               
               msg = inbuf;
       
               inbuf[ strlen(inbuf)-1 ] = '\0';
               if (inbuf[strlen(inbuf)-1] == '\r') inbuf[strlen(inbuf)-1] = '\0';
               cmd = nextwordlower(&msg);

               if (*cmd==0) continue;
               
               i = 0;
               while ( (str = cmdlists[i].name) != NULL ) {
                 if ( strcmp( cmd, str ) == 0 ) break;
                 i++;
               }

               if (str==NULL)
               {
                  sprintf(genbuf, "-ERR Unknown command: \"%s\".", cmd);
                  outs(genbuf);
               }
               else (*cmdlists[i].fptr)();

            }

            if (State == S_LOGIN) {
              free(fcache);
              free(postlen);
            }
            log_usies("ABORT");
            fclose(cfp);
            close(sock);
            exit(0);
            break;
          default:   /* parent process */
            close(sock);
            break;
          }        
        }
}

static int
reaper()
{
     int state, pid;
     
     signal(SIGCHLD,SIG_IGN);
     signal(SIGINT,dokill);
     signal(SIGTERM,dokill);

     while (( pid = waitpid(-1, &state, WNOHANG|WUNTRACED)) > 0);
}

int
Noop()
{
    outs("+OK");
    return;
}

int
get_userdata(user)
char *user;
{
        FILE *rec;
        int found=0;
        char buf[256];

        sprintf(buf, "%s/.PASSWDS", BBSHOME);
        if((rec=fopen(buf,"rb"))==NULL)
                return -1;
        while(1)
        {
                if(fread(&currentuser,sizeof(currentuser),1,rec)<=0) break;
                if(currentuser.numlogins<=0)
                        continue;
                if(strcasecmp(user,currentuser.userid))
                        continue;
                else
                {
                        found=1;
                        strcpy(user,currentuser.userid);
                        break;
                }
        }
        fclose(rec);
        if(!found)
                return -1;
        else
                return 1;

}

int
User()
{
     char *ptr;
     
     if (State == S_LOGIN) {
       outs("-ERR Unknown command: \"user\".");
       return;
     }

     cmd = nextwordlower(&msg);
     if (*cmd == 0) {
       outs("-ERR Too few arguments for the user command.");
       return;
     }
     if (strstr(cmd, ".bbs") == NULL) {
       sprintf(genbuf, "-ERR Unknown user: \"%s\".", cmd);
       outs(genbuf);
       return;
     }

     ptr = strchr(cmd, '.');
     *ptr = '\0';
     if(get_userdata(cmd)==1)
     {
             strcpy(LowUserid, cmd);
             sprintf(genbuf, "+OK Password required for %s.bbs.", cmd);
             outs(genbuf);
     }else
     {
       sprintf(genbuf, "-ERR Unknown user: \"%s\".", cmd);
       outs(genbuf);
     }
     return;
}

void
log_usies(buf)
char *buf;
{
     FILE *fp;
     long ti;

     if ((fp = fopen("reclog/pop3d.log","a")) != NULL) {
       time_t now;
       struct tm *p;
       
       time(&now);
       p = localtime(&now);
       fprintf(fp, "%02d/%02d/%02d %02d:%02d:%02d [%s](%s) %s\n",
                 p->tm_year, p->tm_mon+1, p->tm_mday, p->tm_hour, p->tm_min,
                 p->tm_sec, currentuser.userid ? currentuser.userid : "",
                      remote_userid ? remote_userid : "", buf);
       fflush(fp);
       fclose(fp);
     }
}

int
Retr()
{
     int num;
     
     if (State != S_LOGIN) {
       outs("-ERR Unknown command: \"retr\".");
       return;
     }

     cmd = nextword(&msg);
     
     if (*cmd==0) {
       outs("-ERR Too few arguments for the retr command.");
       return;
     }
     
     num = atoi(cmd);
     if (num <= 0 || totalnum < num) {
       sprintf(genbuf, "-ERR Message %d does not exist.", num);
       outs(genbuf);
       return;
     } else if (fcache[num-1].accessed[0] == 'X') {
       sprintf(genbuf, "-ERR Message %d has been deleted.", num);
       outs(genbuf);
       return;
     }
     num--;
     sprintf(genbuf, "+OK %d octets", postlen[num]);
     outs(genbuf);
     sprintf(genbuf, "From: %s", fcache[num].owner);
     outs(genbuf);
     sprintf(genbuf, "To: %s%s", currentuser.userid, BBSNAME);
     outs(genbuf);
     sprintf(genbuf, "Subject: %s", fcache[num].title);
     outs(genbuf);
     outs("");
     sprintf(genbuf, "mail/%c/%s/%s", toupper(*LowUserid), LowUserid, fcache[num].filename);
     outfile(genbuf, 99999);

}


int
Stat()
{
     if (State != S_LOGIN) {
       outs("-ERR Unknown command: \"stat\".");
       return;
     }
     sprintf(genbuf, "+OK %d %d", totalnum, totalbyte);
     outs(genbuf);
}


int
Rset()
{
     int i;
     
     if (State != S_LOGIN) {
       outs("-ERR Unknown command: \"rset\".");
       return;
     }

     for (i = 0; i < totalnum; i++) {
       fcache[i].accessed[0] = ' ';
     }
     markdel = 0;
     sprintf(genbuf, "+OK Maildrop has %d messages (%d octets)", totalnum, totalbyte);
     outs(genbuf);
}

int
List()
{
     int i;
     
     if (State != S_LOGIN) {
       outs("-ERR Unknown command: \"list\".");
       return;
     }

     cmd = nextword(&msg);
     
     if (*cmd == 0) {
       sprintf(genbuf, "+OK %d messages (%d octets)", totalnum, totalbyte);
       outs(genbuf);
       for (i = 0; i < totalnum; i++) {
         if (fcache[i].accessed[0] == ' ') {
           sprintf(genbuf, "%d %d", i+1, postlen[i]);
           outs(genbuf);
         }
       }
       outs(".");
     } else {
       i = atoi(cmd);
       if (i <= 0 || totalnum < i) {
         sprintf(genbuf, "-ERR Message %d does not exist.", i);
         outs(genbuf);
         return;
       } else if (fcache[i-1].accessed[0] == 'X') {
         sprintf(genbuf, "-ERR Message %d has been deleted.", i);
         outs(genbuf);
         return;
       }
       sprintf(genbuf, "+OK %d %d", i, postlen[i-1]);
       outs(genbuf);
     }
     
}

int
Top() /* Leeward adds, 98.01.21 */
{
     int num;
     int ln;

     struct stat st;

     char *ptr;

     
     if (State != S_LOGIN) {
       outs("-ERR Unknown command: \"top\".");
       return;
     }

     cmd = nextword(&msg);
     
     if (*cmd==0) {
       outs("-ERR Too few arguments for the top command.");
       return;
     }
     
     num = atoi(cmd);
     if (num <= 0 || totalnum < num) {
       sprintf(genbuf, "-ERR Message %d does not exist.", num);
       outs(genbuf);
       return;
     } else if (fcache[num-1].accessed[0] == 'X') {
       sprintf(genbuf, "-ERR Message %d has been deleted.", num);
       outs(genbuf);
       return;
     }

     cmd = nextword(&msg);

     if (*cmd==0) {
       outs("-ERR Too few arguments for the top command.");
       return;
     }

     ln = atoi(cmd);
     if (ln < 0) {
       sprintf(genbuf, "-ERR Line %d does not exist.", ln);
       outs(genbuf);
       return;
     }


     num--;
     sprintf(genbuf, "+OK %d octets", postlen[num]);
     outs(genbuf);
     sprintf(genbuf, "mail/%c/%s/%s", toupper(*LowUserid), LowUserid, fcache[num].filename);
     stat(genbuf, &st);
     ptr = ctime(&st.st_mtime);
/*      Wed Jan 21 17:42:14 1998            -- ctime returns
        012345678901234567890123            -- offsets
  Date: Wed, 21 Jan 1998 17:54:33 +0800     -- RFC wants     */
     sprintf(genbuf, "Date: %3.3s, %2.2s %3.3s %4.4s %8.8s +0800", 
             ptr + 0, ptr + 8, ptr + 4, ptr + 20, ptr + 11);
     outs(genbuf);
     sprintf(genbuf, "From: %s", fcache[num].owner);
     outs(genbuf);
     sprintf(genbuf, "To: %s%s", currentuser.userid, BBSNAME);
     outs(genbuf);
     sprintf(genbuf, "Subject: %s", fcache[num].title);
     outs(genbuf);
     outs("");
     sprintf(genbuf, "mail/%c/%s/%s", toupper(*LowUserid), LowUserid, fcache[num].filename);
     outfile(genbuf, ln);

}


int
Uidl()
{
     int i;
     
     if (State != S_LOGIN) {
       outs("-ERR Unknown command: \"uidl\".");
       return;
     }

     cmd = nextword(&msg);
     
     if (*cmd == 0) {
       outs("+OK");
       for (i = 0; i < totalnum; i++) {
         if (fcache[i].accessed[0] == ' ') {
           sprintf(genbuf, "%d %s", i+1, fcache[i].filename);
           outs(genbuf);
         }
       }
       outs(".");
     } else {
       i = atoi(cmd);
       if (i <= 0 || totalnum < i) {
         sprintf(genbuf, "-ERR Message %d does not exist.", i);
         outs(genbuf);
         return;
       } else if (fcache[i-1].accessed[0] == 'X') {
         sprintf(genbuf, "-ERR Message %d has been deleted.", i);
         outs(genbuf);
         return;
       }
       sprintf(genbuf, "+OK %d %d", i, fcache[i-1].filename);
       outs(genbuf);
     }
     
}


int
Pass()
{
     if (State == S_LOGIN) {
       outs("-ERR Unknown command: \"pass\".");
       return;
     }

     /* Leeward: 97.12.27: enable password include space(s) */
     /*cmd = nextword(&msg);*/
     cmd = nextwordX(&msg);
     
     if (*cmd==0) {
       outs("-ERR Too few arguments for the pass command.");
       return;
     }

     if (LowUserid[0]=='\0') {
       outs("-ERR need a USER");
       return;
     }

     if (!checkpasswd(currentuser.passwd, cmd)) {
       sprintf(genbuf, "-ERR Password supplied for \"%s.bbs\" is incorrect.", LowUserid);
       outs(genbuf);
       LowUserid[0] = '\0';
       log_usies("ERROR PASSWD");
       return;
     }

     if (State==S_CONNECT) {
       log_usies("ENTER");
       State = S_LOGIN;
     }

     Login_init();
     sprintf(genbuf, "+OK %s has %d message(s) (%d octets).", LowUserid, totalnum, totalbyte);
     outs(genbuf);
}

int
Last()
{
     if (State != S_LOGIN) {
       outs("-ERR Unknown command: \"last\".");
       return;
     }

     sprintf(genbuf, "+OK %d is the last message seen.", totalnum);
     outs(genbuf);
}

int
Dele()
{
     int num;
     
     if (State != S_LOGIN) {
       outs("-ERR Unknown command: \"dele\".");
       return;
     }

     cmd = nextword(&msg);
     
     if (*cmd==0) {
       outs("-ERR Too few arguments for the dele command.");
       return;
     }
     
     num = atoi(cmd);
     if (num <= 0 || totalnum < num) {
       sprintf(genbuf, "-ERR Message %d does not exist.", num);
       outs(genbuf);
       return;
     } else if (fcache[num-1].accessed[0] == 'X') {
       sprintf(genbuf, "-ERR Message %d has already been deleted.", num);
       outs(genbuf);
       return;
     }
     num--;

     fcache[num].accessed[0] = 'X';
     markdel++;
     sprintf(genbuf, "+OK Message %d has been deleted.", num);
     outs(genbuf);
}

int
do_delete()
{
    int i, fdr, fdw, count;
    char fpath[80], fnew[80];
    
    sprintf(fpath, "mail/%c/%s/.DIR", toupper(*LowUserid), LowUserid);
    sprintf(fnew, "mail/%c/%s/.DIR.pop3", toupper(*LowUserid), LowUserid);
    if ((fdr = open(fpath, O_RDONLY)) == -1) return;
    if ((fdw = open(fnew, O_RDWR|O_CREAT, 0644)) == -1) return;
    i = count = 0;
    while (read(fdr, &currentmail, sizeof(currentmail))) {
      if (i >= totalnum || fcache[i].accessed[0] == ' ') {
        write(fdw, &currentmail, sizeof(currentmail));
        count++;
      } else {
        sprintf(genbuf, "mail/%c/%s/%s", toupper(*LowUserid), LowUserid,
                           currentmail.filename);
        unlink(genbuf);
      }
      i++;
    }
    close(fdr);
    close(fdw);
    unlink(fpath);
    if (count) 
    {
        rename(fnew, fpath);
    }
    else 
        unlink(fnew);
}

int
Quit()
{
     if (State == S_LOGIN) {
       free(fcache);
       free(postlen);
       if (markdel) do_delete();
     }
     log_usies("EXIT");
     sprintf(genbuf, "+OK FireBird BBS Pop3 server at %s signing off.", strchr(BBSNAME, '@') + 1);
     outs(genbuf);
     fclose(cfp);
     close(sock);
     exit(0);
}

--

        我 们 的 一 切 追 求 和 作 为, 都 有 一 个 令 人 厌 倦 的 过 程

   作 为 一 个 不 识 厌 倦 为 何 物 的 人, 便 掌 握 了 生 命 的 全 部 秘 密

6m※ 修改:·Leeward 於 Jun 15 08:01:39 修改本文·[FROM:  166.111.120.84]m
m5m※ 来源:·BBS 水木清华站 bbs.net.tsinghua.edu.cn·[FROM: 166.111.120.84]m


--

                              Enjoy Linux!
                          -----It's FREE!-----

※ 来源:.紫 丁 香 bbs.hit.edu.cn.[FROM: mtlab.hit.edu.cn]
[百宝箱] [返回首页] [上级目录] [根目录] [返回顶部] [刷新] [返回]
Powered by KBS BBS 2.0 (http://dev.kcn.cn)
页面执行时间:404.016毫秒