Annotation of sbbs/sbbs3/mailsrvr.c, revision 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.