Annotation of sbbs/sbbs3/mailsrvr.c, revision 1.1.1.1

1.1       root        1: /* mailsrvr.c */
                      2: 
                      3: /* Synchronet Mail (SMTP/POP3) server and sendmail threads */
                      4: 
                      5: /* $Id: mailsrvr.c,v 1.45 2000/12/20 18:47:18 rswindell Exp $ */
                      6: 
                      7: /****************************************************************************
                      8:  * @format.tab-size 4          (Plain Text/Source Code File Header)                    *
                      9:  * @format.use-tabs true       (see http://www.synchro.net/ptsc_hdr.html)              *
                     10:  *                                                                                                                                                     *
                     11:  * Copyright 2000 Rob Swindell - http://www.synchro.net/copyright.html         *
                     12:  *                                                                                                                                                     *
                     13:  * This program is free software; you can redistribute it and/or                       *
                     14:  * modify it under the terms of the GNU General Public License                         *
                     15:  * as published by the Free Software Foundation; either version 2                      *
                     16:  * of the License, or (at your option) any later version.                                      *
                     17:  * See the GNU General Public License for more details: gpl.txt or                     *
                     18:  * http://www.fsf.org/copyleft/gpl.html                                                                                *
                     19:  *                                                                                                                                                     *
                     20:  * Anonymous FTP access to the most recent released source is available at     *
                     21:  * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net     *
                     22:  *                                                                                                                                                     *
                     23:  * Anonymous CVS access to the development source and modification history     *
                     24:  * is available at cvs.synchro.net:/cvsroot/sbbs, example:                                     *
                     25:  * cvs -d :pserver:[email protected]:/cvsroot/sbbs login                       *
                     26:  *     (just hit return, no password is necessary)                                                     *
                     27:  * cvs -d :pserver:[email protected]:/cvsroot/sbbs checkout src                *
                     28:  *                                                                                                                                                     *
                     29:  * For Synchronet coding style and modification guidelines, see                                *
                     30:  * http://www.synchro.net/source.html                                                                          *
                     31:  *                                                                                                                                                     *
                     32:  * You are encouraged to submit any modifications (preferably in Unix diff     *
                     33:  * format) via e-mail to [email protected]                                                                      *
                     34:  *                                                                                                                                                     *
                     35:  * Note: If this box doesn't appear square, then you need to fix your tabs.    *
                     36:  ****************************************************************************/
                     37: 
                     38: /* Platform-specific headers */
                     39: #ifdef _WIN32
                     40: 
                     41:        #include <io.h>                 /* open/close */
                     42:        #include <share.h>              /* share open flags */
                     43:        #include <process.h>    /* _beginthread */
                     44:        #include <windows.h>    /* required for mmsystem.h */
                     45:        #include <mmsystem.h>   /* SND_ASYNC */
                     46: 
                     47: #elif defined(__unix__)
                     48: 
                     49:        #include <signal.h>             /* signal/SIGPIPE */
                     50: 
                     51: #endif
                     52: 
                     53: 
                     54: /* ANSI C Library headers */
                     55: #include <stdio.h>
                     56: #include <stdlib.h>                    /* ltoa in GNU C lib */
                     57: #include <stdarg.h>                    /* va_list */
                     58: #include <string.h>                    /* strrchr */
                     59: #include <ctype.h>                     /* isdigit */
                     60: #include <fcntl.h>                     /* Open flags */
                     61: #include <errno.h>                     /* errno */
                     62: 
                     63: /* Synchronet-specific headers */
                     64: #include "sbbs.h"
                     65: #include "mailsrvr.h"
                     66: #include "crc32.h"
                     67: 
                     68: /* Constants */
                     69: #define MAIL_VERSION "1.10"
                     70: 
                     71: int dns_getmx(char* name, char* mx, char* mx2, DWORD intf, DWORD ip_addr, BOOL use_tcp);
                     72: 
                     73: #define SMTP_OK                "250 OK"
                     74: #define SMTP_BADSEQ    "503 Bad sequence of commands"
                     75: 
                     76: #define TIMEOUT_THREAD_WAIT            60              /* Seconds */
                     77: 
                     78: #define STATUS_WFC     "Listening"
                     79: 
                     80: static const char *wday[]={"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
                     81: static const char *mon[]={"Jan","Feb","Mar","Apr","May","Jun"
                     82:             ,"Jul","Aug","Sep","Oct","Nov","Dec"};
                     83: 
                     84: static mail_startup_t* startup=NULL;
                     85: static scfg_t  scfg;
                     86: static SOCKET  server_socket=INVALID_SOCKET;
                     87: static SOCKET  pop3_socket=INVALID_SOCKET;
                     88: static int             active_clients=0;
                     89: static int             active_sendmail=0;
                     90: static BOOL            sendmail_running=FALSE;
                     91: static DWORD   sockets=0;
                     92: 
                     93: typedef struct {
                     94:        SOCKET                  socket;
                     95:        SOCKADDR_IN             client_addr;
                     96: } smtp_t,pop3_t;
                     97: 
                     98: static int lprintf(char *fmt, ...)
                     99: {
                    100:        va_list argptr;
                    101:        char sbuf[1024];
                    102: 
                    103:     if(startup==NULL || startup->lputs==NULL)
                    104:         return(0);
                    105: 
                    106:        va_start(argptr,fmt);
                    107:     vsprintf(sbuf,fmt,argptr);
                    108:     va_end(argptr);
                    109:     return(startup->lputs(sbuf));
                    110: }
                    111: 
                    112: #ifdef _WINSOCKAPI_
                    113: 
                    114: static WSADATA WSAData;
                    115: static BOOL WSAInitialized=FALSE;
                    116: 
                    117: static BOOL winsock_startup(void)
                    118: {
                    119:        int             status;             /* Status Code */
                    120: 
                    121:     if((status = WSAStartup(MAKEWORD(1,1), &WSAData))==0) {
                    122:                lprintf("%s %s",WSAData.szDescription, WSAData.szSystemStatus);
                    123:                WSAInitialized=TRUE;
                    124:                return (TRUE);
                    125:        }
                    126: 
                    127:     lprintf("!WinSock startup ERROR %d", status);
                    128:        return (FALSE);
                    129: }
                    130: 
                    131: #else /* No WINSOCK */
                    132: 
                    133: #define winsock_startup()      (TRUE)
                    134: 
                    135: #endif
                    136: 
                    137: static void update_clients(void)
                    138: {
                    139:        if(startup!=NULL && startup->clients!=NULL)
                    140:                startup->clients(active_clients+active_sendmail);
                    141: }
                    142: 
                    143: static void client_on(SOCKET sock, client_t* client)
                    144: {
                    145:        if(startup!=NULL && startup->client_on!=NULL)
                    146:                startup->client_on(TRUE,sock,client);
                    147: }
                    148: 
                    149: static void client_off(SOCKET sock)
                    150: {
                    151:        if(startup!=NULL && startup->client_on!=NULL)
                    152:                startup->client_on(FALSE,sock,NULL);
                    153: }
                    154: 
                    155: static void thread_up(void)
                    156: {
                    157:        if(startup!=NULL && startup->thread_up!=NULL)
                    158:                startup->thread_up(TRUE);
                    159: }
                    160: 
                    161: static void thread_down(void)
                    162: {
                    163:        if(startup!=NULL && startup->thread_up!=NULL)
                    164:                startup->thread_up(FALSE);
                    165: }
                    166: 
                    167: SOCKET mail_open_socket(int type)
                    168: {
                    169:        SOCKET sock;
                    170: 
                    171:        sock=socket(AF_INET, type, IPPROTO_IP);
                    172:        if(sock!=INVALID_SOCKET && startup!=NULL && startup->socket_open!=NULL) 
                    173:                startup->socket_open(TRUE);
                    174:        if(sock!=INVALID_SOCKET) {
                    175:                sockets++;
                    176: #if 0 /*def _DEBUG */
                    177:                lprintf("%04d Socket opened (%d sockets in use)",sock,sockets);
                    178: #endif
                    179:        }
                    180:        return(sock);
                    181: }
                    182: 
                    183: int mail_close_socket(SOCKET sock)
                    184: {
                    185:        int             result;
                    186: 
                    187:        shutdown(sock,SHUT_RDWR);       /* required on Unix */
                    188:        result=closesocket(sock);
                    189:        if(/* result==0 && */ startup!=NULL && startup->socket_open!=NULL) 
                    190:                startup->socket_open(FALSE);
                    191:        sockets--;
                    192:        if(result!=0)
                    193:                lprintf("%04d !ERROR %d closing socket",sock, ERROR_VALUE);
                    194:        else {
                    195: #if 0 /*def _DEBUG */
                    196:                lprintf("%04d Socket closed (%d sockets in use)",sock,sockets);
                    197: #endif
                    198:        }
                    199: 
                    200:        return(result);
                    201: }
                    202: 
                    203: static void status(char* str)
                    204: {
                    205:        if(startup!=NULL && startup->status!=NULL)
                    206:            startup->status(str);
                    207: }
                    208: 
                    209: static int sockprintf(SOCKET sock, char *fmt, ...)
                    210: {
                    211:        int             len;
                    212:        int             result;
                    213:        va_list argptr;
                    214:        char    sbuf[1024];
                    215: 
                    216:     va_start(argptr,fmt);
                    217:     len=vsprintf(sbuf,fmt,argptr);
                    218:        if(startup->options&MAIL_OPT_DEBUG_TX)
                    219:                lprintf("%04d TX: %s", sock, sbuf);
                    220:        strcat(sbuf,"\r\n");
                    221:        len+=2;
                    222:     va_end(argptr);
                    223:        while((result=send(sock,sbuf,len,0))!=len) {
                    224:                if(result==SOCKET_ERROR) {
                    225:                        if(ERROR_VALUE==EWOULDBLOCK) {
                    226:                                mswait(1);
                    227:                                continue;
                    228:                        }
                    229:                        if(ERROR_VALUE==ECONNRESET) 
                    230:                                lprintf("%04d Connection reset by peer on send",sock);
                    231:                        else if(ERROR_VALUE==ECONNABORTED) 
                    232:                                lprintf("%04d Connection aborted by peer on send",sock);
                    233:                        else
                    234:                                lprintf("%04d !ERROR %d sending on socket",sock,ERROR_VALUE);
                    235:                        return(0);
                    236:                }
                    237:                lprintf("%04d !ERROR: short send on socket: %d instead of %d",sock,result,len);
                    238:        }
                    239:        return(len);
                    240: }
                    241: 
                    242: static time_t checktime(void)
                    243: {
                    244:        struct tm tm;
                    245: 
                    246:     memset(&tm,0,sizeof(tm));
                    247:     tm.tm_year=94;
                    248:     tm.tm_mday=1;
                    249:     return(mktime(&tm)-0x2D24BD00L);
                    250: }
                    251: 
                    252: static void recverror(SOCKET socket, int rd)
                    253: {
                    254:        if(rd==0) 
                    255:                lprintf("%04d Socket closed by peer on receive",socket);
                    256:        else if(rd==SOCKET_ERROR) {
                    257:                if(ERROR_VALUE==ECONNRESET) 
                    258:                        lprintf("%04d Connection reset by peer on receive",socket);
                    259:                else if(ERROR_VALUE==ECONNABORTED) 
                    260:                        lprintf("%04d Connection aborted by peer on receive",socket);
                    261:                else
                    262:                        lprintf("%04d !Socket error %d on receive", socket, ERROR_VALUE);
                    263:        } else
                    264:                lprintf("%04d !recv on socket returned unexpected value: %d",socket,rd);
                    265: }
                    266: 
                    267: static int sockreadline(SOCKET socket, char* buf, int len)
                    268: {
                    269:        char    ch;
                    270:        int             i,rd=0;
                    271:        time_t  start;
                    272: 
                    273:        start=time(NULL);
                    274:        
                    275:        while(rd<len-1) {
                    276:                i= recv(socket, &ch, 1, 0);
                    277:                if(i<1) {
                    278:                        if(ERROR_VALUE==EWOULDBLOCK) {
                    279:                                if((time(NULL)-start)>startup->max_inactivity) {
                    280:                                        lprintf("%04d !Socket inactive",socket);
                    281:                                        return(0);
                    282:                                }
                    283:                                mswait(1);
                    284:                                continue;
                    285:                        }
                    286:                        recverror(socket,i);
                    287:                        return(i);
                    288:                }
                    289:                if(ch=='\n' && rd>=1) {
                    290:                        break;
                    291:                }       
                    292:                buf[rd++]=ch;
                    293:        }
                    294:        buf[rd-1]=0;
                    295:        
                    296:        return(rd);
                    297: }
                    298: 
                    299: /************************************************/
                    300: /* Truncates white-space chars off end of 'str' */
                    301: /************************************************/
                    302: static void truncsp(char *str)
                    303: {
                    304:        uint c;
                    305: 
                    306:        c=strlen(str);
                    307:        while(c && (uchar)str[c-1]<=' ') c--;
                    308:        str[c]=0;
                    309: }
                    310: 
                    311: 
                    312: static char* alias(char* name, char* alias)
                    313: {
                    314:        int             file;
                    315:        char*   p=name;
                    316:        char*   np;
                    317:        char*   tp;
                    318:        char    fname[MAX_PATH];
                    319:        FILE*   fp;
                    320: 
                    321:        sprintf(fname,"%salias.cfg",scfg.ctrl_dir);
                    322:        if((file=sopen(fname,O_RDONLY|O_BINARY,SH_DENYNO))==-1)
                    323:                return(name);
                    324: 
                    325:        if((fp=fdopen(file,"rb"))==NULL) {
                    326:                close(file);
                    327:                return(name);
                    328:        }
                    329: 
                    330:        while(!feof(fp)) {
                    331:                if(!fgets(alias,80,fp))
                    332:                        break;
                    333:                np=alias;
                    334:                while(*np && *np<=' ') np++;
                    335:                if(*np==';')
                    336:                        continue;
                    337:                tp=np;
                    338:                while(*tp && *tp>' ') tp++;
                    339:                if(*tp) *tp=0;
                    340:                if(!stricmp(np,name)) {
                    341:                        np=tp+1;
                    342:                        while(*np && *np<=' ') np++;
                    343:                        p=np;
                    344:                        truncsp(p);
                    345:                        lprintf("0000 Alias: %s",p);
                    346:                        break;
                    347:                }
                    348:        }
                    349:        fclose(fp);
                    350:        return(p);
                    351: }
                    352: 
                    353: static BOOL sockgetrsp(SOCKET socket, char* rsp, char *buf, int len)
                    354: {
                    355:        int rd;
                    356: 
                    357:        while(1) {
                    358:                rd = sockreadline(socket, buf, len);
                    359:                if(rd<1) 
                    360:                        return(FALSE);
                    361:                if(buf[3]=='-') { /* Multi-line response */
                    362:                        if(startup->options&MAIL_OPT_DEBUG_RX_RSP) 
                    363:                                lprintf("%04d RX: %s",socket,buf);
                    364:                        continue;
                    365:                }
                    366:                if(strnicmp(buf,rsp,strlen(rsp))) {
                    367:                        lprintf("%04d !INVALID RESPONSE: '%s' Expected: '%s'", socket, buf, rsp);
                    368:                        return(FALSE);
                    369:                }
                    370:                break;
                    371:        }
                    372:        if(startup->options&MAIL_OPT_DEBUG_RX_RSP) 
                    373:                lprintf("%04d RX: %s",socket,buf);
                    374:        return(TRUE);
                    375: }
                    376: 
                    377: static void usermailaddr(char* addr, char* name)
                    378: {
                    379:        int i;
                    380: 
                    381:        if(strchr(name,'.')) /* unresolved exception here Nov-06-2000 */
                    382:                sprintf(addr,"\"%s\"@",name);
                    383:        else {
                    384:                sprintf(addr,"%s@",name);
                    385:                /* convert "first last@" to "first.last@" */
                    386:                for(i=0;addr[i];i++)
                    387:                        if(addr[i]==' ' || addr[i]&0x80)
                    388:                                addr[i]='.';
                    389:                strlwr(addr);
                    390:        }
                    391:        strcat(addr,scfg.sys_inetaddr);
                    392: }
                    393: 
                    394: static char *msgdate(when_t when, char* buf)
                    395: {
                    396:        struct tm       tm;
                    397:        struct tm*      tm_p;
                    398:        
                    399:        tm_p=localtime((const time_t*)&when.time);
                    400:        if(tm_p!=NULL)
                    401:                tm=*tm_p;
                    402:        else
                    403:                memset(&tm,0,sizeof(tm));
                    404:        sprintf(buf,"%s, %d %s %d %02d:%02d:%02d %s"
                    405:                ,wday[tm.tm_wday]
                    406:                ,tm.tm_mday
                    407:                ,mon[tm.tm_mon]
                    408:                ,1900+tm.tm_year
                    409:                ,tm.tm_hour
                    410:                ,tm.tm_min
                    411:                ,tm.tm_sec
                    412:                ,zonestr(when.zone)
                    413:                );
                    414:        return(buf);
                    415: }
                    416: 
                    417: #define MAX_LINE_LEN   1000
                    418: 
                    419: static void sockmsgtxt(SOCKET socket, smbmsg_t* msg, char* msgtxt, char* fromaddr
                    420:                                                ,ulong maxlines)
                    421: {
                    422:        char            toaddr[256];
                    423:        char            date[64];
                    424:        char*           p;
                    425:        char*           tp;
                    426:        int                     i;
                    427:        ulong           line;
                    428: 
                    429:        /* HEADERS */
                    430:        sockprintf(socket,"Date: %s",msgdate(msg->hdr.when_written,date));
                    431:        if(fromaddr[0]=='<')
                    432:                sockprintf(socket,"From: \"%s\" %s",msg->from,fromaddr);
                    433:        else
                    434:                sockprintf(socket,"From: \"%s\" <%s>",msg->from,fromaddr);
                    435:        sockprintf(socket,"Subject: %s",msg->subj);
                    436:        if(msg->to_net.type==NET_INTERNET || msg->to_net.type==NET_QWK) {
                    437:                if(*((char*)msg->to_net.addr)=='<')
                    438:                        sockprintf(socket,"To: \"%s\" %s",msg->to,(char*)msg->to_net.addr);
                    439:                else
                    440:                        sockprintf(socket,"To: \"%s\" <%s>",msg->to,(char*)msg->to_net.addr);
                    441:        } else {
                    442:                usermailaddr(toaddr,msg->to);
                    443:                sockprintf(socket,"To: \"%s\" <%s>",msg->to,toaddr);
                    444:        }
                    445:        if(msg->replyto_net.type==NET_INTERNET)
                    446:                sockprintf(socket,"Reply-To: %s",msg->replyto_net.addr);
                    447:        else
                    448:                sockprintf(socket,"Reply-To: %s",fromaddr);
                    449:        sockprintf(socket,"Message-ID: <%08lX.%lu@%s>"
                    450:                ,msg->hdr.when_written.time,msg->idx.number,scfg.sys_inetaddr);
                    451:        for(i=0;i<msg->total_hfields;i++) 
                    452:                if(msg->hfield[i].type==RFC822HEADER)
                    453:                        sockprintf(socket,"%s",(char*)msg->hfield_dat[i]);
                    454:        sockprintf(socket,"");  /* Header Terminator */
                    455:        /* MESSAGE BODY */
                    456:        line=0;
                    457:        p=msgtxt;
                    458:        while(*p && line<maxlines) {
                    459:                tp=strchr(p,'\n');
                    460:                if(tp) {
                    461:                        if(tp-p>MAX_LINE_LEN)
                    462:                                tp=p+MAX_LINE_LEN;
                    463:                        *tp=0;
                    464:                }
                    465:                truncsp(p);     /* Takes care of '\r' or spaces */
                    466:                if(*p=='.')
                    467:                        i=sockprintf(socket,".%.*s",MAX_LINE_LEN,p);
                    468:                else
                    469:                        i=sockprintf(socket,"%.*s",MAX_LINE_LEN,p);
                    470:                if(!i)
                    471:                        break;
                    472:                if(tp==NULL)
                    473:                        break;
                    474:                p=tp+1;
                    475:                line++;
                    476:                mswait(1);
                    477:        }
                    478:        sockprintf(socket,"."); /* End of text */
                    479: }
                    480: 
                    481: static u_long resolve_ip(char *addr)
                    482: {
                    483:        HOSTENT*        host;
                    484: 
                    485:        if(isdigit(addr[0]) && strchr(addr,'.'))
                    486:                return(inet_addr(addr));
                    487:        if ((host=gethostbyname(addr))==NULL) {
                    488:                lprintf("0000 !ERROR resolving host name: %s",addr);
                    489:                return(0);
                    490:        }
                    491:        return(*((ulong*)host->h_addr_list[0]));
                    492: }
                    493: 
                    494: 
                    495: static void pop3_thread(void* arg)
                    496: {
                    497:        char*           p;
                    498:        char            str[128];
                    499:        char            buf[512];
                    500:        char            host_name[128];
                    501:        char            host_ip[64];
                    502:        char            username[LEN_ALIAS+1];
                    503:        char            password[LEN_PASS+1];
                    504:        char            fromaddr[256];
                    505:        char*           msgtxt;
                    506:        int                     i;
                    507:        int                     rd;
                    508:        ulong           l;
                    509:        ulong           lines;
                    510:        ulong           msgs,bytes,msgnum,msgbytes;
                    511:        SOCKET          socket;
                    512:        HOSTENT*        host;
                    513:        smb_t           smb;
                    514:        smbmsg_t        msg;
                    515:        user_t          user;
                    516:        client_t        client;
                    517:        mail_t*         mail;
                    518:        pop3_t          pop3=*(pop3_t*)arg;
                    519: 
                    520:        thread_up();
                    521: 
                    522:        free(arg);
                    523: 
                    524:        socket=pop3.socket;
                    525: 
                    526:        if(startup->options&MAIL_OPT_DEBUG_POP3)
                    527:                lprintf("%04d POP3 session thread started", socket);
                    528: 
                    529: #ifdef _WIN32
                    530:        if(startup->pop3_sound[0] && !(startup->options&MAIL_OPT_MUTE)) 
                    531:                PlaySound(startup->pop3_sound, NULL, SND_ASYNC|SND_FILENAME);
                    532: #endif
                    533: 
                    534:        strcpy(host_ip,inet_ntoa(pop3.client_addr.sin_addr));
                    535: 
                    536:        if(startup->options&MAIL_OPT_DEBUG_POP3)
                    537:                lprintf("%04d POP3 connection accepted from: %s"
                    538:                        ,socket, host_ip);
                    539: 
                    540:        if(startup->options&MAIL_OPT_NO_HOST_LOOKUP)
                    541:                host=NULL;
                    542:        else
                    543:                host=gethostbyaddr((char *)&pop3.client_addr.sin_addr
                    544:                        ,sizeof(pop3.client_addr.sin_addr),AF_INET);
                    545: 
                    546:        if(host!=NULL && host->h_name!=NULL)
                    547:                sprintf(host_name,"%.*s",(int)sizeof(host_name)-1,host->h_name);
                    548:        else
                    549:                strcpy(host_name,"<no name>");
                    550: 
                    551:        if(startup->options&MAIL_OPT_DEBUG_POP3)
                    552:                lprintf("%04d POP3 client name: %s", socket, host_name);
                    553: 
                    554:        if(trashcan(&scfg,host_ip,"ip")) {
                    555:                lprintf("%04d !POP3 client blocked in ip.can: %s"
                    556:                        ,socket, host_ip);
                    557:                sockprintf(socket,"-ERR Access denied.");
                    558:                mail_close_socket(socket);
                    559:                thread_down();
                    560:                return;
                    561:        }
                    562: 
                    563:        if(trashcan(&scfg,host_name,"host")) {
                    564:                lprintf("%04d !POP3 client blocked in host.can: %s"
                    565:                        ,socket, host_name);
                    566:                sockprintf(socket,"-ERR Access denied.");
                    567:                mail_close_socket(socket);
                    568:                thread_down();
                    569:                return;
                    570:        }
                    571: 
                    572:        active_clients++;
                    573:        update_clients();
                    574: 
                    575:        /* Initialize client display */
                    576:        client.size=sizeof(client);
                    577:        client.time=time(NULL);
                    578:        sprintf(client.addr,"%.*s",(int)sizeof(client.addr)-1,host_ip);
                    579:        sprintf(client.host,"%.*s",(int)sizeof(client.host)-1,host_name);
                    580:        client.port=ntohs(pop3.client_addr.sin_port);
                    581:        client.protocol="POP3";
                    582:        client.user="<unknown>";
                    583:        client_on(socket,&client);
                    584: 
                    585:        sprintf(str,"POP3: %s", host_ip);
                    586:        status(str);
                    587: 
                    588:        mail=NULL;
                    589: 
                    590:        do {
                    591:                memset(&smb,0,sizeof(smb));
                    592:                memset(&msg,0,sizeof(msg));
                    593: 
                    594:                sprintf(smb.file,"%smail",scfg.data_dir);
                    595:                if((i=smb_open(&smb))!=0) {
                    596:                        lprintf("%04d !Error %d (%s) opening %s",socket,i,smb.last_error,smb.file);
                    597:                        sockprintf(socket,"-ERR %d opening %s",i,smb.file);
                    598:                        break;
                    599:                }
                    600: 
                    601:                sockprintf(socket,"+OK Synchronet POP3 Server for %s v%s Ready"
                    602:                        ,PLATFORM_DESC,MAIL_VERSION);
                    603: 
                    604:                if(!sockgetrsp(socket,"USER ",buf,sizeof(buf))) {
                    605:                        sockprintf(socket,"-ERR USER command expected");
                    606:                        break;
                    607:                }
                    608:                p=buf+5;
                    609:                while(*p && *p<=' ') p++;
                    610:                sprintf(username,"%.*s",(int)sizeof(username)-1,p);
                    611:                sockprintf(socket,"+OK");
                    612:                if(!sockgetrsp(socket,"PASS ",buf,sizeof(buf))) {
                    613:                        sockprintf(socket,"-ERR PASS command expected");
                    614:                        break;
                    615:                }
                    616:                p=buf+5;
                    617:                while(*p && *p<=' ') p++;
                    618:                sprintf(password,"%.*s",(int)sizeof(password)-1,p);
                    619:                user.number=matchuser(&scfg,username);
                    620:                if(!user.number) {
                    621:                        lprintf("%04d !POP3 UNKNOWN USER: %s (password: %s)"
                    622:                                , socket, username, password);
                    623:                        sockprintf(socket,"-ERR");
                    624:                        break;
                    625:                }
                    626:                if((i=getuserdat(&scfg, &user))!=0) {
                    627:                        lprintf("%04d !POP3 ERROR %d getting data on user #%u (%s)"
                    628:                                ,socket, i, user.number, username);
                    629:                        sockprintf(socket, "-ERR");
                    630:                        break;
                    631:                }
                    632:                if(user.misc&(DELETED|INACTIVE)) {
                    633:                        lprintf("%04d !POP3 DELETED or INACTIVE user #%u (%s)"
                    634:                                ,socket, user.number, username);
                    635:                        sockprintf(socket, "-ERR");
                    636:                        break;
                    637:                }
                    638:                if(stricmp(password,user.pass)) {
                    639:                        lprintf("%04d !POP3 WRONG PASSWORD for user %s: '%s' expected '%s'"
                    640:                                ,socket, username, password, user.pass);
                    641:                        sockprintf(socket, "-ERR");
                    642:                        break;
                    643:                }
                    644: 
                    645:                /* Update client display */
                    646:                client.user=user.alias;
                    647:                client_on(socket,&client);
                    648: 
                    649:                if(startup->options&MAIL_OPT_DEBUG_POP3)                
                    650:                        lprintf("%04d POP3 %s logged in", socket, user.alias);
                    651:                sprintf(str,"POP3: %s",user.alias);
                    652:                status(str);
                    653: 
                    654:                sockprintf(socket,"+OK User verified");
                    655: 
                    656:                mail=loadmail(&smb,&msgs,user.number,MAIL_YOUR,0);
                    657: 
                    658:                for(l=bytes=0;l<msgs;l++) {
                    659:                        msg.hdr.number=mail[l].number;
                    660:                        if((i=smb_getmsgidx(&smb,&msg))!=0) {
                    661:                                lprintf("%04d !POP3 ERROR %d getting message index"
                    662:                                        ,socket ,i);
                    663:                                break;
                    664:                        }
                    665:                        if((i=smb_lockmsghdr(&smb,&msg))!=0) {
                    666:                                lprintf("%04d !POP3 ERROR %d locking message header #%lu"
                    667:                                        ,socket ,i ,msg.hdr.number);
                    668:                                break; 
                    669:                        }
                    670:                        i=smb_getmsghdr(&smb,&msg);
                    671:                        smb_unlockmsghdr(&smb,&msg);
                    672:                        if(i!=0) {
                    673:                                lprintf("%04d !POP3 ERROR %d getting message header #%lu"
                    674:                                        ,socket, i, msg.hdr.number);
                    675:                                break;
                    676:                        }
                    677:                        for(i=0;i<msg.hdr.total_dfields;i++)
                    678:                                if(msg.dfield[i].type==TEXT_BODY || msg.dfield[i].type==TEXT_TAIL)
                    679:                                        bytes+=msg.dfield[i].length;
                    680:                        smb_freemsgmem(&msg);
                    681:                }                       
                    682: 
                    683:                while(1) {      /* TRANSACTION STATE */
                    684:                        rd = sockreadline(socket, buf, sizeof(buf));
                    685:                        if(rd<1) 
                    686:                                break;
                    687:                        if(startup->options&MAIL_OPT_DEBUG_POP3)
                    688:                                lprintf("%04d POP3 RX: %s", socket, buf);
                    689:                        if(!stricmp(buf, "NOOP")) {
                    690:                                sockprintf(socket,"+OK");
                    691:                                continue;
                    692:                        }
                    693:                        if(!stricmp(buf, "QUIT")) {
                    694:                                sockprintf(socket,"+OK");
                    695:                                break;
                    696:                        }
                    697:                        if(!stricmp(buf, "STAT")) {
                    698:                                sockprintf(socket,"+OK %lu %lu",msgs,bytes);
                    699:                                continue;
                    700:                        }
                    701:                        if(!stricmp(buf, "RSET")) {
                    702:                                for(l=0;l<msgs;l++) {
                    703:                                        msg.hdr.number=mail[l].number;
                    704:                                        if((i=smb_getmsgidx(&smb,&msg))!=0) {
                    705:                                                lprintf("%04d !POP3 ERROR %d getting message index"
                    706:                                                        ,socket, i);
                    707:                                                break;
                    708:                                        }
                    709:                                        if((i=smb_lockmsghdr(&smb,&msg))!=0) {
                    710:                                                lprintf("%04d !POP3 ERROR %d locking message header #%lu"
                    711:                                                        ,socket, i,msg.hdr.number);
                    712:                                                break; 
                    713:                                        }
                    714:                                        if((i=smb_getmsghdr(&smb,&msg))!=0) {
                    715:                                                lprintf("%04d !POP3 ERROR %d getting message header #%lu"
                    716:                                                        ,socket, i, msg.hdr.number);
                    717:                                                break;
                    718:                                        }
                    719:                                        msg.hdr.attr=mail[l].attr;
                    720:                                        msg.idx.attr=msg.hdr.attr;
                    721:                                        if((i=smb_putmsg(&smb,&msg))!=0)
                    722:                                                lprintf("%04d !POP3 ERROR %d updating message index"
                    723:                                                        ,socket, i);
                    724:                                        smb_unlockmsghdr(&smb,&msg);
                    725:                                        smb_freemsgmem(&msg);
                    726:                                }
                    727:                                if(l<msgs)
                    728:                                        sockprintf(socket,"-ERR %d messages reset (ERROR: %d)",l,i);
                    729:                                else
                    730:                                        sockprintf(socket,"+OK %lu messages (%lu bytes)",msgs,bytes);
                    731:                                continue;
                    732:                        }
                    733:                        if(!strnicmp(buf, "LIST",4) || !strnicmp(buf,"UIDL",4)) {
                    734:                                p=buf+4;
                    735:                                while(*p && *p<=' ') p++;
                    736:                                if(isdigit(*p)) {
                    737:                                        msgnum=atol(p);
                    738:                                        if(msgnum<1 || msgnum>msgs) {
                    739:                                                lprintf("%04d !POP3 INVALID message #%ld"
                    740:                                                        ,socket, msgnum);
                    741:                                                sockprintf(socket,"-ERR no such message");
                    742:                                                continue;
                    743:                                        }
                    744:                                        msg.hdr.number=mail[msgnum-1].number;
                    745:                                        if((i=smb_getmsgidx(&smb,&msg))!=0) {
                    746:                                                lprintf("%04d !POP3 ERROR %d getting message index"
                    747:                                                        ,socket, i);
                    748:                                                sockprintf(socket,"-ERR %d getting message index",i);
                    749:                                                break;
                    750:                                        }
                    751:                                        if(msg.idx.attr&MSG_DELETE) {
                    752:                                                lprintf("%04d !POP3 ATTEMPT to list deleted message"
                    753:                                                        ,socket);
                    754:                                                sockprintf(socket,"-ERR message deleted");
                    755:                                                continue;
                    756:                                        }
                    757:                                        if((i=smb_lockmsghdr(&smb,&msg))!=0) {
                    758:                                                lprintf("%04d !POP3 ERROR %d locking message header #%lu"
                    759:                                                        ,socket, i, msg.hdr.number);
                    760:                                                sockprintf(socket,"-ERR %d locking message header",i);
                    761:                                                continue; 
                    762:                                        }
                    763:                                        i=smb_getmsghdr(&smb,&msg);
                    764:                                        smb_unlockmsghdr(&smb,&msg);
                    765:                                        if(i!=0) {
                    766:                                                smb_freemsgmem(&msg);
                    767:                                                lprintf("%04d !POP3 ERROR %d getting message header #%lu"
                    768:                                                        ,socket, i,msg.hdr.number);
                    769:                                                sockprintf(socket,"-ERR %d getting message header",i);
                    770:                                                continue;
                    771:                                        }
                    772:                                        if(!strnicmp(buf, "LIST",4)) {
                    773:                                                msgbytes=0;
                    774:                                                for(i=0;i<msg.hdr.total_dfields;i++)
                    775:                                                        if(msg.dfield[i].type==TEXT_BODY || msg.dfield[i].type==TEXT_TAIL)
                    776:                                                                msgbytes+=msg.dfield[i].length;
                    777:                                                sockprintf(socket,"+OK %lu %lu",msgnum,msgbytes);
                    778:                                        } else /* UIDL */
                    779:                                                sockprintf(socket,"+OK %lu %lu",msgnum,msg.hdr.number);
                    780: 
                    781:                                        smb_freemsgmem(&msg);
                    782:                                        continue;
                    783:                                }
                    784:                                /* List ALL messages */
                    785:                                sockprintf(socket,"+OK %lu messages (%lu bytes)",msgs,bytes);
                    786:                                for(l=0;l<msgs;l++) {
                    787:                                        msg.hdr.number=mail[l].number;
                    788:                                        if((i=smb_getmsgidx(&smb,&msg))!=0) {
                    789:                                                lprintf("%04d !POP3 ERROR %d getting message index"
                    790:                                                        ,socket, i);
                    791:                                                break;
                    792:                                        }
                    793:                                        if(msg.idx.attr&MSG_DELETE) 
                    794:                                                continue;
                    795:                                        if((i=smb_lockmsghdr(&smb,&msg))!=0) {
                    796:                                                lprintf("%04d !POP3 ERROR %d locking message header #%lu"
                    797:                                                        ,socket, i,msg.hdr.number);
                    798:                                                break; 
                    799:                                        }
                    800:                                        i=smb_getmsghdr(&smb,&msg);
                    801:                                        smb_unlockmsghdr(&smb,&msg);
                    802:                                        if(i!=0) {
                    803:                                                smb_freemsgmem(&msg);
                    804:                                                lprintf("%04d !POP3 ERROR %d getting message header #%lu"
                    805:                                                        ,socket, i,msg.hdr.number);
                    806:                                                break;
                    807:                                        }
                    808:                                        if(!strnicmp(buf, "LIST",4)) {
                    809:                                                msgbytes=0;
                    810:                                                for(i=0;i<msg.hdr.total_dfields;i++)
                    811:                                                        if(msg.dfield[i].type==TEXT_BODY || msg.dfield[i].type==TEXT_TAIL)
                    812:                                                                msgbytes+=msg.dfield[i].length;
                    813:                                                sockprintf(socket,"%lu %lu",l+1,msgbytes);
                    814:                                        } else /* UIDL */
                    815:                                                sockprintf(socket,"%lu %lu",l+1,msg.hdr.number);
                    816: 
                    817:                                        smb_freemsgmem(&msg);
                    818:                                }                       
                    819:                                sockprintf(socket,".");
                    820:                                continue;
                    821:                        }
                    822:                        if(!strnicmp(buf, "RETR ",5) || !strnicmp(buf,"TOP ",4)) {
                    823:                                sprintf(str,"POP3: %s", user.alias);
                    824:                                status(str);
                    825: 
                    826:                                lines=-1;
                    827:                                p=buf+4;
                    828:                                while(*p && *p<=' ') p++;
                    829:                                msgnum=atol(p);
                    830: 
                    831:                                if(!strnicmp(buf,"TOP ",4)) {
                    832:                                        while(*p && isdigit(*p)) p++;
                    833:                                        while(*p && *p<=' ') p++;
                    834:                                        lines=atol(p);
                    835:                                }
                    836:                                if(msgnum<1 || msgnum>msgs) {
                    837:                                        lprintf("%04d !POP3 %s ATTEMPTED to retrieve an INVALID message #%ld"
                    838:                                                ,socket, user.alias, msgnum);
                    839:                                        sockprintf(socket,"-ERR no such message");
                    840:                                        continue;
                    841:                                }
                    842:                                msg.hdr.number=mail[msgnum-1].number;
                    843: 
                    844:                                lprintf("%04d POP3 %s retrieving message #%ld"
                    845:                                        ,socket, user.alias, msg.hdr.number);
                    846: 
                    847:                                if((i=smb_getmsgidx(&smb,&msg))!=0) {
                    848:                                        lprintf("%04d !POP3 ERROR %d getting message index"
                    849:                                                ,socket, i);
                    850:                                        sockprintf(socket,"-ERR %d getting message index",i);
                    851:                                        continue;
                    852:                                }
                    853:                                if(msg.idx.attr&MSG_DELETE) {
                    854:                                        lprintf("%04d !POP3 ATTEMPT to retrieve deleted message"
                    855:                                                ,socket);
                    856:                                        sockprintf(socket,"-ERR message deleted");
                    857:                                        continue;
                    858:                                }
                    859:                                if((i=smb_lockmsghdr(&smb,&msg))!=0) {
                    860:                                        lprintf("%04d !POP3 ERROR %d locking message header #%lu"
                    861:                                                ,socket, i, msg.hdr.number);
                    862:                                        sockprintf(socket,"-ERR %d locking message header",i);
                    863:                                        continue; 
                    864:                                }
                    865:                                if((i=smb_getmsghdr(&smb,&msg))!=0) {
                    866:                                        smb_unlockmsghdr(&smb,&msg);
                    867:                                        lprintf("%04d !POP3 ERROR %d getting message header #%lu"
                    868:                                                ,socket, i, msg.hdr.number);
                    869:                                        sockprintf(socket,"-ERR %d getting message header",i);
                    870:                                        continue;
                    871:                                }
                    872:                                smb_unlockmsghdr(&smb,&msg);
                    873: 
                    874:                                if((msgtxt=smb_getmsgtxt(&smb,&msg,GETMSGTXT_TAILS))==NULL) {
                    875:                                        smb_freemsgmem(&msg);
                    876:                                        lprintf("%04d !POP3 ERROR retrieving message text for message #%lu"
                    877:                                                ,socket, msg.hdr.number);
                    878:                                        sockprintf(socket,"-ERR retrieving message text");
                    879:                                        continue;
                    880:                                }
                    881: 
                    882:                                sockprintf(socket,"+OK message follows");
                    883:                                if(msg.from_net.type==NET_INTERNET)
                    884:                                        strcpy(fromaddr,msg.from_net.addr);
                    885:                                else if(msg.from_net.type==NET_QWK)
                    886:                                        sprintf(fromaddr,"\"%s@%s\"@%s"
                    887:                                                ,msg.from,(char*)msg.from_net.addr,scfg.sys_inetaddr);
                    888:                                else 
                    889:                                        usermailaddr(fromaddr,msg.from);        /* unresolved exception here Nov-06-2000 */
                    890:                                lprintf("%04d POP3 sending message text (%u bytes)"
                    891:                                        ,socket,strlen(msgtxt));
                    892:                                sockmsgtxt(socket,&msg,msgtxt,fromaddr,lines);
                    893:                                /* if(startup->options&MAIL_OPT_DEBUG_POP3) */
                    894:                                lprintf("%04d POP3 message transfer complete",socket);
                    895: 
                    896:                                msg.hdr.attr|=MSG_READ;
                    897:                                msg.idx.attr=msg.hdr.attr;
                    898:                                msg.hdr.netattr|=MSG_SENT;
                    899: 
                    900:                                if((i=smb_lockmsghdr(&smb,&msg))!=0) 
                    901:                                        lprintf("%04d !POP3 ERROR %d locking message header #%lu"
                    902:                                                ,socket, i, msg.hdr.number);
                    903:                                if((i=smb_putmsg(&smb,&msg))!=0)
                    904:                                        lprintf("%04d !POP3 ERROR %d marking message #%lu as read"
                    905:                                                ,socket, i, msg.hdr.number);
                    906:                                smb_unlockmsghdr(&smb,&msg);
                    907:                                smb_freemsgmem(&msg);
                    908:                                smb_freemsgtxt(msgtxt);
                    909:                                continue;
                    910:                        }
                    911:                        if(!strnicmp(buf, "DELE ",5)) {
                    912:                                p=buf+5;
                    913:                                while(*p && *p<=' ') p++;
                    914:                                msgnum=atol(p);
                    915: 
                    916:                                if(msgnum<1 || msgnum>msgs) {
                    917:                                        lprintf("%04d !POP3 %s ATTEMPTED to delete an INVALID message #%ld"
                    918:                                                ,socket, user.alias, msgnum);
                    919:                                        sockprintf(socket,"-ERR no such message");
                    920:                                        continue;
                    921:                                }
                    922:                                msg.hdr.number=mail[msgnum-1].number;
                    923: 
                    924:                                lprintf("%04d POP3 %s deleting message #%ld"
                    925:                                        ,socket, user.alias, msg.hdr.number);
                    926: 
                    927:                                if((i=smb_getmsgidx(&smb,&msg))!=0) {
                    928:                                        lprintf("%04d !POP3 ERROR %d getting message index"
                    929:                                                ,socket, i);
                    930:                                        sockprintf(socket,"-ERR %d getting message index",i);
                    931:                                        continue;
                    932:                                }
                    933:                                if((i=smb_lockmsghdr(&smb,&msg))!=0) {
                    934:                                        lprintf("%04d !POP3 ERROR %d locking message header #%lu"
                    935:                                                ,socket, i,msg.hdr.number);
                    936:                                        sockprintf(socket,"-ERR %d locking message header",i);
                    937:                                        continue; 
                    938:                                }
                    939:                                if((i=smb_getmsghdr(&smb,&msg))!=0) {
                    940:                                        smb_unlockmsghdr(&smb,&msg);
                    941:                                        lprintf("%04d !POP3 ERROR %d getting message header #%lu"
                    942:                                                ,socket, i,msg.hdr.number);
                    943:                                        sockprintf(socket,"-ERR %d getting message header",i);
                    944:                                        continue;
                    945:                                }
                    946:                                msg.hdr.attr|=MSG_DELETE;
                    947:                                msg.idx.attr=msg.hdr.attr;
                    948:                                if((i=smb_putmsg(&smb,&msg))!=0) {
                    949:                                        smb_unlockmsghdr(&smb,&msg);
                    950:                                        smb_freemsgmem(&msg);
                    951:                                        lprintf("%04d !POP3 ERROR %d marking message as read", socket, i);
                    952:                                        sockprintf(socket,"-ERR %d marking message for deletion",i);
                    953:                                        continue;
                    954:                                }
                    955:                                smb_unlockmsghdr(&smb,&msg);
                    956:                                smb_freemsgmem(&msg);
                    957:                                sockprintf(socket,"+OK");
                    958:                                if(startup->options&MAIL_OPT_DEBUG_POP3)
                    959:                                        lprintf("%04d POP3 message deleted", socket);
                    960:                                continue;
                    961:                        }
                    962:                        lprintf("%04d !POP3 UNSUPPORTED COMMAND: %s", socket, buf);
                    963:                        sockprintf(socket,"-ERR UNSUPPORTED COMMAND: %s",buf);
                    964:                }
                    965:                if(user.number)
                    966:                        putuserrec(&scfg,user.number,U_LASTON,8,ultoa(time(NULL),str,16));
                    967: 
                    968:        } while(0);
                    969: 
                    970:        status(STATUS_WFC);
                    971: 
                    972:        /* Free up resources here */
                    973:        mail_close_socket(socket);
                    974: 
                    975:        if(mail!=NULL)
                    976:                freemail(mail);
                    977: 
                    978:        smb_freemsgmem(&msg);
                    979:        smb_close(&smb);
                    980: 
                    981:        if(startup->options&MAIL_OPT_DEBUG_POP3)
                    982:                lprintf("%04d POP3 session thread terminated", socket);
                    983: 
                    984:        active_clients--;
                    985:        update_clients();
                    986:        client_off(socket);
                    987: 
                    988:        thread_down();
                    989: }
                    990: 
                    991: BOOL rblchk(DWORD mail_addr_n, char* rbl_addr)
                    992: {
                    993:        char            name[256];
                    994:        DWORD           mail_addr;
                    995: 
                    996:        mail_addr=ntohl(mail_addr_n);
                    997:        sprintf(name,"%ld.%ld.%ld.%ld.%s"
                    998:                ,mail_addr&0xff
                    999:                ,(mail_addr>>8)&0xff
                   1000:                ,(mail_addr>>16)&0xff
                   1001:                ,(mail_addr>>24)&0xff
                   1002:                ,rbl_addr
                   1003:                );
                   1004: 
                   1005:        if(gethostbyname(name)==NULL)
                   1006:                return(FALSE);
                   1007: 
                   1008:        return(TRUE);
                   1009: }
                   1010: 
                   1011: 
                   1012: static void smtp_thread(void* arg)
                   1013: {
                   1014:        int                     i,j,x;
                   1015:        int                     rd;
                   1016:        char            str[512];
                   1017:        char            buf[1024],*p,*tp;
                   1018:        char            hdrfield[512];
                   1019:        char            alias_buf[128];
                   1020:        char            reverse_path[128];
                   1021:        char            date[64];
                   1022:        char            month[16];
                   1023:        char            rcpt_name[128];
                   1024:        char            rcpt_addr[128];
                   1025:        char            sender[128]={0};
                   1026:        char            sender_addr[128]={0};
                   1027:        char            hello_name[128];
                   1028:        char            host_name[128];
                   1029:        char            host_ip[64];
                   1030:        int                     addr_len;
                   1031:        ushort          xlat;
                   1032:        ushort          nettype=NET_NONE;
                   1033:        uint            usernum;
                   1034:        ulong           crc;
                   1035:        ulong           length;
                   1036:        ulong           offset;
                   1037:        BOOL            esmtp=FALSE;
                   1038:        FILE*           msgtxt=NULL;
                   1039:        char            msgtxt_fname[MAX_PATH];
                   1040:        FILE*           rcptlst;
                   1041:        char            rcptlst_fname[MAX_PATH];
                   1042:        FILE*           spy=NULL;
                   1043:        SOCKET          socket;
                   1044:        HOSTENT*        host;
                   1045:        smb_t           smb;
                   1046:        smbmsg_t        msg;
                   1047:        smbmsg_t        newmsg;
                   1048:        user_t          user;
                   1049:        client_t        client;
                   1050:        struct tm       tm;
                   1051:        smtp_t          smtp=*(smtp_t*)arg;
                   1052:        SOCKADDR_IN server_addr;
                   1053:        enum {
                   1054:                         SMTP_STATE_INITIAL
                   1055:                        ,SMTP_STATE_HELO
                   1056:                        ,SMTP_STATE_MAIL_FROM
                   1057:                        ,SMTP_STATE_RCPT_TO
                   1058:                        ,SMTP_STATE_DATA_HEADER
                   1059:                        ,SMTP_STATE_DATA_BODY
                   1060: 
                   1061:        } state = SMTP_STATE_INITIAL;
                   1062: 
                   1063:        thread_up();
                   1064: 
                   1065:        free(arg);
                   1066: 
                   1067:        socket=smtp.socket;
                   1068: 
                   1069:        lprintf("%04d SMTP RX Session thread started", socket);
                   1070: 
                   1071: #ifdef _WIN32
                   1072:        if(startup->inbound_sound[0] && !(startup->options&MAIL_OPT_MUTE)) 
                   1073:                PlaySound(startup->inbound_sound, NULL, SND_ASYNC|SND_FILENAME);
                   1074: #endif
                   1075: 
                   1076:        addr_len=sizeof(server_addr);
                   1077:        if((i=getsockname(socket, (struct sockaddr *)&server_addr,&addr_len))!=0) {
                   1078:                lprintf("%04d !SMTP ERROR %d (%d) getting address/port"
                   1079:                        ,socket, i, ERROR_VALUE);
                   1080:                return;
                   1081:        } 
                   1082: 
                   1083:        memset(&msg,0,sizeof(smbmsg_t));
                   1084: 
                   1085:        strcpy(host_ip,inet_ntoa(smtp.client_addr.sin_addr));
                   1086: 
                   1087:        lprintf("%04d SMTP connection accepted from: %s", socket, host_ip);
                   1088: 
                   1089:        if(startup->options&MAIL_OPT_NO_HOST_LOOKUP)
                   1090:                host=NULL;
                   1091:        else
                   1092:                host=gethostbyaddr ((char *)&smtp.client_addr.sin_addr
                   1093:                        ,sizeof(smtp.client_addr.sin_addr),AF_INET);
                   1094: 
                   1095:        if(host!=NULL && host->h_name!=NULL)
                   1096:                sprintf(host_name,"%.*s",(int)sizeof(host_name)-1,host->h_name);
                   1097:        else
                   1098:                strcpy(host_name,"<no name>");
                   1099: 
                   1100:        lprintf("%04d SMTP host name: %s", socket, host_name);
                   1101: 
                   1102:        strcpy(hello_name,host_name);
                   1103: 
                   1104:        if(trashcan(&scfg,host_ip,"ip")) {
                   1105:                lprintf("%04d !SMTP server blocked in ip.can: %s"
                   1106:                        ,socket, host_ip);
                   1107:                sockprintf(socket,"550 Access denied.");
                   1108:                mail_close_socket(socket);
                   1109:                thread_down();
                   1110:                return;
                   1111:        }
                   1112: 
                   1113:        if(trashcan(&scfg,host_name,"host")) {
                   1114:                lprintf("%04d !SMTP server blocked in host.can: %s"
                   1115:                        ,socket, host_name);
                   1116:                sockprintf(socket,"550 Access denied.");
                   1117:                mail_close_socket(socket);
                   1118:                thread_down();
                   1119:                return;
                   1120:        }
                   1121: 
                   1122:        /*  SPAM Filters (maps.vix.com) */
                   1123:        if(startup->options&MAIL_OPT_USE_RBL
                   1124:                && rblchk(smtp.client_addr.sin_addr.s_addr
                   1125:                        ,"rbl.maps.vix.com"
                   1126:                        )==TRUE) {
                   1127:                lprintf("%04d !SMTP SPAM server filtered (RBL): %s [%s]"
                   1128:                        ,socket, host_name,host_ip);
                   1129:                sockprintf(socket
                   1130:                        ,"571 Mail from %s refused, see http://www.mail-abuse.org/rbl"
                   1131:                        ,host_ip);
                   1132:                mail_close_socket(socket);
                   1133:                thread_down();
                   1134:                return;
                   1135:        }
                   1136:        if(startup->options&MAIL_OPT_USE_DUL
                   1137:                && rblchk(smtp.client_addr.sin_addr.s_addr
                   1138:                        ,"dul.maps.vix.com"
                   1139:                        )==TRUE) {
                   1140:                lprintf("%04d !SMTP SPAM server filtered (DUL): %s [%s]"
                   1141:                        ,socket, host_name,host_ip);
                   1142:                sockprintf(socket
                   1143:                        ,"571 Mail from %s refused, see http://www.mail-abuse.org/dul"
                   1144:                        ,host_ip);
                   1145:                mail_close_socket(socket);
                   1146:                thread_down();
                   1147:                return;
                   1148:        }
                   1149:        if(startup->options&MAIL_OPT_USE_RSS
                   1150:                && rblchk(smtp.client_addr.sin_addr.s_addr
                   1151:                        ,"relays.mail-abuse.org"
                   1152:                        )==TRUE) {
                   1153:                lprintf("%04d !SMTP SPAM server filtered (RSS): %s [%s]"
                   1154:                        ,socket, host_name,host_ip);
                   1155:                sockprintf(socket
                   1156:                        ,"571 Mail from %s refused, see http://www.mail-abuse.org/rss"
                   1157:                        ,host_ip);                                      
                   1158:                mail_close_socket(socket);
                   1159:                thread_down();
                   1160:                return;
                   1161:        }
                   1162: 
                   1163:        sprintf(rcptlst_fname,"%sSMTP%d.LST", scfg.data_dir, socket);
                   1164:        rcptlst=fopen(rcptlst_fname,"w+");
                   1165:        if(rcptlst==NULL) {
                   1166:                lprintf("%04d !SMTP ERROR %d creating recipient list: %s"
                   1167:                        ,socket, errno, rcptlst_fname);
                   1168:                sockprintf(socket,"421 System error");
                   1169:                mail_close_socket(socket);
                   1170:                thread_down();
                   1171:                return;
                   1172:        }
                   1173: 
                   1174:        if(trashcan(&scfg,host_name,"smtpspy") 
                   1175:                || trashcan(&scfg,host_ip,"smtpspy")) {
                   1176:                sprintf(str,"%sSMTPSPY.TXT", scfg.data_dir);
                   1177:                spy=fopen(str,"a");
                   1178:        }
                   1179: 
                   1180:        active_clients++;
                   1181:        update_clients();
                   1182: 
                   1183:        /* Initialize client display */
                   1184:        client.size=sizeof(client);
                   1185:        client.time=time(NULL);
                   1186:        sprintf(client.addr,"%.*s",(int)sizeof(client.addr)-1,host_ip);
                   1187:        sprintf(client.host,"%.*s",(int)sizeof(client.host)-1,host_name);
                   1188:        client.port=ntohs(smtp.client_addr.sin_port);
                   1189:        client.protocol="SMTP";
                   1190:        client.user="<unknown>";
                   1191:        client_on(socket,&client);
                   1192: 
                   1193:        sprintf(str,"SMTP: %s",host_ip);
                   1194:        status(str);
                   1195: 
                   1196:        sockprintf(socket,"220 %s Synchronet SMTP Server for %s v%s Ready"
                   1197:                ,scfg.sys_inetaddr,PLATFORM_DESC,MAIL_VERSION);
                   1198:        while(1) {
                   1199:                rd = sockreadline(socket, buf, sizeof(buf));
                   1200:                if(rd<1) 
                   1201:                        break;
                   1202:                if(spy!=NULL)
                   1203:                        fprintf(spy,"%s\n",buf);
                   1204:                if(state>=SMTP_STATE_DATA_HEADER) {
                   1205:                        if(!strcmp(buf,".")) {
                   1206:                                lprintf("%04d SMTP End of message (%lu bytes)", socket, ftell(msgtxt));
                   1207: 
                   1208:                                if(sender[0]==0) {
                   1209:                                        lprintf("%04d !SMTP Mail header missing 'FROM' field", socket);
                   1210:                                        sockprintf(socket, "554 Mail header missing 'FROM' field");
                   1211:                                        state=SMTP_STATE_HELO;
                   1212:                                        continue;
                   1213:                                }
                   1214: 
                   1215:                                if(msgtxt!=NULL) {
                   1216:                                        rewind(msgtxt);
                   1217:                                        sprintf(smb.file,"%smail", scfg.data_dir);
                   1218:                                        smb.retry_time=scfg.smb_retry_time;
                   1219:                                        if((i=smb_open(&smb))!=0) {
                   1220:                                                lprintf("%04d !SMTP ERROR %d (%s) opening %s"
                   1221:                                                        ,socket, i, smb.last_error, smb.file);
                   1222:                                                sockprintf(socket, "452 Insufficient system storage");
                   1223:                                                continue;
                   1224:                                        }
                   1225: 
                   1226:                                        if(smb_fgetlength(smb.shd_fp)<1) {       /* Create it if it doesn't exist */
                   1227:                                                smb.status.max_crcs=scfg.mail_maxcrcs;
                   1228:                                                smb.status.max_age=scfg.mail_maxage;
                   1229:                                                smb.status.max_msgs=MAX_SYSMAIL;
                   1230:                                                smb.status.attr=SMB_EMAIL;
                   1231:                                                if((i=smb_create(&smb))!=0) {
                   1232:                                                        smb_close(&smb);
                   1233:                                                        lprintf("%04d !SMTP ERROR %d creating %s"
                   1234:                                                                ,socket, i, smb.file);
                   1235:                                                        sockprintf(socket, "452 Insufficient system storage");
                   1236:                                                        continue;
                   1237:                                                } 
                   1238:                                        }
                   1239: 
                   1240:                                        if((i=smb_locksmbhdr(&smb))!=0) {
                   1241:                                                smb_close(&smb);
                   1242:                                                lprintf("%04d !SMTP ERROR %d locking %s"
                   1243:                                                        ,socket, i, smb.file);
                   1244:                                                sockprintf(socket, "452 Insufficient system storage");
                   1245:                                                continue; }
                   1246: 
                   1247:                                        length=filelength(fileno(msgtxt))+2;     /* +2 for translation string */
                   1248: 
                   1249:                                        if((i=smb_open_da(&smb))!=0) {
                   1250:                                                smb_unlocksmbhdr(&smb);
                   1251:                                                smb_close(&smb);
                   1252:                                                lprintf("%04d !SMTP ERROR %d (%s) opening %s.sda"
                   1253:                                                        ,socket, i, smb.last_error, smb.file);
                   1254:                                                sockprintf(socket, "452 Insufficient system storage");
                   1255:                                                continue; }
                   1256: 
                   1257:                                        if(scfg.sys_misc&SM_FASTMAIL)
                   1258:                                                offset=smb_fallocdat(&smb,length,1);
                   1259:                                        else
                   1260:                                                offset=smb_allocdat(&smb,length,1);
                   1261:                                        smb_close_da(&smb);
                   1262: 
                   1263:                                        smb_fseek(smb.sdt_fp,offset,SEEK_SET);
                   1264:                                        xlat=XLAT_NONE;
                   1265:                                        smb_fwrite(&xlat,2,smb.sdt_fp);
                   1266:                                        x=SDT_BLOCK_LEN-2;                              /* Don't read/write more than 255 */
                   1267:                                        while(!feof(msgtxt)) {
                   1268:                                                memset(buf,0,x);
                   1269:                                                j=fread(buf,1,x,msgtxt);
                   1270:                                                if(j<1)
                   1271:                                                        break;
                   1272:                                                if((j!=x || feof(msgtxt)) && buf[j-1]=='\n' && buf[j-2]=='\r')
                   1273:                                                        buf[j-1]=buf[j-2]=0;
                   1274:                                                if(scfg.mail_maxcrcs) {
                   1275:                                                        for(i=0;i<j;i++)
                   1276:                                                                crc=ucrc32(buf[i],crc); 
                   1277:                                                }
                   1278:                                                smb_fwrite(buf,j,smb.sdt_fp);
                   1279:                                                x=SDT_BLOCK_LEN; 
                   1280:                                        }
                   1281:                                        smb_fflush(smb.sdt_fp);
                   1282:                                        crc=~crc;
                   1283: 
                   1284:                                        if(scfg.mail_maxcrcs) {
                   1285:                                                i=smb_addcrc(&smb,crc);
                   1286:                                                if(i) {
                   1287:                                                        smb_freemsgdat(&smb,offset,length,1);
                   1288:                                                        smb_unlocksmbhdr(&smb);
                   1289:                                                        smb_close(&smb);
                   1290:                                                        lprintf("%04d !SMTP Duplicate message", socket);
                   1291:                                                        sockprintf(socket, "554 Duplicate Message");
                   1292:                                                        continue; 
                   1293:                                                } 
                   1294:                                        }
                   1295: 
                   1296:                                        msg.hdr.offset=offset;
                   1297: 
                   1298:                                        smb_dfield(&msg,TEXT_BODY,length);
                   1299: 
                   1300:                                        smb_unlocksmbhdr(&smb);
                   1301:                                        if(msg.idx.subj==0) {
                   1302:                                                p="";
                   1303:                                                smb_hfield(&msg, SUBJECT, 0, p);
                   1304:                                                msg.idx.subj=crc16(p);
                   1305:                                        }
                   1306:                                        rewind(rcptlst);
                   1307:                                        while(!feof(rcptlst)) {
                   1308:                                                if((i=smb_copymsgmem(&newmsg,&msg))!=0) {
                   1309:                                                        lprintf("%04d !SMTP ERROR %d copying message"
                   1310:                                                                ,socket, i);
                   1311:                                                        break;
                   1312:                                                }
                   1313:                                                if(fgets(str,sizeof(str)-1,rcptlst)==NULL)
                   1314:                                                        break;
                   1315:                                                usernum=atoi(str);
                   1316:                                                fgets(rcpt_name,sizeof(rcpt_name)-1,rcptlst);
                   1317:                                                if(fgets(rcpt_addr,sizeof(rcpt_addr)-1,rcptlst)==NULL)
                   1318:                                                        break;
                   1319:                                                truncsp(rcpt_name);
                   1320:                                                truncsp(rcpt_addr);
                   1321: 
                   1322:                                                snprintf(hdrfield,sizeof(hdrfield),
                   1323:                                                        "Received: from %s (%s [%s])\r\n"
                   1324:                                                        "          by %s [%s] (Synchronet Mail Server for %s v%s) with %s\r\n"
                   1325:                                                        "          for %s; %s"
                   1326:                                                        ,host_name,hello_name,host_ip
                   1327:                                                        ,scfg.sys_inetaddr,inet_ntoa(server_addr.sin_addr)
                   1328:                                                        ,PLATFORM_DESC,MAIL_VERSION
                   1329:                                                        ,esmtp ? "ESMTP" : "SMTP"
                   1330:                                                        ,rcpt_addr,msgdate(msg.hdr.when_imported,date));
                   1331:                                                smb_hfield(&newmsg, RFC822HEADER, (ushort)strlen(hdrfield), hdrfield);
                   1332: 
                   1333:                                                smb_hfield(&newmsg, RECIPIENT, (ushort)strlen(rcpt_name), rcpt_name);
                   1334: 
                   1335:                                                if(rcpt_addr[0]=='#') { /* Local destination */
                   1336:                                                        newmsg.idx.to=atoi(rcpt_addr+1);
                   1337:                                                        smb_hfield(&newmsg, RECIPIENTEXT
                   1338:                                                                ,(ushort)strlen(rcpt_addr+1), rcpt_addr+1);
                   1339:                                                } else {
                   1340:                                                        newmsg.idx.to=0;
                   1341:                                                        nettype=NET_INTERNET;
                   1342:                                                        smb_hfield(&newmsg, RECIPIENTNETTYPE, nettype, &nettype);
                   1343:                                                        smb_hfield(&newmsg, RECIPIENTNETADDR
                   1344:                                                                ,(ushort)strlen(rcpt_addr), rcpt_addr);
                   1345:                                                }
                   1346: 
                   1347:                                                i=smb_addmsghdr(&smb,&newmsg,SMB_SELFPACK);
                   1348:                                                smb_freemsgmem(&newmsg);
                   1349:                                                if(i!=0) {
                   1350:                                                        lprintf("%04d !SMTP ERROR %d adding message header"
                   1351:                                                                ,socket, i);
                   1352:                                                        break;
                   1353:                                                }
                   1354:                                                lprintf("%04d SMTP Created message #%ld from %s to %s <%s>"
                   1355:                                                        ,socket, newmsg.hdr.number, sender, rcpt_name, rcpt_addr);
                   1356:                                                if(usernum) {
                   1357:                                                        sprintf(str,"\7\1n\1hOn %.24s\r\n\1m%s \1n\1msent you e-mail from: "
                   1358:                                                                "\1h%s\1n\r\n"
                   1359:                                                                ,ctime((const time_t*)&newmsg.hdr.when_imported.time)
                   1360:                                                                ,sender,sender_addr);
                   1361:                                                        if(!newmsg.idx.to) {    /* Forwarding */
                   1362:                                                                strcat(str,"\1mand it was automatically forwaded to: \1h");
                   1363:                                                                strcat(str,user.netmail);
                   1364:                                                                strcat(str,"\1n\r\n");
                   1365:                                                        }
                   1366:                                                        putsmsg(&scfg, usernum, str);
                   1367:                                                }
                   1368:                                        }
                   1369:                                        smb_close(&smb);
                   1370:                                        if(i) {
                   1371:                                                smb_freemsgdat(&smb,offset,length,1);
                   1372:                                                sockprintf(socket, "452 Insufficient system storage");
                   1373:                                                continue;
                   1374:                                        }
                   1375:                                }
                   1376:                                sockprintf(socket,SMTP_OK);
                   1377:                                state=SMTP_STATE_HELO;
                   1378:                                continue;
                   1379:                        }
                   1380:                        if(buf[0]==0 && state==SMTP_STATE_DATA_HEADER) {        
                   1381:                                state=SMTP_STATE_DATA_BODY;     /* Null line separates header and body */
                   1382:                                continue;
                   1383:                        }
                   1384:                        if(state==SMTP_STATE_DATA_BODY) {
                   1385:                                p=buf;
                   1386:                                if(*p=='.') p++;        /* Transparency (RFC821 4.5.2) */
                   1387:                                if(msgtxt!=NULL) 
                   1388:                                        fprintf(msgtxt, "%s\r\n", p);
                   1389:                                continue;
                   1390:                        }
                   1391:                        /* RFC822 Header parsing */
                   1392:                        if(startup->options&MAIL_OPT_DEBUG_RX_HEADER)
                   1393:                                lprintf("%04d SMTP %s",socket, buf);
                   1394: 
                   1395:                        if(!strnicmp(buf, "SUBJECT:",8)) {
                   1396:                                p=buf+8;
                   1397:                                while(*p && *p<=' ') p++;
                   1398:                                smb_hfield(&msg, SUBJECT, (ushort)strlen(p), p);
                   1399:                                strlwr(p);
                   1400:                                msg.idx.subj=crc16(p);
                   1401:                                continue;
                   1402:                        }
                   1403:                        if(!strnicmp(buf, "TO:",3)) {
                   1404:                                p=buf+3;
                   1405:                                while(*p && *p<=' ') p++;
                   1406:                                if(*p=='<')  {
                   1407:                                        p++;
                   1408:                                        tp=strrchr(p,'>');
                   1409:                                        if(tp) *tp=0;
                   1410:                                }
                   1411: #if 0
                   1412:                                if(!nettype) {
                   1413:                                        nettype=NET_INTERNET;
                   1414:                                        smb_hfield(&msg, RECIPIENTNETTYPE, nettype, &nettype);
                   1415:                                        smb_hfield(&msg, RECIPIENTNETADDR, (ushort)strlen(p), p);
                   1416:                                }
                   1417: #endif
                   1418:                                continue;
                   1419:                        }
                   1420:                        if(!strnicmp(buf, "REPLY-TO:",9)) {
                   1421:                                p=buf+9;
                   1422:                                while(*p && *p<=' ') p++;
                   1423:                                if(*p=='<')  {
                   1424:                                        p++;
                   1425:                                        tp=strchr(p,'>');
                   1426:                                        if(tp) *tp=0;
                   1427:                                }
                   1428:                                nettype=NET_INTERNET;
                   1429:                                smb_hfield(&msg, REPLYTONETTYPE, nettype, &nettype);
                   1430:                                smb_hfield(&msg, REPLYTONETADDR, (ushort)strlen(p), p);
                   1431:                                continue;
                   1432:                        }
                   1433:                        if(!strnicmp(buf, "FROM:",5)) {
                   1434:                                p=strchr(buf+5,'<');
                   1435:                                if(p) {
                   1436:                                        p++;
                   1437:                                        tp=strchr(p,'>');
                   1438:                                        if(tp) *tp=0;
                   1439:                                        sprintf(sender_addr,"%.*s",(int)sizeof(sender_addr)-1,p);
                   1440:                                } else {
                   1441:                                        p=buf+5;
                   1442:                                        while(*p && *p<=' ') p++;
                   1443:                                        sprintf(sender_addr,"%.*s",(int)sizeof(sender_addr)-1,p);
                   1444:                                }
                   1445:                                nettype=NET_INTERNET;
                   1446:                                smb_hfield(&msg, SENDERNETTYPE, sizeof(nettype), &nettype);
                   1447:                                smb_hfield(&msg, SENDERNETADDR, (ushort)strlen(sender_addr), sender_addr);
                   1448:                        
                   1449:                                p=buf+5;
                   1450:                                while(*p && *p<=' ') p++;
                   1451:                                if(*p=='"') { 
                   1452:                                        p++;
                   1453:                                        tp=strchr(p,'"');
                   1454:                                } else if(*p=='<') {
                   1455:                                        p++;
                   1456:                                        tp=strchr(p,'>');
                   1457:                                } else
                   1458:                                        tp=strchr(p,'<');
                   1459:                                if(tp) *tp=0;
                   1460:                                truncsp(p);
                   1461:                                sprintf(sender,"%.*s",(int)sizeof(sender)-1,p);
                   1462:                                smb_hfield(&msg, SENDER, (ushort)strlen(sender), sender);
                   1463:                                continue;
                   1464:                        }
                   1465:                        if(!strnicmp(buf, "DATE:",5)) {
                   1466:                                p=buf+5;
                   1467:                                while(*p && *p<=' ') p++;
                   1468: /*                             lprintf("Sent: %s",p); */
                   1469:                                memset(&tm,0,sizeof(tm));
                   1470:                                while(*p && !isdigit(*p)) p++;
                   1471:                                /* DAY */
                   1472:                                tm.tm_mday=atoi(p);
                   1473:                                while(*p && isdigit(*p)) p++;
                   1474:                                /* MONTH */
                   1475:                                while(*p && *p<=' ') p++;
                   1476:                                sprintf(month,"%3.3s",p);
                   1477:                                if(!stricmp(month,"jan"))
                   1478:                                        tm.tm_mon=0;
                   1479:                                else if(!stricmp(month,"feb"))
                   1480:                                        tm.tm_mon=1;
                   1481:                                else if(!stricmp(month,"mar"))
                   1482:                                        tm.tm_mon=2;
                   1483:                                else if(!stricmp(month,"apr"))
                   1484:                                        tm.tm_mon=3;
                   1485:                                else if(!stricmp(month,"may"))
                   1486:                                        tm.tm_mon=4;
                   1487:                                else if(!stricmp(month,"jun"))
                   1488:                                        tm.tm_mon=5;
                   1489:                                else if(!stricmp(month,"jul"))
                   1490:                                        tm.tm_mon=6;
                   1491:                                else if(!stricmp(month,"aug"))
                   1492:                                        tm.tm_mon=7;
                   1493:                                else if(!stricmp(month,"sep"))
                   1494:                                        tm.tm_mon=8;
                   1495:                                else if(!stricmp(month,"oct"))
                   1496:                                        tm.tm_mon=9;
                   1497:                                else if(!stricmp(month,"nov"))
                   1498:                                        tm.tm_mon=10;
                   1499:                                else
                   1500:                                        tm.tm_mon=11;
                   1501:                                p+=4;
                   1502:                                /* YEAR */
                   1503:                                tm.tm_year=atoi(p);
                   1504:                                if(tm.tm_year>1900)
                   1505:                                        tm.tm_year-=1900;
                   1506:                                while(*p && isdigit(*p)) p++;
                   1507:                                /* HOUR */
                   1508:                                while(*p && *p<=' ') p++;
                   1509:                                tm.tm_hour=atoi(p);
                   1510:                                while(*p && isdigit(*p)) p++;
                   1511:                                /* MINUTE */
                   1512:                                if(*p) p++;
                   1513:                                tm.tm_min=atoi(p);
                   1514:                                while(*p && isdigit(*p)) p++;
                   1515:                                /* SECONDS */
                   1516:                                if(*p) p++;
                   1517:                                tm.tm_sec=atoi(p);
                   1518:                                while(*p && isdigit(*p)) p++;
                   1519:                                /* TIME ZONE */
                   1520:                                while(*p && *p<=' ') p++;
                   1521:                                if(*p && (isdigit(*p) || *p=='-')) { /* HHMM or -HHMM format */
                   1522:                                        sprintf(str,"%.*s",*p=='-'? 3:2,p);
                   1523:                                        msg.hdr.when_written.zone=atoi(str)*60;
                   1524:                                        p+=(*p=='-') ? 3:2;
                   1525:                                        msg.hdr.when_written.zone+=atoi(p);
                   1526:                                }
                   1527:                                else if(!strnicmp(p,"PDT",3))
                   1528:                                        msg.hdr.when_written.zone=(short)PDT;
                   1529:                                else if(!strnicmp(p,"MDT",3))
                   1530:                                        msg.hdr.when_written.zone=(short)MDT;
                   1531:                                else if(!strnicmp(p,"CDT",3))
                   1532:                                        msg.hdr.when_written.zone=(short)CDT;
                   1533:                                else if(!strnicmp(p,"EDT",3))
                   1534:                                        msg.hdr.when_written.zone=(short)EDT;
                   1535:                                else if(!strnicmp(p,"PST",3))
                   1536:                                        msg.hdr.when_written.zone=(short)PST;
                   1537:                                else if(!strnicmp(p,"MST",3))
                   1538:                                        msg.hdr.when_written.zone=(short)MST;
                   1539:                                else if(!strnicmp(p,"CST",3))
                   1540:                                        msg.hdr.when_written.zone=(short)CST;
                   1541:                                else if(!strnicmp(p,"EST",3))
                   1542:                                        msg.hdr.when_written.zone=(short)EST;
                   1543:                                msg.hdr.when_written.time=mktime(&tm);
                   1544:                                continue;
                   1545:                        }
                   1546:                        if(!strnicmp(buf, "MESSAGE-ID:",11)) {
                   1547:                                p=buf+11;
                   1548:                                while(*p && *p<=' ') p++;
                   1549:                                smb_hfield(&msg, RFC822MSGID, (ushort)strlen(p), p);
                   1550:                                continue;
                   1551:                        }
                   1552:                        if(!strnicmp(buf, "IN-REPLY-TO:",12)) {
                   1553:                                p=buf+12;
                   1554:                                while(*p && *p<=' ') p++;
                   1555:                                smb_hfield(&msg, RFC822REPLYID, (ushort)strlen(p), p);
                   1556:                                continue;
                   1557:                        }
                   1558:                        /* Fall-through */
                   1559:                        smb_hfield(&msg, RFC822HEADER, (ushort)strlen(buf), buf);
                   1560:                        continue;
                   1561:                }
                   1562:                lprintf("%04d SMTP RX: %s", socket, buf);
                   1563:                if(!strnicmp(buf,"HELO",4)) {
                   1564:                        p=buf+4;
                   1565:                        while(*p && *p<=' ') p++;
                   1566:                        sprintf(hello_name,"%.*s",(int)sizeof(hello_name)-1,p);
                   1567:                        sockprintf(socket,"250 %s",scfg.sys_inetaddr);
                   1568:                        esmtp=FALSE;
                   1569:                        state=SMTP_STATE_HELO;
                   1570:                        continue;
                   1571:                }
                   1572:                if(!strnicmp(buf,"EHLO",4)) {
                   1573:                        p=buf+4;
                   1574:                        while(*p && *p<=' ') p++;
                   1575:                        sprintf(hello_name,"%.*s",(int)sizeof(hello_name)-1,p);
                   1576:                        sockprintf(socket,"250 %s",scfg.sys_inetaddr);
                   1577:                        esmtp=TRUE;
                   1578:                        state=SMTP_STATE_HELO;
                   1579:                        continue;
                   1580:                }
                   1581:                if(!stricmp(buf,"QUIT")) {
                   1582:                        sockprintf(socket,"221 %s Service closing transmission channel",scfg.sys_inetaddr);
                   1583:                        break;
                   1584:                } 
                   1585:                if(!stricmp(buf,"NOOP")) {
                   1586:                        sockprintf(socket, SMTP_OK);
                   1587:                        continue;
                   1588:                }
                   1589:                if(state<SMTP_STATE_HELO) {
                   1590:                        /* RFC 821 4.1.1 "The first command in a session must be the HELO command." */
                   1591:                        lprintf("%04d !SMTP Missing HELO command",socket);
                   1592:                        sockprintf(socket, SMTP_BADSEQ);
                   1593:                        continue;
                   1594:                }
                   1595:                if(!stricmp(buf,"TURN")) {
                   1596:                        sockprintf(socket,"502 command not supported");
                   1597:                        continue;
                   1598:                }
                   1599:                if(!stricmp(buf,"RSET")) {
                   1600:                        smb_freemsgmem(&msg);
                   1601:                        memset(&msg,0,sizeof(smbmsg_t));                /* Initialize message header */
                   1602:                        reverse_path[0]=0;
                   1603:                        sender[0]=0;
                   1604:                        sender_addr[0]=0;
                   1605:                        sockprintf(socket,SMTP_OK);
                   1606:                        rewind(rcptlst);
                   1607:                        chsize(fileno(rcptlst),0);
                   1608:                        state=SMTP_STATE_HELO;
                   1609:                        continue;
                   1610:                }
                   1611:                if(!strnicmp(buf,"MAIL FROM:",10)) {
                   1612:                        smb_freemsgmem(&msg);
                   1613:                        memset(&msg,0,sizeof(smbmsg_t));                /* Initialize message header */
                   1614:                        memcpy(msg.hdr.id,"SHD\x1a",4);
                   1615:                        msg.hdr.version=smb_ver();
                   1616:                        msg.hdr.when_imported.time=time(NULL);
                   1617:                        msg.hdr.when_imported.zone=scfg.sys_timezone;
                   1618:                        p=buf+10;
                   1619:                        while(*p && *p<=' ') p++;
                   1620:                        sprintf(reverse_path,"%.*s",(int)sizeof(reverse_path)-1,p);
                   1621:                        sender[0]=0;
                   1622:                        sender_addr[0]=0;
                   1623:                        if(spy==NULL && trashcan(&scfg,reverse_path,"smtpspy")) {
                   1624:                                sprintf(str,"%sSMTPSPY.TXT", scfg.data_dir);
                   1625:                                spy=fopen(str,"a");
                   1626:                        }
                   1627:                        sockprintf(socket,SMTP_OK);
                   1628:                        state=SMTP_STATE_MAIL_FROM;
                   1629:                        continue;
                   1630:                }
                   1631: #if 0  /* No one uses this command */
                   1632:                if(!strnicmp(buf,"VRFY",4)) {
                   1633:                        p=buf+4;
                   1634:                        while(*p && *p<=' ') p++;
                   1635:                        if(*p==0) {
                   1636:                                sockprintf(socket,"550 No user specified.");
                   1637:                                continue;
                   1638:                        }
                   1639: #endif
                   1640: 
                   1641: 
                   1642: 
                   1643:                if(!strnicmp(buf,"RCPT TO:",8)) {
                   1644: 
                   1645:                        if(state<SMTP_STATE_MAIL_FROM) {
                   1646:                                lprintf("%04d !SMTP Missing 'MAIL' command",socket);
                   1647:                                sockprintf(socket, SMTP_BADSEQ);
                   1648:                                continue;
                   1649:                        }
                   1650: 
                   1651:                        sprintf(str,"%.*s",(int)sizeof(str)-1,buf+8);
                   1652:                        p=str;
                   1653:                        while(*p && *p<=' ') p++;
                   1654: 
                   1655:                        if(*p=='<') p++;                                /* Skip '<' */
                   1656:                        tp=strchr(str,'>');                             /* Truncate '>' */
                   1657:                        if(tp!=NULL) *tp=0;
                   1658: 
                   1659:                        tp=strrchr(str,'@');
                   1660:                        if(tp!=NULL) {
                   1661:                                
                   1662:                                /* RELAY */
                   1663:                                if(stricmp(tp+1,scfg.sys_inetaddr) && 
                   1664:                                        resolve_ip(tp+1)!=server_addr.sin_addr.s_addr) {
                   1665: 
                   1666:                                        if(!trashcan(&scfg,host_name,"relay") && 
                   1667:                                                !trashcan(&scfg,host_ip,"relay")) {
                   1668:                                                lprintf("%04d !SMTP ILLEGAL RELAY ATTEMPT from %s [%s] to %s"
                   1669:                                                        ,socket, host_name, host_ip, tp+1);
                   1670:                                                sockprintf(socket, "550 Relay not allowed.");
                   1671:                                                continue;
                   1672:                                        }
                   1673: 
                   1674:                                        lprintf("%04d SMTP Relaying to external mail service: %s"
                   1675:                                                ,socket, tp+1);
                   1676: 
                   1677:                                        fprintf(rcptlst,"0\n%.*s\n%.*s\n"
                   1678:                                                ,(int)sizeof(rcpt_name)-1,p
                   1679:                                                ,(int)sizeof(rcpt_addr)-1,p);
                   1680:                                        
                   1681:                                        sockprintf(socket,SMTP_OK);
                   1682:                                        state=SMTP_STATE_RCPT_TO;
                   1683:                                        continue;
                   1684:                                }
                   1685:                                *tp=0;  /* truncate at '@' */
                   1686:                        }
                   1687:                        while(*p && !isalnum(*p)) p++;  /* Skip '<' or '"' */
                   1688:                        tp=strrchr(p,'"');      
                   1689:                        if(tp!=NULL) *tp=0;     /* truncate at '"' */
                   1690: 
                   1691:                        p=alias(p,alias_buf);
                   1692: 
                   1693:                                                                                        /* RX by sysop alias */
                   1694:                        if(!stricmp(p,"SYSOP") || !stricmp(p,scfg.sys_id) 
                   1695:                                || !stricmp(p,"POSTMASTER") || !stricmp(p,scfg.sys_op))
                   1696:                                usernum=1;
                   1697:                        else if(startup->options&MAIL_OPT_ALLOW_RX_BY_NUMBER 
                   1698:                                && isdigit(*p)) {
                   1699:                                usernum=atoi(p);                        /* RX by user number */
                   1700:                                /* verify usernum */
                   1701:                                username(&scfg,usernum,str);
                   1702:                                if(!str[0] || !stricmp(str,"DELETED USER"))
                   1703:                                        usernum=0;
                   1704:                                p=str;
                   1705:                        } else {
                   1706:                                usernum=matchuser(&scfg,p);     /* RX by "user alias", "user.alias" or "user_alias" */
                   1707: 
                   1708:                                if(!usernum) { /* RX by "real name", "real.name", or "sysop.alias" */
                   1709:                                        
                   1710:                                        /* convert "user.name" to "user name" */
                   1711:                                        sprintf(rcpt_name,"%.*s",sizeof(rcpt_name)-1,p);
                   1712:                                        for(tp=rcpt_name;*tp;tp++)      
                   1713:                                                if(*tp=='.') *tp=' ';
                   1714: 
                   1715:                                        if(!stricmp(rcpt_name,scfg.sys_op))
                   1716:                                                usernum=1;                      /* RX by "sysop.alias" */
                   1717: 
                   1718:                                        if(!usernum)                    /* RX by "real name" */
                   1719:                                                usernum=userdatdupe(&scfg, 0, U_NAME, LEN_NAME, p, FALSE);
                   1720: 
                   1721:                                        if(!usernum)                    /* RX by "real.name" */
                   1722:                                                usernum=userdatdupe(&scfg, 0, U_NAME, LEN_NAME, rcpt_name, FALSE);
                   1723:                                }
                   1724:                        }
                   1725:                        if(!usernum) {
                   1726:                                lprintf("%04d !SMTP UNKNOWN USER: %s", socket, buf+8);
                   1727:                                sockprintf(socket, "550 Unknown User: %s", buf+8);
                   1728:                                continue;
                   1729:                        }
                   1730:                        user.number=usernum;
                   1731:                        if((i=getuserdat(&scfg, &user))!=0) {
                   1732:                                lprintf("%04d !SMTP ERROR %d getting data on user #%u (%s)"
                   1733:                                        ,socket, i, usernum, p);
                   1734:                                sockprintf(socket, "550 Unknown User: %s", buf+8);
                   1735:                                continue;
                   1736:                        }
                   1737:                        if(user.misc&(DELETED|INACTIVE)) {
                   1738:                                lprintf("%04d !SMTP DELETED or INACTIVE user #%u (%s)"
                   1739:                                        ,socket, usernum, p);
                   1740:                                sockprintf(socket, "550 Unknown User: %s", buf+8);
                   1741:                                continue;
                   1742:                        }
                   1743: #if 0  /* implement later */
                   1744:                        if(useron.etoday>=cfg.level_emailperday[useron.level]
                   1745:                                && !(useron.rest&FLAG('Q'))) {
                   1746:                                bputs(text[TooManyEmailsToday]);
                   1747:                                continue; }
                   1748: #endif
                   1749: 
                   1750:                        fprintf(rcptlst,"%u\n%.*s\n",user.number,(int)sizeof(rcpt_name)-1,p);
                   1751: 
                   1752:                        /* Forward to Internet */
                   1753:                        tp=strrchr(user.netmail,'@');
                   1754:                        if(scfg.sys_misc&SM_FWDTONET && user.misc&NETMAIL 
                   1755:                                && tp && strchr(tp,'.') && !strchr(tp,'/') 
                   1756:                                && !strstr(tp,scfg.sys_inetaddr)) {
                   1757:                                lprintf("%04d SMTP Forwarding to: %s"
                   1758:                                        ,socket, user.netmail);
                   1759:                                fprintf(rcptlst,"%s\n",user.netmail);
                   1760:                                sockprintf(socket,"251 User not local; will forward to %s", user.netmail);
                   1761:                        } else { /* Local (no-forward) */
                   1762:                                fprintf(rcptlst,"#%u\n",usernum);
                   1763:                                sockprintf(socket,SMTP_OK);
                   1764:                        }
                   1765:                        state=SMTP_STATE_RCPT_TO;
                   1766:                        continue;
                   1767:                }
                   1768:                if(!strnicmp(buf,"DATA",4)) {
                   1769:                        if(state<SMTP_STATE_RCPT_TO) {
                   1770:                                lprintf("%04d !SMTP Missing 'RCPT TO' command", socket);
                   1771:                                sockprintf(socket, SMTP_BADSEQ);
                   1772:                                continue;
                   1773:                        }
                   1774:                        if(msgtxt!=NULL)
                   1775:                                fclose(msgtxt);
                   1776:                        sprintf(msgtxt_fname,"%sSMTP%d.RX", scfg.data_dir, socket);
                   1777:                        if((msgtxt=fopen(msgtxt_fname,"w+b"))==NULL) {
                   1778:                                lprintf("%04d !SMTP Error %d opening %s"
                   1779:                                        ,socket, errno, msgtxt_fname);
                   1780:                                sockprintf(socket, "452 Insufficient system storage");
                   1781:                                continue;
                   1782:                        }
                   1783:                        sockprintf(socket, "354 send the mail data, end with <CRLF>.<CRLF>");
                   1784:                        state=SMTP_STATE_DATA_HEADER;
                   1785:                        continue;
                   1786:                }
                   1787:                sockprintf(socket,"500 Syntax error");
                   1788:                lprintf("%04d !SMTP UNSUPPORTED COMMAND: %s", socket, buf);
                   1789:        }
                   1790: 
                   1791:        /* Free up resources here */
                   1792:        mail_close_socket(socket);
                   1793: 
                   1794:        smb_freemsgmem(&msg);
                   1795: 
                   1796:        if(msgtxt!=NULL) {
                   1797:                fclose(msgtxt);
                   1798:                if(!(startup->options&MAIL_OPT_DEBUG_RX_BODY))
                   1799:                        unlink(msgtxt_fname);
                   1800:        }
                   1801:        if(rcptlst!=NULL) {
                   1802:                fclose(rcptlst);
                   1803:                unlink(rcptlst_fname);
                   1804:        }
                   1805:        if(spy!=NULL)
                   1806:                fclose(spy);
                   1807: 
                   1808:        status(STATUS_WFC);
                   1809: 
                   1810:        lprintf("%04d SMTP RX Session thread terminated", socket);
                   1811:        active_clients--;
                   1812:        update_clients();
                   1813:        client_off(socket);
                   1814: 
                   1815:        thread_down();
                   1816: }
                   1817: 
                   1818: BOOL bounce(smb_t* smb, smbmsg_t* msg, char* err, BOOL immediate)
                   1819: {
                   1820:        char            str[128],full_err[512];
                   1821:        int                     i;
                   1822:        ushort          agent=AGENT_PROCESS;
                   1823:        smbmsg_t        newmsg;
                   1824: 
                   1825:        if((i=smb_lockmsghdr(smb,msg))!=0) {
                   1826:                lprintf("0000 !BOUNCE ERROR %d locking message header #%lu"
                   1827:                        ,i,msg->hdr.number);
                   1828:                return(FALSE);
                   1829:        }
                   1830: 
                   1831:        msg->hdr.delivery_attempts++;
                   1832:        if((i=smb_putmsg(smb,msg))!=0) {
                   1833:                lprintf("0000 !BOUNCE ERROR %d incrementing delivery attempt counter",i);
                   1834:                smb_unlockmsghdr(smb,msg);
                   1835:                return(FALSE);
                   1836:        }
                   1837: 
                   1838:        lprintf("0000 !Delivery attempt #%u FAILED for message #%lu from %s to %s"
                   1839:                ,msg->hdr.delivery_attempts, msg->hdr.number
                   1840:                ,msg->from, msg->to_net.addr);
                   1841: 
                   1842:        if(!immediate && msg->hdr.delivery_attempts<startup->max_delivery_attempts) {
                   1843:                smb_unlockmsghdr(smb,msg);
                   1844:                return(TRUE);
                   1845:        }
                   1846:        
                   1847:        lprintf("0000 !Bouncing message back to %s", msg->from);
                   1848: 
                   1849:        newmsg=*msg;
                   1850:        /* Mark original message as deleted */
                   1851:        msg->hdr.attr|=MSG_DELETE;
                   1852:        msg->idx.attr=msg->hdr.attr;
                   1853:        if((i=smb_putmsg(smb,msg))!=0) {
                   1854:                lprintf("0000 !BOUNCE ERROR %d deleting message",i);
                   1855:                smb_unlockmsghdr(smb,msg);
                   1856:                return(FALSE);
                   1857:        }
                   1858:        smb_unlockmsghdr(smb,msg);
                   1859: 
                   1860:        newmsg.hfield=NULL;
                   1861:        newmsg.hfield_dat=NULL;
                   1862:        newmsg.total_hfields=0;
                   1863:        newmsg.idx.to=newmsg.idx.from;
                   1864:        newmsg.idx.from=0;
                   1865:        newmsg.hdr.delivery_attempts=0;
                   1866: 
                   1867:        smb_hfield(&newmsg, RECIPIENT, (ushort)strlen(newmsg.from), newmsg.from);
                   1868:        if(newmsg.idx.to) {
                   1869:                sprintf(str,"%u",newmsg.idx.to);
                   1870:                smb_hfield(&newmsg, RECIPIENTEXT, (ushort)strlen(str), str);
                   1871:        }
                   1872:        smb_hfield(&newmsg, RECIPIENTAGENT, sizeof(ushort), &newmsg.from_agent);
                   1873:        smb_hfield(&newmsg, RECIPIENTNETTYPE, sizeof(newmsg.from_net.type), &newmsg.from_net.type);
                   1874:        if(newmsg.from_net.type) 
                   1875:                smb_hfield(&newmsg, RECIPIENTNETADDR, (ushort)strlen(newmsg.from_net.addr)
                   1876:                        ,newmsg.from_net.addr);
                   1877:        strcpy(str,"Mail Delivery Subsystem");
                   1878:        smb_hfield(&newmsg, SENDER, (ushort)strlen(str), str);
                   1879:        smb_hfield(&newmsg, SENDERAGENT, sizeof(agent), &agent);
                   1880:        
                   1881:        /* Put error message in subject for now */
                   1882:        sprintf(full_err,"Delivery failure of message to %s after %u attempts: %s"
                   1883:                ,(char*)msg->to_net.addr, msg->hdr.delivery_attempts, err);
                   1884:        smb_hfield(&newmsg, SUBJECT, (ushort)strlen(full_err), full_err);
                   1885: 
                   1886:        if((i=smb_addmsghdr(smb,&newmsg,SMB_SELFPACK))!=0)
                   1887:                lprintf("0000 !BOUNCE ERROR %d adding message header",i);
                   1888: 
                   1889:        newmsg.dfield=NULL;                             /* Don't double-free the data fields */
                   1890:        newmsg.hdr.total_dfields=0;
                   1891:        smb_freemsgmem(&newmsg);
                   1892: 
                   1893:        return(TRUE);
                   1894: }
                   1895: 
                   1896: #ifdef __BORLANDC__
                   1897: #pragma argsused
                   1898: #endif
                   1899: static void sendmail_thread(void* arg)
                   1900: {
                   1901:        int                     i,j;
                   1902:        char            to[128];
                   1903:        char            mx[128];
                   1904:        char            mx2[128];
                   1905:        char            err[128];
                   1906:        char            buf[512];
                   1907:        char            fromaddr[256];
                   1908:        char*           server;
                   1909:        char*           msgtxt=NULL;
                   1910:        char*           p;
                   1911:        ulong           offset;
                   1912:        ulong           last_msg=0;
                   1913:        ulong           total_msgs;
                   1914:        ulong           ip_addr;
                   1915:        ulong           dns;
                   1916:        BOOL            success;
                   1917:        SOCKET          sock=INVALID_SOCKET;
                   1918:        SOCKADDR_IN     addr;
                   1919:        SOCKADDR_IN     server_addr;
                   1920:        time_t          last_scan=0;
                   1921:        smb_t           smb;
                   1922:        smbmsg_t        msg;
                   1923: 
                   1924:        sendmail_running=TRUE;
                   1925: 
                   1926:        thread_up();
                   1927: 
                   1928:        lprintf("0000 SendMail thread started");
                   1929: 
                   1930:        memset(&msg,0,sizeof(msg));
                   1931:        memset(&smb,0,sizeof(smb));
                   1932: 
                   1933:        while(server_socket!=INVALID_SOCKET) {
                   1934: 
                   1935:                if(startup->options&MAIL_OPT_NO_SENDMAIL) {
                   1936:                        mswait(1000);
                   1937:                        continue;
                   1938:                }
                   1939: 
                   1940:                if(active_sendmail!=0) {
                   1941:                        active_sendmail=0;
                   1942:                        update_clients();
                   1943:                }
                   1944: 
                   1945:                smb_close(&smb);
                   1946: 
                   1947:                if(sock!=INVALID_SOCKET) {
                   1948:                        mail_close_socket(sock);
                   1949:                        sock=INVALID_SOCKET;
                   1950:                }
                   1951: 
                   1952:                if(msgtxt!=NULL) {
                   1953:                        smb_freemsgtxt(msgtxt);
                   1954:                        msgtxt=NULL;
                   1955:                }
                   1956: 
                   1957:                smb_freemsgmem(&msg);
                   1958: 
                   1959:                mswait(3000);
                   1960: 
                   1961:                sprintf(smb.file,"%smail",scfg.data_dir);
                   1962:                if((i=smb_open(&smb))!=0) 
                   1963:                        continue;
                   1964:                if((i=smb_locksmbhdr(&smb))!=0)
                   1965:                        continue;
                   1966:                if((i=smb_getstatus(&smb))!=0) {
                   1967:                        smb_unlocksmbhdr(&smb);
                   1968:                        continue;
                   1969:                }
                   1970:                smb_unlocksmbhdr(&smb);
                   1971:                if(smb.status.last_msg==last_msg && time(NULL)-last_scan<startup->rescan_frequency)
                   1972:                        continue;
                   1973:                last_msg=smb.status.last_msg;
                   1974:                last_scan=time(NULL);
                   1975:                total_msgs=smb.status.total_msgs;
                   1976:                smb_rewind(smb.sid_fp);
                   1977:                for(offset=0;offset<total_msgs;offset++) {
                   1978: 
                   1979:                        if(active_sendmail!=0) {
                   1980:                                active_sendmail=0;
                   1981:                                update_clients();
                   1982:                        }
                   1983: 
                   1984:                        if(sock!=INVALID_SOCKET) {
                   1985:                                mail_close_socket(sock);
                   1986:                                sock=INVALID_SOCKET;
                   1987:                        }
                   1988: 
                   1989:                        if(msgtxt!=NULL) {
                   1990:                                smb_freemsgtxt(msgtxt);
                   1991:                                msgtxt=NULL;
                   1992:                        }
                   1993: 
                   1994:                        smb_freemsgmem(&msg);
                   1995: 
                   1996:                        smb_fseek(smb.sid_fp, offset*sizeof(msg.idx), SEEK_SET);
                   1997:                        if(smb_fread(&msg.idx, sizeof(msg.idx), smb.sid_fp) != sizeof(msg.idx))
                   1998:                                break;
                   1999:                        if(msg.idx.attr&MSG_DELETE)     /* Marked for deletion */
                   2000:                                continue;
                   2001:                        if(msg.idx.to)  /* Local */
                   2002:                                continue;
                   2003:                        msg.offset=offset;
                   2004: 
                   2005:                        if((i=smb_lockmsghdr(&smb,&msg))!=0) {
                   2006:                                lprintf("0000 !SEND ERROR %d locking message header #%lu"
                   2007:                                        ,i,msg.idx.number);
                   2008:                                continue;
                   2009:                        }
                   2010:                        if((i=smb_getmsghdr(&smb,&msg))!=0) {
                   2011:                                smb_unlockmsghdr(&smb,&msg);
                   2012:                                lprintf("0000 !SEND ERROR %d reading message header #%lu"
                   2013:                                        ,i,msg.idx.number);
                   2014:                                continue; 
                   2015:                        }
                   2016:                        smb_unlockmsghdr(&smb,&msg);
                   2017: 
                   2018:                        if(msg.to_net.type!=NET_INTERNET) 
                   2019:                                continue;
                   2020: 
                   2021:                        active_sendmail=1;
                   2022:                        update_clients();
                   2023: 
                   2024:                        lprintf("0000 SEND Message #%lu from %s to %s"
                   2025:                                ,msg.hdr.number, msg.from, msg.to_net.addr);
                   2026:                        status("SendMail");
                   2027: #ifdef _WIN32
                   2028:                        if(startup->outbound_sound[0] && !(startup->options&MAIL_OPT_MUTE)) 
                   2029:                                PlaySound(startup->outbound_sound, NULL, SND_ASYNC|SND_FILENAME);
                   2030: #endif
                   2031: 
                   2032:                        lprintf("0000 SEND getting message text");
                   2033:                        if((msgtxt=smb_getmsgtxt(&smb,&msg,GETMSGTXT_TAILS))==NULL) {
                   2034:                                lprintf("0000 !SEND ERROR retrieving message text");
                   2035:                                continue;
                   2036:                        }
                   2037: 
                   2038:                        if(startup->options&MAIL_OPT_RELAY_TX)  
                   2039:                                server=startup->relay_server;
                   2040:                        else {
                   2041:                                sprintf(to,"%.*s",(int)sizeof(to)-1,(char*)msg.to_net.addr);
                   2042:                                p=strrchr(to,'>');      /* Truncate '>' */
                   2043:                                if(p!=NULL) *p=0;
                   2044: 
                   2045:                                p=strrchr(to,'@');
                   2046:                                if(p==NULL) {
                   2047:                                        lprintf("0000 !SEND INVALID destination address: %s", to);
                   2048:                                        sprintf(err,"Invalid destination address: %s", to);
                   2049:                                        bounce(&smb,&msg,err,TRUE);
                   2050:                                        continue;
                   2051:                                }
                   2052:                                if((dns=resolve_ip(startup->dns_server))==0) 
                   2053:                                        continue;
                   2054:                                p++;
                   2055:                                lprintf("0000 SEND getting MX records for %s from %s",p,startup->dns_server);
                   2056:                                if((i=dns_getmx(p, mx, mx2, startup->interface_addr, dns
                   2057:                                        ,startup->options&MAIL_OPT_USE_TCP_DNS ? TRUE : FALSE))!=0) {
                   2058:                                        lprintf("0000 !SEND ERROR %d obtaining MX records for %s from %s"
                   2059:                                                ,i,p,startup->dns_server);
                   2060:                                        sprintf(err,"Error %d obtaining MX record for %s",i,p);
                   2061:                                        bounce(&smb,&msg,err,FALSE);
                   2062:                                        continue;
                   2063:                                }
                   2064:                                server=mx;
                   2065:                        }
                   2066: 
                   2067: 
                   2068:                        lprintf("0000 SEND opening socket");
                   2069:                        if((sock=mail_open_socket(SOCK_STREAM))==INVALID_SOCKET) {
                   2070:                                lprintf("0000 !SEND ERROR %d opening socket", ERROR_VALUE);
                   2071:                                continue;
                   2072:                        }
                   2073: 
                   2074:                        lprintf("%04d SEND socket opened",sock);
                   2075: 
                   2076:                        memset(&addr,0,sizeof(addr));
                   2077:                        addr.sin_addr.s_addr = htonl(startup->interface_addr);
                   2078:                        addr.sin_family = AF_INET;
                   2079: 
                   2080:                        lprintf("%04d SEND binding socket",sock);
                   2081:                        if((i=bind(sock, (struct sockaddr *) &addr, sizeof (addr)))!=0) {
                   2082:                                lprintf("%04d !SEND ERROR %d (%d) binding socket", sock, i, ERROR_VALUE);
                   2083:                                continue;
                   2084:                        }
                   2085: 
                   2086:                        strcpy(err,"UNKNOWN ERROR");
                   2087:                        success=FALSE;
                   2088:                        for(j=0;j<2 && !success;j++) {
                   2089:                                if(j) {
                   2090:                                        if(startup->options&MAIL_OPT_RELAY_TX || !mx2[0])
                   2091:                                                break;
                   2092:                                        server=mx2;     /* Give second mx record a try */
                   2093:                                }
                   2094:                                
                   2095:                                lprintf("%04d SEND resolving SMTP host name: %s", sock, server);
                   2096:                                ip_addr=resolve_ip(server);
                   2097:                                if(!ip_addr)  {
                   2098:                                        sprintf(err,"Failed to resolve SMTP host name: %s",server);
                   2099:                                        continue;
                   2100:                                }
                   2101: 
                   2102:                                memset(&server_addr,0,sizeof(server_addr));
                   2103:                                server_addr.sin_addr.s_addr = ip_addr;
                   2104:                                server_addr.sin_family = AF_INET;
                   2105:                                if(startup->options&MAIL_OPT_RELAY_TX)
                   2106:                                        server_addr.sin_port = htons(startup->relay_port);
                   2107:                                else
                   2108:                                        server_addr.sin_port = htons(IPPORT_SMTP);
                   2109:                                
                   2110:                                lprintf("%04d SEND connecting to port %u on %s [%s]"
                   2111:                                        ,sock
                   2112:                                        ,ntohs(server_addr.sin_port)
                   2113:                                        ,server,inet_ntoa(server_addr.sin_addr));
                   2114:                                if((i=connect(sock, (struct sockaddr *)&server_addr, sizeof(server_addr)))!=0) {
                   2115:                                        lprintf("%04d !SEND ERROR %d (%d) connecting to SMTP server: %s"
                   2116:                                                ,sock
                   2117:                                                ,i,ERROR_VALUE, server);
                   2118:                                        sprintf(err,"Error %d connecting to SMTP server: %s"
                   2119:                                                ,(int)ERROR_VALUE,server);
                   2120:                                        continue;
                   2121:                                }
                   2122:                                success=TRUE;
                   2123:                        }
                   2124:                        if(!success) {  /* Failed to send, so bounce */
                   2125:                                bounce(&smb,&msg,err,FALSE);    
                   2126:                                continue;
                   2127:                        }
                   2128: 
                   2129:                        lprintf("%04d SEND connected to %s",sock,server);
                   2130: 
                   2131:                        /* HELO */
                   2132:                        if(!sockgetrsp(sock,"220",buf,sizeof(buf))) {
                   2133:                                sprintf(err,"%s replied with '%s' instead of 220",server,buf);
                   2134:                                bounce(&smb,&msg,err,buf[0]=='5');
                   2135:                                continue;
                   2136:                        }
                   2137:                        sockprintf(sock,"HELO %s",scfg.sys_inetaddr);
                   2138:                        if(!sockgetrsp(sock,"250", buf, sizeof(buf))) {
                   2139:                                sprintf(err,"%s replied with '%s' instead of 250",server,buf);
                   2140:                                bounce(&smb,&msg,err,buf[0]=='5');
                   2141:                                continue;
                   2142:                        }
                   2143:                        /* MAIL */
                   2144:                        if(msg.from_net.type==NET_INTERNET)
                   2145:                                strcpy(fromaddr,msg.from_net.addr);
                   2146:                        else 
                   2147:                                usermailaddr(fromaddr,msg.from);
                   2148:                        if(fromaddr[0]=='<')
                   2149:                                sockprintf(sock,"MAIL FROM: %s",fromaddr);
                   2150:                        else
                   2151:                                sockprintf(sock,"MAIL FROM: <%s>",fromaddr);
                   2152:                        if(!sockgetrsp(sock,"250", buf, sizeof(buf))) {
                   2153:                                sprintf(err,"%s replied with '%s' instead of 250",server,buf);
                   2154:                                bounce(&smb,&msg,err,buf[0]=='5');
                   2155:                                continue;
                   2156:                        }
                   2157:                        /* RCPT */
                   2158:                        if(*((char*)msg.to_net.addr)=='<')
                   2159:                                sockprintf(sock,"RCPT TO: %s", (char*)msg.to_net.addr);
                   2160:                        else
                   2161:                                sockprintf(sock,"RCPT TO: <%s>", (char*)msg.to_net.addr);
                   2162:                        if(!sockgetrsp(sock,"250", buf, sizeof(buf))) {
                   2163:                                sprintf(err,"%s replied with '%s' instead of 250",server,buf);
                   2164:                                bounce(&smb,&msg,err,buf[0]=='5');
                   2165:                                continue;
                   2166:                        }
                   2167:                        /* DATA */
                   2168:                        sockprintf(sock,"DATA");
                   2169:                        if(!sockgetrsp(sock,"354", buf, sizeof(buf))) {
                   2170:                                sprintf(err,"%s replied with '%s' instead of 354",server,buf);
                   2171:                                bounce(&smb,&msg,err,buf[0]=='5');
                   2172:                                continue;
                   2173:                        }
                   2174:                        lprintf("%04d SEND sending message text (%u bytes)"
                   2175:                                ,sock, strlen(msgtxt));
                   2176:                        sockmsgtxt(sock,&msg,msgtxt,fromaddr,-1);
                   2177:                        if(!sockgetrsp(sock,"250", buf, sizeof(buf))) {
                   2178:                                sprintf(err,"%s replied with '%s' instead of 250",server,buf);
                   2179:                                bounce(&smb,&msg,err,buf[0]=='5');
                   2180:                                continue;
                   2181:                        }
                   2182:                        lprintf("%04d SEND message transfer complete", sock);
                   2183: 
                   2184:                        msg.hdr.attr|=MSG_DELETE;
                   2185:                        msg.idx.attr=msg.hdr.attr;
                   2186:                        if((i=smb_lockmsghdr(&smb,&msg))!=0) 
                   2187:                                lprintf("%04d !SEND ERROR %d locking message header #%lu"
                   2188:                                        ,sock
                   2189:                                        ,i,msg.hdr.number);
                   2190:                        if((i=smb_putmsg(&smb,&msg))!=0)
                   2191:                                lprintf("%04d !SEND ERROR %d deleting message #%lu"
                   2192:                                        ,sock
                   2193:                                        ,i,msg.hdr.number);
                   2194:                        smb_unlockmsghdr(&smb,&msg);
                   2195: 
                   2196:                        /* QUIT */
                   2197:                        sockprintf(sock,"QUIT");
                   2198:                        sockgetrsp(sock,"221", buf, sizeof(buf));
                   2199:                        mail_close_socket(sock);
                   2200:                        sock=INVALID_SOCKET;
                   2201:                }                               
                   2202:                status(STATUS_WFC);
                   2203:        }
                   2204:        if(sock!=INVALID_SOCKET)
                   2205:                mail_close_socket(sock);
                   2206: 
                   2207:        smb_freemsgtxt(msgtxt);
                   2208:        smb_freemsgmem(&msg);
                   2209:        smb_close(&smb);
                   2210: 
                   2211:        lprintf("0000 SendMail thread terminated");
                   2212: 
                   2213:        sendmail_running=FALSE;
                   2214: 
                   2215:        thread_down();
                   2216: }
                   2217: 
                   2218: void DLLCALL mail_terminate(void)
                   2219: {
                   2220:        if(server_socket!=INVALID_SOCKET) {
                   2221:        lprintf("%04d MAIL Terminate: closing socket",server_socket);
                   2222:                mail_close_socket(server_socket);
                   2223:            server_socket=INVALID_SOCKET;
                   2224:     }
                   2225: }
                   2226: 
                   2227: static void cleanup(int code)
                   2228: {
                   2229:        if(server_socket!=INVALID_SOCKET) {
                   2230:                mail_close_socket(server_socket);
                   2231:                server_socket=INVALID_SOCKET;
                   2232:        }
                   2233: 
                   2234:        if(pop3_socket!=INVALID_SOCKET) {
                   2235:                mail_close_socket(pop3_socket);
                   2236:                pop3_socket=INVALID_SOCKET;
                   2237:        }
                   2238: 
                   2239:        update_clients();
                   2240: 
                   2241: #ifdef _WINSOCKAPI_    
                   2242:        if(WSAInitialized && WSACleanup()!=0) 
                   2243:                lprintf("0000 !WSACleanup ERROR %d",ERROR_VALUE);
                   2244: #endif
                   2245: 
                   2246:     lprintf("#### Mail Server thread terminated");
                   2247:        status("Down");
                   2248:        if(startup!=NULL && startup->terminated!=NULL)
                   2249:                startup->terminated(code);
                   2250:        thread_down();
                   2251: }
                   2252: 
                   2253: char* DLLCALL mail_ver(void)
                   2254: {
                   2255:        static char ver[256];
                   2256:        char compiler[32];
                   2257: 
                   2258:        COMPILER_DESC(compiler);
                   2259: 
                   2260:        sprintf(ver,"Synchronet Mail Server v%s%s  SMBLIB v%s  "
                   2261:                "Compiled %s %s with %s"
                   2262:                ,MAIL_VERSION
                   2263: #ifdef _DEBUG
                   2264:                ," Debug"
                   2265: #else
                   2266:                ,""
                   2267: #endif
                   2268:                ,smb_lib_ver()
                   2269:                ,__DATE__, __TIME__, compiler
                   2270:                );
                   2271: 
                   2272:        return(ver);
                   2273: }
                   2274: 
                   2275: void DLLCALL mail_server(void* arg)
                   2276: {
                   2277:        char                    compiler[32];
                   2278:        SOCKADDR_IN             server_addr;
                   2279:        SOCKADDR_IN             client_addr;
                   2280:        int                             client_addr_len;
                   2281:        SOCKET                  client_socket;
                   2282:        int                             i;
                   2283:        int                             result;
                   2284:        ulong                   l;
                   2285:        time_t                  t;
                   2286:        time_t                  start;
                   2287:        LINGER                  linger;
                   2288:        fd_set                  socket_set;
                   2289:        SOCKET                  high_socket_set;
                   2290:        pop3_t*                 pop3;
                   2291:        smtp_t*                 smtp;
                   2292:        struct timeval  tv;
                   2293: 
                   2294:        startup=(mail_startup_t*)arg;
                   2295: 
                   2296:     if(startup==NULL) {
                   2297:        sbbs_beep(100,500);
                   2298:        fprintf(stderr, "No startup structure passed!\n");
                   2299:        return;
                   2300:     }
                   2301: 
                   2302:        if(startup->size!=sizeof(mail_startup_t)) {     /* verify size */
                   2303:                sbbs_beep(100,500);
                   2304:                sbbs_beep(300,500);
                   2305:                sbbs_beep(100,500);
                   2306:                fprintf(stderr, "Invalid startup structure!\n");
                   2307:                return;
                   2308:        }
                   2309: 
                   2310:        if(startup->relay_port==0)
                   2311:                startup->relay_port=IPPORT_SMTP;
                   2312: 
                   2313:        thread_up();
                   2314: 
                   2315:        status("Initializing");
                   2316: 
                   2317: #ifdef __unix__                /* Ignore "Broken Pipe" signal */
                   2318:        signal(SIGPIPE,SIG_IGN);
                   2319: #endif
                   2320: 
                   2321:        lprintf("Synchronet Mail Server Version %s%s"
                   2322:                ,MAIL_VERSION
                   2323: #ifdef _DEBUG
                   2324:                ," Debug"
                   2325: #else
                   2326:                ,""
                   2327: #endif
                   2328:                );
                   2329: 
                   2330:        COMPILER_DESC(compiler);
                   2331: 
                   2332:        lprintf("Compiled %s %s with %s", __DATE__, __TIME__, compiler);
                   2333: 
                   2334:        lprintf("SMBLIB v%s (format %x.%02x)",smb_lib_ver(),smb_ver()>>8,smb_ver()&0xff);
                   2335: 
                   2336:        srand(time(NULL));
                   2337: 
                   2338:        if(!(startup->options&MAIL_OPT_LOCAL_TIMEZONE)) {
                   2339:                if(PUTENV("TZ=UCT0"))
                   2340:                        lprintf("!putenv() FAILED");
                   2341:                tzset();
                   2342: 
                   2343:                if((t=checktime())!=0) {   /* Check binary time */
                   2344:                        lprintf("!TIME PROBLEM (%ld)",t);
                   2345:                        cleanup(1);
                   2346:                        return;
                   2347:                }
                   2348:        }
                   2349: 
                   2350:        if(!winsock_startup()) {
                   2351:                cleanup(1);
                   2352:                return;
                   2353:        }
                   2354: 
                   2355:        t=time(NULL);
                   2356:        lprintf("Initializing on %.24s with options: %lx"
                   2357:                ,ctime(&t),startup->options);
                   2358: 
                   2359:        /* Initial configuration and load from CNF files */
                   2360:     memset(&scfg, 0, sizeof(scfg));
                   2361:     sprintf(scfg.ctrl_dir, "%.*s", (int)sizeof(scfg.ctrl_dir)-1
                   2362:        ,startup->ctrl_dir);
                   2363:     lprintf("Loading configuration files from %s", scfg.ctrl_dir);
                   2364:        if(!load_cfg(&scfg, NULL)) {
                   2365:                lprintf("!Failed to load configuration files");
                   2366:                cleanup(1);
                   2367:                return;
                   2368:        }
                   2369: 
                   2370:        if(!startup->max_clients) {
                   2371:                startup->max_clients=scfg.sys_nodes;
                   2372:                if(startup->max_clients<10)
                   2373:                        startup->max_clients=10;
                   2374:        }
                   2375: 
                   2376:        lprintf("Maximum clients: %u",startup->max_clients);
                   2377: 
                   2378:        if(!startup->max_inactivity) 
                   2379:                startup->max_inactivity=120; /* seconds */
                   2380: 
                   2381:        lprintf("Maximum inactivity: %u seconds",startup->max_inactivity);
                   2382: 
                   2383:        active_clients=0;
                   2384:        update_clients();
                   2385: 
                   2386:     /* open a socket and wait for a client */
                   2387: 
                   2388:     server_socket = mail_open_socket(SOCK_STREAM);
                   2389: 
                   2390:        if (server_socket == INVALID_SOCKET) {
                   2391:                lprintf("!ERROR %d opening socket", ERROR_VALUE);
                   2392:                cleanup(1);
                   2393:                return;
                   2394:        }
                   2395: 
                   2396:     lprintf("%04d SMTP socket opened",server_socket);
                   2397: 
                   2398: #if 1
                   2399:        linger.l_onoff=TRUE;
                   2400:     linger.l_linger=5; /* seconds */
                   2401: 
                   2402:        result = setsockopt (server_socket, SOL_SOCKET, SO_LINGER
                   2403:        ,(char *)&linger, sizeof(linger));
                   2404: 
                   2405:        if (result != 0) {
                   2406:                lprintf("%04d !ERROR %d (%d) setting socket options"
                   2407:                        ,server_socket, result, ERROR_VALUE);
                   2408:                cleanup(1);
                   2409:                return;
                   2410:        }
                   2411: #endif
                   2412: 
                   2413:        /*****************************/
                   2414:        /* Listen for incoming calls */
                   2415:        /*****************************/
                   2416:     memset(&server_addr, 0, sizeof(server_addr));
                   2417: 
                   2418:        server_addr.sin_addr.s_addr = htonl(startup->interface_addr);
                   2419:     server_addr.sin_family = AF_INET;
                   2420:     server_addr.sin_port   = htons(startup->smtp_port);
                   2421: 
                   2422:     result = bind(server_socket, (struct sockaddr *) &server_addr
                   2423:        ,sizeof (server_addr));
                   2424: 
                   2425:        if (result != 0) {
                   2426:                lprintf("%04d !ERROR %d (%d) binding SMTP socket to port %u"
                   2427:                        ,server_socket, result, ERROR_VALUE, startup->smtp_port);
                   2428:                cleanup(1);
                   2429:                return;
                   2430:        }
                   2431: 
                   2432:     lprintf("%04d SMTP socket bound to port %u"
                   2433:                ,server_socket, startup->smtp_port);
                   2434: 
                   2435:     result = listen (server_socket, 1);
                   2436: 
                   2437:        if (result != 0) {
                   2438:                lprintf("%04d !ERROR %d (%d) listening on socket"
                   2439:                        ,server_socket, result, ERROR_VALUE);
                   2440:                cleanup(1);
                   2441:                return;
                   2442:        }
                   2443: 
                   2444:        if(startup->options&MAIL_OPT_ALLOW_POP3) {
                   2445: 
                   2446:                /* open a socket and wait for a client */
                   2447: 
                   2448:                pop3_socket = mail_open_socket(SOCK_STREAM);
                   2449: 
                   2450:                if (pop3_socket == INVALID_SOCKET) {
                   2451:                        lprintf("!ERROR %d opening POP3 socket", ERROR_VALUE);
                   2452:                        cleanup(1);
                   2453:                        return;
                   2454:                }
                   2455: 
                   2456:                lprintf("%04d POP3 socket opened",pop3_socket);
                   2457: 
                   2458:                /*****************************/
                   2459:                /* Listen for incoming calls */
                   2460:                /*****************************/
                   2461:                memset(&server_addr, 0, sizeof(server_addr));
                   2462: 
                   2463:                server_addr.sin_addr.s_addr = htonl(startup->interface_addr);
                   2464:                server_addr.sin_family = AF_INET;
                   2465:                server_addr.sin_port   = htons(startup->pop3_port);
                   2466: 
                   2467:                result = bind(pop3_socket, (struct sockaddr *) &server_addr
                   2468:                ,sizeof (server_addr));
                   2469: 
                   2470:                if (result != 0) {
                   2471:                        lprintf("%04d !ERROR %d (%d) binding POP3 socket to port %u"
                   2472:                                ,pop3_socket, result, ERROR_VALUE, startup->pop3_port);
                   2473:                        cleanup(1);
                   2474:                        return;
                   2475:                }
                   2476: 
                   2477:            lprintf("%04d POP3 socket bound to port %u"
                   2478:                        ,pop3_socket, startup->pop3_port);
                   2479: 
                   2480:                result = listen (pop3_socket, 1);
                   2481: 
                   2482:                if (result != 0) {
                   2483:                        lprintf("%04d !ERROR %d (%d) listening on POP3 socket"
                   2484:                                ,pop3_socket, result, ERROR_VALUE);
                   2485:                        cleanup(1);
                   2486:                        return;
                   2487:                }
                   2488:        }
                   2489: 
                   2490:        /* signal caller that we've started up successfully */
                   2491:     if(startup->started!=NULL)
                   2492:        startup->started();
                   2493: 
                   2494:        if(!(startup->options&MAIL_OPT_NO_SENDMAIL))
                   2495:                _beginthread (sendmail_thread, 0, NULL);
                   2496: 
                   2497:        lprintf("%04d Mail Server thread started",server_socket);
                   2498:        status(STATUS_WFC);
                   2499: 
                   2500:        while (server_socket!=INVALID_SOCKET) {
                   2501: 
                   2502:                /* now wait for connection */
                   2503: 
                   2504:                FD_ZERO(&socket_set);
                   2505:                FD_SET(server_socket,&socket_set);
                   2506:                high_socket_set=server_socket+1;
                   2507:                if(startup->options&MAIL_OPT_ALLOW_POP3) {
                   2508:                        FD_SET(pop3_socket,&socket_set);
                   2509:                        if(pop3_socket+1>high_socket_set)
                   2510:                                high_socket_set=pop3_socket+1;
                   2511:                }
                   2512: 
                   2513:                tv.tv_sec=2;
                   2514:                tv.tv_usec=0;
                   2515: 
                   2516:                if((i=select(high_socket_set,&socket_set,NULL,NULL,&tv))<1) {
                   2517:                        if(i==0) {
                   2518:                                mswait(1);
                   2519:                                continue;
                   2520:                        }
                   2521:                        if(ERROR_VALUE==EINTR)
                   2522:                                lprintf("0000 Mail Server listening interrupted");
                   2523:                        else if(ERROR_VALUE == ENOTSOCK)
                   2524:                lprintf("0000 Mail Server sockets closed");
                   2525:                        else
                   2526:                                lprintf("0000 !ERROR %d selecting sockets",ERROR_VALUE);
                   2527:                        break;
                   2528:                }
                   2529: 
                   2530: 
                   2531:                if(FD_ISSET(server_socket,&socket_set)) {
                   2532: 
                   2533:                        client_addr_len = sizeof (client_addr);
                   2534:                        client_socket = accept(server_socket, (struct sockaddr *)&client_addr
                   2535:                        ,&client_addr_len);
                   2536: 
                   2537:                        if (client_socket == INVALID_SOCKET)
                   2538:                        {
                   2539:                                if(ERROR_VALUE == ENOTSOCK)
                   2540:                        lprintf("%04d SMTP socket closed while listening",server_socket);
                   2541:                                else
                   2542:                                        lprintf("%04d !ERROR %d accept failed", server_socket, ERROR_VALUE);
                   2543:                                break;
                   2544:                        }
                   2545:                        if(startup->socket_open!=NULL)
                   2546:                                startup->socket_open(TRUE);
                   2547:                        sockets++;
                   2548: 
                   2549:                        if(active_clients>=startup->max_clients) {
                   2550:                                lprintf("%04d !MAXMIMUM CLIENTS (%u) reached, access denied"
                   2551:                                        ,client_socket, startup->max_clients);
                   2552:                                sockprintf(client_socket,"421 Maximum active clients reached, please try again later.");
                   2553:                                mswait(3000);
                   2554:                                mail_close_socket(client_socket);
                   2555:                                continue;
                   2556:                        }
                   2557: 
                   2558:                        l=1;
                   2559: 
                   2560:                        if((i=ioctlsocket(client_socket, FIONBIO, &l))!=0) {
                   2561:                                lprintf("%04d !ERROR %d (%d) disabling blocking on socket"
                   2562:                                        ,client_socket, i, ERROR_VALUE);
                   2563:                                mail_close_socket(client_socket);
                   2564:                                continue;
                   2565:                        }
                   2566: 
                   2567:                        if((smtp=malloc(sizeof(smtp_t)))==NULL) {
                   2568:                                lprintf("%04d !ERROR allocating %u bytes of memory for smtp_t"
                   2569:                                        ,client_socket, sizeof(smtp_t));
                   2570:                                mail_close_socket(client_socket);
                   2571:                                continue;
                   2572:                        }
                   2573: 
                   2574:                        smtp->socket=client_socket;
                   2575:                        smtp->client_addr=client_addr;
                   2576:                        _beginthread (smtp_thread, 0, smtp);
                   2577:                }
                   2578: 
                   2579:                if(FD_ISSET(pop3_socket,&socket_set)) {
                   2580: 
                   2581:                        client_addr_len = sizeof (client_addr);
                   2582:                        client_socket = accept(pop3_socket, (struct sockaddr *)&client_addr
                   2583:                        ,&client_addr_len);
                   2584: 
                   2585:                        if (client_socket == INVALID_SOCKET)
                   2586:                        {
                   2587:                                if(ERROR_VALUE == ENOTSOCK)
                   2588:                        lprintf("%04d POP3 socket closed while listening",pop3_socket);
                   2589:                                else
                   2590:                                        lprintf("%04d !ERROR %d accept failed", pop3_socket, ERROR_VALUE);
                   2591:                                break;
                   2592:                        }
                   2593:                        if(startup->socket_open!=NULL)
                   2594:                                startup->socket_open(TRUE);
                   2595:                        sockets++;
                   2596: 
                   2597:                        if(active_clients>=startup->max_clients) {
                   2598:                                lprintf("%04d !MAXMIMUM CLIENTS (%u) reached, access denied"
                   2599:                                        ,client_socket, startup->max_clients);
                   2600:                                sockprintf(client_socket,"-ERR Maximum active clients reached, please try again later.");
                   2601:                                mswait(3000);
                   2602:                                mail_close_socket(client_socket);
                   2603:                                continue;
                   2604:                        }
                   2605: 
                   2606: 
                   2607:                        l=1;
                   2608: 
                   2609:                        if((i=ioctlsocket(client_socket, FIONBIO, &l))!=0) {
                   2610:                                lprintf("%04d !ERROR %d (%d) disabling blocking on socket"
                   2611:                                        ,client_socket, i, ERROR_VALUE);
                   2612:                                sockprintf(client_socket,"-ERR System error, please try again later.");
                   2613:                                mswait(3000);
                   2614:                                mail_close_socket(client_socket);
                   2615:                                continue;
                   2616:                        }
                   2617: 
                   2618:                        if((pop3=malloc(sizeof(pop3_t)))==NULL) {
                   2619:                                lprintf("%04d !ERROR allocating %u bytes of memory for pop3_t"
                   2620:                                        ,client_socket,sizeof(pop3_t));
                   2621:                                sockprintf(client_socket,"-ERR System error, please try again later.");
                   2622:                                mswait(3000);
                   2623:                                mail_close_socket(client_socket);
                   2624:                                continue;
                   2625:                        }
                   2626: 
                   2627:                        pop3->socket=client_socket;
                   2628:                        pop3->client_addr=client_addr;
                   2629: 
                   2630:                        _beginthread (pop3_thread, 0, pop3);
                   2631:                }
                   2632:        }
                   2633: 
                   2634:        if(active_clients) {
                   2635:                lprintf("0000 Waiting for %d active clients to disconnect...", active_clients);
                   2636:                start=time(NULL);
                   2637:                while(active_clients) {
                   2638:                        if(time(NULL)-start>TIMEOUT_THREAD_WAIT) {
                   2639:                                lprintf("!TIMEOUT waiting for %u active clients ",active_clients);
                   2640:                                break;
                   2641:                        }
                   2642:                        mswait(100);
                   2643:                }
                   2644:        }
                   2645: 
                   2646:        if(sendmail_running) {
                   2647:                lprintf("0000 Waiting for SendMail thread to terminate...");
                   2648:                start=time(NULL);
                   2649:                while(sendmail_running) {
                   2650:                        if(time(NULL)-start>TIMEOUT_THREAD_WAIT) {
                   2651:                                lprintf("!TIMEOUT waiting for sendmail thread to "
                   2652:                        "terminate");
                   2653:                                break;
                   2654:                        }
                   2655:                        mswait(100);
                   2656:                }
                   2657:        }
                   2658: 
                   2659:        cleanup(0);
                   2660: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.