/*
 * Copyright (c) 1990, 1999 Erick Engelke
 */
#include <rtos.h>
#include <net.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>

static void smtp_result( tcp_Socket *s, int val, char *msg )
{
    char buffer[ 8 ];
    sprintf( buffer, "%u ", val );
    sock_write( s, buffer, strlen( buffer ) );
    sock_puts( s, msg );
}
static int test_cmd( char *buffer, char *cmd, char *arg )
{
    int res, len;
    char ch;

    len = strlen( cmd );
    res = strnicmp( buffer, cmd, len );

    /* copy data if we matched and data desired */
    if (( res == 0 ) && cmd ) {
        *buffer = 0;
        buffer += len;

        /* advance to start of argument */
        do {
            ch = *buffer++;
            if ( ch == 0 ) return( res );
        } while ( isspace( ch ));

        /* skip openning < */
        if ( ch == '<' ) ch = *buffer ++;

        len = 0;
        do {
            if (   ( ++len > 79 )
                || ( ch == 0 )
                || ( ch == '>' )) break;
            *arg++ = ch;
            ch = *buffer ++;    /* get next */
        } while ( 1 );

        *arg = 0;
    }
    return( res );
}

#define SMTPPORT 25

/*
 * implement one smtp server
 */
void smtpdthread( DWORD ptr )
{
    tcp_Socket *s;
    char buffer[ 256 ];
    char from[ 128 ];
    char to[ 128 ];
    char subject[ 128 ];

    void (*userproc)(char *from, char *to, char *subject);

    userproc = (void *)ptr;

    if ( userproc == NULL )
        rt_halt( "smtpd passed user proc of NULL");

    s = kcalloc( sizeof( tcp_Socket ), 1 );

    do {
        /* start listenning */
        tcp_listen( s, SMTPPORT, 0, 0, NULL, 0 );

        /* wait for a connection */
        do {
            rt_sleep( 100 );    /* just waiting */
            if ( tcp_tick( s ) == NULL ) goto reopen;
        } while ( ! sock_established( s ));

        *from = 0;
        *to = 0;
        *subject = 0;
        sock_mode( s, TCP_MODE_ASCII );

        smtp_result( s, 220, "sendmail ready for a message");

        /* get each line of input text */
        do {
            while ( ! sock_dataready( s )) {
                rt_sleep(0);
                if ( tcp_tick( s ) == NULL ) break;
            }
            sock_gets( s, buffer, sizeof( buffer ));
            rip( buffer );   /* remove CR/LF */

            if ( ! test_cmd( buffer, "helo", NULL))
                smtp_result( s, 250, "hello");
            else if ( ! test_cmd( buffer, "mail from:", from ))
                smtp_result( s, 250, "sender ok");
            else if ( ! test_cmd( buffer, "rcpt to:", to ))
                smtp_result( s, 250, "recipient ok");
            else if ( ! test_cmd( buffer, "data", NULL )) {
                smtp_result( s, 354, "ok send the data");
                do {
                    while ( ! sock_dataready( s )) {
                        rt_yield();
                        if ( tcp_tick( s ) == NULL ) goto reopen;
                    }
                    sock_gets( s, buffer, sizeof( buffer ));
                    /* look for first subject line */
                    if ( *subject == 0 )
                        test_cmd( buffer, "subject:", subject );
                    rip( buffer );
                } while ( stricmp( buffer, "." ));
                smtp_result( s, 250, "message accepted");
                /* prepare output */
                (*userproc)( from, to, subject  );
                *to = *from = *subject = 0;
            }
            else if ( ! test_cmd( buffer, "quit", NULL )) {
                smtp_result( s, 221, "closing connection");
                break;
            }
            else smtp_result( s, 500, "command not recognized");
        } while ( 1 );

reopen:
        sock_close( s );

        /*
         * and wait for it to close
         */
        while ( tcp_tick( s ) )
            rt_sleep( 100 );

        /* now we are unthreaded, start whole process again */
    } while ( 1 );
}

