MAILER.C

29 KB 6e064a79ece855ac…
/*--------------------------------------------------------------------------*/
/*                                                                          */
/*                                                                          */
/*      ------------         Bit-Bucket Software, Co.                       */
/*      \ 10001101 /         Writers and Distributors of                    */
/*       \ 011110 /          Freely Available<tm> Software.                 */
/*        \ 1011 /                                                          */
/*         ------                                                           */
/*                                                                          */
/*  (C) Copyright 1987-91, Bit Bucket Software Co., a Delaware Corporation. */
/*                                                                          */
/*                                                                          */
/*                 This module was written by Bob Hartman                   */
/*                                                                          */
/*                                                                          */
/*                   BinkleyTerm Mail Control Routines                      */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/*    For complete  details  of the licensing restrictions, please refer    */
/*    to the License  agreement,  which  is published in its entirety in    */
/*    the MAKEFILE and BT.C, and also contained in the file LICENSE.250.    */
/*                                                                          */
/*    USE  OF THIS FILE IS SUBJECT TO THE  RESTRICTIONS CONTAINED IN THE    */
/*    BINKLEYTERM  LICENSING  AGREEMENT.  IF YOU DO NOT FIND THE TEXT OF    */
/*    THIS  AGREEMENT IN ANY OF THE  AFOREMENTIONED FILES,  OR IF YOU DO    */
/*    NOT HAVE THESE FILES,  YOU  SHOULD  IMMEDIATELY CONTACT BIT BUCKET    */
/*    SOFTWARE CO.  AT ONE OF THE  ADDRESSES  LISTED BELOW.  IN NO EVENT    */
/*    SHOULD YOU  PROCEED TO USE THIS FILE  WITHOUT HAVING  ACCEPTED THE    */
/*    TERMS  OF  THE  BINKLEYTERM  LICENSING  AGREEMENT,  OR  SUCH OTHER    */
/*    AGREEMENT AS YOU ARE ABLE TO REACH WITH BIT BUCKET SOFTWARE, CO.      */
/*                                                                          */
/*                                                                          */
/* You can contact Bit Bucket Software Co. at any one of the following      */
/* addresses:                                                               */
/*                                                                          */
/* Bit Bucket Software Co.        FidoNet  1:104/501, 1:343/491             */
/* P.O. Box 460398                AlterNet 7:491/0                          */
/* Aurora, CO 80046               BBS-Net  86:2030/1                        */
/*                                Internet f491.n343.z1.fidonet.org         */
/*                                                                          */
/* Please feel free to contact us at any time to share your comments about  */
/* our software and/or licensing policies.                                  */
/*                                                                          */
/*--------------------------------------------------------------------------*/

/* Include this file before any other includes or defines! */

#include "includes.h"

int poll_node (ADDRP);
int call_node (ADDRP, int);

int unattended ()
{
#ifdef MILQ
    REGIONP OldCurWin = CurWinSet( callwin );
#endif
    int no_inbound = 0;
    int j, m;
    long init_timer, t = -1L, t1;                   /* used for the timeouts  */
    long blank_timer;
    struct _key_fnc_hdr *OldKeyFncHdr;
    int done = 1;                                   /* if we exit with this, 
                                                     * get out of BT          */
    HFILE stream;
    USHORT got;

#ifdef MILQ
    HWND                OldActvAccel = MilqueActvAccel;
    HWND                OldActvWnd = MilqueActvWnd;

    MilqueActvAccel = MilqueMailerAccel;
    MilqueActvWnd = MilqueMailerWnd;
    SetFocus( MilqueMailerActvWnd );
#endif

    un_attended = 1;
    clear_statusline ();

    comm_bits = BITS_8;
    parity = NO_PARITY;
    stop_bits = STOP_1;
    program_baud ();

    OldKeyFncHdr = KbMapSet (&UnattendedKeyFncHdr);

    if (fullscreen)
        {
        screen_clear ();
        sb_dirty ();
        }

    opening_banner ();

    if (fullscreen)
        {
        mailer_banner ();
        }

    if ((stream = share_open (PRDCT_PRFX ".BAN", O_RDONLY|O_BINARY, DENY_WRITE)) != -1)
        {
        (void)_dos_read (stream, BBSwelcome, WELCOME_LEN, &got);
        (void) close (stream);
        }
    else
        {
        BBSwelcome[0] = '\0';
        }

    /* Initialize the random number generator */
    j = (int) time (NULL);
    srand ((unsigned int) j);

    status_line (MSG_TXT(M_BINK_BEGIN), ANNOUNCE, COMPILER_NAME);
    set_xy ("");

    set_prior(4);                                           /* Always High    */
    XON_DISABLE ();
    set_prior(2);                                           /* Regular        */

    /* Turn off forced events */
    if (noforce)
        {
        find_event ();
        noforce = 0;
        }
    if (redo_dynam)
        {
        for (j = 0; j < num_events; j++)
            {
            e_ptrs[j].behavior &= ~MAT_SKIP;
            }
        redo_dynam = 0;
        }

    /*
     * See if we should exit before initializing the modem (and therefore
     * possibly letting a call sneak through)
     */

    find_event ();
    do_ready (MSG_TXT(M_READY_INIT));

    /* Make sure we have all necessary parameters and that the nodelist
     * index gets read in. If not, then we must exit right now.
     */

    if (!net_params || !nodefind (&boss_addr, 0))
        if (boss_addr.Net != 0xffff)
            {
            status_line (MSG_TXT(M_MISCONFIGURED));
            errl_exit (254);
            }

    /* Set up outbound mail */
    list_next_event ();
    set_up_outbound ();

    if (!CARRIER)
        {
        mdm_init (modem_init);                              /* Reinit modem   */
        }

    blank_timer = timerset ((unsigned int)blank_time);/* Set a timer  */
    init_timer = timerset ((unsigned int)60000);    /* Set a 10 minute timer  */
    t1 = timerset ((unsigned) next_minute ());      /* Set a 1 minute timer   */
    waitfor_line = timerset ((unsigned int)6000);   /* no collisions for 1 min*/

top_of_mail:
    un_attended = 1;
    no_inbound = 0;
    m = 1;

    /* As long as we don't press a key */
bad_char:
    more_mail = 1;
    while (!(KEYPRESS () || ctrlc_ctr))
        {
        find_event ();
#ifdef MILQ
        if ( hold_hWnd != GetFocus() )
          SendMessage( node_hWnd, WM_COMMAND, GD_LAST, (long)&hist.last_addr );
#endif
        /* Show that we are ready */
        if (m)
            {
            if (fullscreen)
                {
                do_ready (MSG_TXT(M_READY_WAITING));
                list_next_event ();
                }
            else
                status_line (MSG_TXT(M_EVENT_WAITING), cur_event + 1);

            blank_timer = timerset ((unsigned int)blank_time);/* Set a timer  */
            init_timer = timerset ((unsigned int)60000);/* Set a 10 min timer */
            t1 = timerset ((unsigned) next_minute ());  /* Set a 1 min timer  */
            }

        if (timeup (t1))
            {
            put_up_time ();
            list_next_event ();
            t1 = timerset ((unsigned) next_minute ());  /* Set a 1 min timer  */
            }

        /* See if blanking interval has elapsed */
        if (timeup (blank_timer))
            {
            blank_timer = timerset ((unsigned int)blank_time);
            screen_blank = 1;
            if (fullscreen)
                sb_show ();
            }

        /* If we haven't gotten anything in 10 minutes, re-init the modem */
        if (timeup (init_timer))
            {
            mdm_init (modem_init);
            init_timer = timerset ((unsigned int)60000); /* Set a 10 minute timer */

            /*
             * Say that we have more mail so that things entered through other
             * side of a multi-tasker will still go out
             */

            set_up_outbound ();
            more_mail = 1;
            }

        m = 0;

        if (cur_event >= 0)
            no_inbound = (e_ptrs[cur_event].behavior & MAT_OUTONLY);
        else
            no_inbound = 1;

        if (t != -1L)
            t = random_time ((cur_event >= 0) ? e_ptrs[cur_event].wait_time : 5);
        else 
            t = timerset (1000);

       /*  variable 'no_inbound' will be TRUE if we are manually dialing out
        *  or if we are in an event where we do not want incoming stuff.
        */

        while ((!timeup (t)) && (!KEYPRESS ()) && (m == 0) && !ctrlc_ctr)
            {
            find_event ();
            time_release ();
            if (timeup (t1))
                {
                put_up_time ();
                list_next_event ();
                t1 = timerset ((unsigned) next_minute ());/* Set a 1 min timer*/
                }

            /* If we want inbound, see if there is any. If we send
                anything, clean up afterwards ...         */

            if (!no_inbound)
                {
                m = handle_inbound_mail (0);
                if (m)
                    xmit_sameplace ();
                }
            }

        if ((m) && (fullscreen))
            {
            do_ready (MSG_TXT(M_READY_WAITING));
            list_next_event ();
            }

immed_call:

        find_event ();

        /* If we have pressed a key, get out */

        if (KEYPRESS () || ctrlc_ctr)
            break;

        /* If we are not in an event, or if this is a no-outbound
           event, loop again */

        if ((cur_event < 0) || (e_ptrs[cur_event].behavior & MAT_NOOUT))
            {
            time_release ();
            continue;
            }

        if (more_mail)
            more_mail = xmit_next (&next_addr);

        if (more_mail)
            m = call_node (&next_addr, no_inbound);
        else
            {
            /* No more mail to do, was it dynamic? */
            if (e_ptrs[cur_event].behavior & MAT_DYNAM)
                {
                if (!blank_on_key)
                    screen_blank = 0;
                e_ptrs[cur_event].behavior |= MAT_SKIP;
                status_line (":%s %s %d", MSG_TXT(M_END_OF), MSG_TXT(M_DYNAMIC_EVENT), cur_event + 1);
                t = -1L;
                goto top_of_mail;
                }
            }
        }

    screen_blank = 0;
    if (fullscreen)
        sb_show ();

    /* Eat the character we pressed */
    if (ctrlc_ctr || !KEYPRESS ())
        {
        /*
         * Be serious, there had to be a key pressed or we wouldn't be here I
         * know it sounds silly, but ^C will sometimes do crap like this
         */
        status_line (MSG_TXT(M_EXIT_REQUEST));
        }
    else
        {
        blank_timer = timerset ((unsigned int)blank_time);/* Set a timer  */
        j = (int) KbRemap (FOSSIL_CHAR ());
        if (((unsigned)j & F_UN_BASE) == F_UN_BASE)
            switch ((unsigned)j)
                {
                case F_UN_FUNKEY1:
                case F_UN_FUNKEY2:
                case F_UN_FUNKEY3:
                case F_UN_FUNKEY4:
                case F_UN_FUNKEY5:
                case F_UN_FUNKEY6:
                case F_UN_FUNKEY7:
                case F_UN_FUNKEY8:
                case F_UN_FUNKEY9:
                case F_UN_FUNKEY10:
                    j = 1 + (int)((unsigned) j - (unsigned)F_UN_FUNKEY1);
                    status_line (MSG_TXT(M_FUNCTION_KEY), j * 10);
                    errl_exit (j * 10);
                    break;

                case F_UN_BLANKSCREEN:
                    screen_blank = 1;
                    if (fullscreen)
                        sb_show ();
                    break;

                case F_UN_CLEARHIST:
                    j = hist.which_day;
                    (void) memset (&hist, 0, sizeof (HISTORY));
                    hist.which_day = j;
                    if (fullscreen)
                        {
                        do_today ();
                        sb_show ();
                        }
                    break;

                case F_UN_MSGEDITOR:
                    if (BBSreader != NULL)
                        {
                        vfossil_cursor (1);
                        status_line (MSG_TXT(M_DISABLE_MODEM));
                        mdm_init (modem_busy);
                        exit_DTR ();
                        status_line (MSG_TXT(M_BEGIN_MESSAGE_READER));
                        vfossil_close ();
                        b_spawn (BBSreader);
                        vfossil_init ();
                        if (fullscreen)
                            {
                            screen_clear ();
                            sb_dirty ();
                            opening_banner ();
                            mailer_banner ();
                            }
                        status_line (MSG_TXT(M_END_MESSAGE_READER));
                        set_up_outbound ();
                        m = 1;
                        more_mail = 1;
                        status_line (MSG_TXT(M_ENABLE_MODEM));
                        RAISE_DTR ();
                        mdm_init (modem_init);
                        waitfor_line = timerset ((unsigned int)6000);
                        }
                    else
                        {
                        set_xy (NULL);
                        status_line (MSG_TXT(M_NO_MESSAGE_READER));
                        set_xy (NULL);
                        m = 1;
                        }
                    break;

                case F_UN_GETFILE:
                    if (sb_popup (10, 10, 7, 60, Do_Get, 0))
                        {
                        status_line (MSG_TXT(M_NO_GET));
                        }
                    else
                        {
                        set_up_outbound ();
                        m = 1;
                        more_mail = 1;
                        }
                    break;

                case F_UN_REINITMODEM:
                    /* The idea for this code came from Holger Schurig */
                    mdm_hangup ();
                    set_up_outbound ();
                    m = 1;
                    more_mail = 1;
                    break;

                case F_UN_SHELL:
                    status_line (MSG_TXT(M_SHELLING));
                    if (fullscreen)
                        gotoxy (0, SB_ROWS);
                    vfossil_cursor (1);
                    (void) cputs (MSG_TXT(M_TYPE_EXIT));
                    LOWER_DTR ();
                    change_prompt ();
                    b_spawn (NULL);
                    if (fullscreen)
                        {
                        screen_clear ();
                        sb_dirty ();
                        opening_banner ();
                        mailer_banner ();
                        }
                    status_line (MSG_TXT(M_BINKLEY_BACK));
                    m = 1;
                    set_up_outbound ();
                    set_prior(4);                            /* Always High */
                    RAISE_DTR ();
                    set_prior(2);                            /* Regular */
                    break;


                case F_UN_KILLNODESMAIL:
                    if (sb_popup (10, 5, 4, 70, Do_Kill, 0))
                        {
                        status_line (MSG_TXT(M_NO_KILL));
                        }
                    else
                        {
                        set_up_outbound ();
                        m = 1;
                        more_mail = 1;
                        }
                    break;

                case F_UN_POLLBOSS:
                    (void) poll_node (&boss_addr);
                    m = 1;
                    break;

                case F_UN_ANSWER:
                    if (ans_str != NULL)
                        mdm_cmd_string (ans_str, 0);
                    break;

                case F_UN_POLLNODE:
                    (void) poll_node ((ADDRP)NULL);
                    m = 1;
                    break;

                case F_UN_QUITTHISEVENT:
                    if (cur_event >= 0)
                        e_ptrs[cur_event].behavior |= MAT_SKIP;
                    goto top_of_mail;

                case F_UN_RESTARTEVENTS:
                    for (j = 0; j < num_events; j++)
                        {
                        /* Don't redo forced events */
                        if (!(e_ptrs[j].behavior & MAT_FORCED))
                            {
                            e_ptrs[j].last_ran = (char)-1;
                            e_ptrs[j].behavior &= ~MAT_SKIP;
                            }
                        }
                    goto top_of_mail;

                case F_UN_SENDFILE:
                    if (sb_popup (10, 5, 6, 70, Do_Send, 0))
                        {
                        status_line (MSG_TXT(M_NO_SEND));
                        }
                    else
                        {
                        set_up_outbound ();
                        m = 1;
                        more_mail = 1;
                        }
                    break;

                case F_UN_TERMINALMODE:
                    status_line (MSG_TXT(M_ENTER_TERMINAL_MODE));
                    done = 0;                                 /* We won't exit now */
                    goto mail_done;

                case F_UN_REPAINTSCREEN:
                    if (fullscreen)
                        {
                        screen_clear ();
                        sb_dirty ();
                        sb_show ();
                        }
                    break;

                case F_UN_HELPSCREEN:
                    mailer_help ();
                    if (fullscreen)
                        {
                        screen_clear ();
                        sb_dirty ();
                        opening_banner ();
                        mailer_banner ();
                        }
                    m = 1;
                    break;

                case F_UN_EXITBINK:
                    status_line (MSG_TXT(M_EXIT_REQUEST));
                    goto mail_done;

                case F_UN_SHELL1:
                case F_UN_SHELL2:
                case F_UN_SHELL3:
                case F_UN_SHELL4:
                case F_UN_SHELL5:
                case F_UN_SHELL6:
                case F_UN_SHELL7:
                case F_UN_SHELL8:
                case F_UN_SHELL9:
                    j = (int) ((unsigned) j - (unsigned)F_UN_SHELL1);
                    if (shells[j] != NULL)
                        {
                        status_line (MSG_TXT(M_KEYBOARD_SHELL), j + 1);
                        mdm_init (modem_busy);
                        exit_DTR ();
                        close_up ();
                        vfossil_cursor (1);
                        b_spawn (shells[j]);
                        come_back ();
                        m = 1;
                        status_line (MSG_TXT(M_END_KEYBOARD_SHELL));
                        screen_clear ();
                        if (fullscreen)
                            sb_dirty ();
                        opening_banner ();
                        mailer_banner ();
                        set_up_outbound ();
                        RAISE_DTR ();
                        mdm_init (modem_init);
                        waitfor_line = timerset ((unsigned int)6000);
                        }
                    else
                        status_line (MSG_TXT(M_NO_KEYBOARD_SHELL), j + 1);
                    break;

                case F_PEND_PGUP:
                    if (next_mail == NULL)
                        {
                        next_mail = mail_top;
                        }

                    if (next_mail != NULL)
                        {
                        for (j = 0; j < SB_ROW_HOLD; j++)
                            {
                            if (next_mail->prev != NULL)
                                next_mail = next_mail->prev;
                            }
                        xmit_window (next_mail);
                        }
                    break;

                case F_PEND_PGDN:
                    if (next_mail == NULL)
                        {
                        next_mail = mail_top;
                        }

                    if (next_mail != NULL)
                        {
                        for (j = 0; j < SB_ROW_HOLD; j++)
                            {
                            if (next_mail->next != NULL)
                                next_mail = next_mail->next;
                            }
                        xmit_window (next_mail);
                        }
                    break;

                case F_PEND_UPAR:
                    if (next_mail == NULL)
                        {
                        next_mail = mail_top;
                        }

                    if (next_mail != NULL)
                        {
                        if (next_mail->prev != NULL)
                            next_mail = next_mail->prev;
                        xmit_window (next_mail);
                        }
                    break;

                case F_PEND_DNAR:
                    if (next_mail == NULL)
                        {
                        next_mail = mail_top;
                        }

                    if (next_mail != NULL)
                        {
                        if (next_mail->next != NULL)
                            next_mail = next_mail->next;
                        xmit_window (next_mail);
                        }
                    break;

                case F_PEND_HOME:
                    next_mail = mail_top;
                    xmit_window (next_mail);
                    break;

                case F_PEND_END:
                    if (next_mail == NULL)
                        {
                        next_mail = mail_top;
                        }

                    if (next_mail != NULL)
                        {
                        while (next_mail->next != NULL)
                            {
                            next_mail = next_mail->next;
                            }
                        }

                    for (j = 0; j < (SB_ROW_HOLD - 1); j++)
                        {
                        if (next_mail->prev != NULL)
                            next_mail = next_mail->prev;
                        }
                    xmit_window (next_mail);
                    break;

                case F_UN_CALLRIGHTNOW:
                    if (cur_event >= 0)
                        if (e_ptrs[cur_event].behavior & MAT_NOOUT)
                            {
                            status_line (MSG_TXT(M_NO_CALLS_NOW));
                            goto immed_call;
                            }

                    status_line (MSG_TXT(M_IMMEDIATE_CALL));
                    m = 0;
                    more_mail = 1;
                    goto immed_call;

                default:
                    status_line (MSG_TXT(M_JUNK_CHARACTER));
                    m = 1;
                    break;
                }
        else
            switch (toupper (j & 0xff))
                {
                case 3:
                    status_line (MSG_TXT(M_EXIT_REQUEST));
                    goto mail_done;

                case 0x20:
                    m = 1;
                    break;

                default:
                    status_line (MSG_TXT(M_JUNK_CHARACTER));
                    m = 1;
                    break;
                }
        goto bad_char;
        }

mail_done:

    write_sched ();
    status_line (MSG_TXT (M_BINK_END), ANNOUNCE, COMPILER_NAME);
    un_attended = 0;
    if (fullscreen)
        {
        gotoxy (0, SB_ROWS);
        }
    set_prior(4);                                            /* Always High */
    XON_ENABLE ();
    set_prior(2);                                            /* Regular */
    (void) KbMapSet(OldKeyFncHdr);

#ifdef MILQ
    MilqueActvAccel = OldActvAccel;
    MilqueActvWnd = OldActvWnd;
    MilqueMailerActvWnd = GetFocus();
    CurWinSet( OldCurWin );
#endif


    return (done);
}

/*
 * Poll a node. If address is supplied, use it. Otherwise,
 * make a popup and ask for it.
 */

int poll_node (ADDRP address)
{
   int m;
   char jbuf[90];

   if (address == (ADDRP)NULL)
      {
      status_line (MSG_TXT(M_POLL_MODE));

      if (!fullscreen)
         {
         scr_printf ("\r\n");
         clear_eol ();
         scr_printf (MSG_TXT(M_ENTER_NET_NODE));
         m = get_number (jbuf);
         if (m)
             {
             m = find_address (jbuf, &next_addr);
             }
         if (!(m >= 1 && nodefind (&next_addr, 1)))
             return (-1);
         }
      else
         if (!sb_popup (10, 10, 4, 60, Do_Poll, 0))
            {
            status_line (MSG_TXT(M_POLL_COMPLETED));
            return (-1);
            }
      }
   else
      next_addr = *address;

   doing_poll = 1;
   if (fullscreen)
       {
       sprintf( junk,
                "%s %s",
                  MSG_TXT(M_CURRENTLY_POLLING),
                  Full_Addr_Str( &next_addr ) );
       sb_move (file_hWnd, 1, 2);
       FlLnModeSet( FILE_LN_1, 0 );
       sb_puts( GetDlgItem( file_hWnd, FILE_LN_1 ), junk );
       }
   set_prior(4);                        /* Always High */
   if ((do_mail (&next_addr, 1) == 1) && sent_mail)
       {
       next_mail = find_mail (&next_addr);
       (void) bad_call (&next_addr, -1);
       xmit_delete ();
       }
   set_prior(2);                        /* Regular */
   doing_poll = 0;

   status_line (MSG_TXT(M_POLL_COMPLETED));
   if (fullscreen)
       {
       mailer_banner ();
       clear_filetransfer ();
       }
   RAISE_DTR ();
   mdm_init (modem_init);
   return (0);
}

/*
 * Call a node. If we get through, do call accounting. If
 * we have a dialout collision, try to get the inbound.
 */

int call_node (ADDRP address, int no_inbound)
{
    MAILP mp;
    int m;

    /* save the next call in the list in case we exit */

    if ((next_mail == NULL) || (next_mail->next == NULL))
        {
        mp = mail_top;
        }
    else
        {
        mp = next_mail->next;
        }
    hist.next_addr = mp->mail_addr;

    /* If this is a CM call, tell do_mail not to pay
       attention to the nodelist flags! */

    if ((e_ptrs[cur_event].behavior & (MAT_CM | MAT_HIPRICM))
    &&  (next_mail->mailtypes & MAIL_CRASH))
         m = -1;
    else m =  0;

    set_prior(4);                               /* Always High    */
    m = do_mail (address, m);
    set_prior(2);                               /* Regular        */

/*
 * If there was a session, handle bad-call accounting
 * based on whether the session was a complete success
 * or not. Then take an exit if appropriate, based on
 * what actually arrived here.
 */
    if (m > 0)
        {
        if (m == 1)         /* There was a good session */
            {
            if (!sent_mail)
                {
                /* We connected but the transfer didn't work */
                (void) bad_call (address, 1);
                }
            else
                {
                /* We got through, so delete his status file */
                (void) bad_call (address, -1);
                xmit_delete ();
                }
            }

        if (m == 2)         /* Nothing happened */
            (void) bad_call (address, 2);

        /* Take an exit if we got something in */

        if (got_arcmail || got_packet || got_mail)
            receive_exit ();
        mailer_banner ();
        }
    else if (m < 0)
        {
        if (m == -1)
            status_line (MSG_TXT(M_INCOMING_CALL));
       
        /* Call collision or NO-DIAL-TONE. Try to answer the
           call in time to catch the remote. Exception: if it
           has been less than a minute since unbusying the line. */

        if (!no_inbound && timeup (waitfor_line))
            {
            m = handle_inbound_mail (1);
            if (m)
                xmit_sameplace ();
            }
        }

    return (m);
}