home *** CD-ROM | disk | FTP | other *** search
/ PC Online 1996 October / PCO_10.ISO / filesbbs / bsrc_260.arj / SRC.ZIP / mailer.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-03-23  |  24.3 KB  |  1,038 lines

  1. /*--------------------------------------------------------------------------*/
  2. /*                                                                          */
  3. /*                                                                          */
  4. /*      ------------         Bit-Bucket Software, Co.                       */
  5. /*      \ 10001101 /         Writers and Distributors of                    */
  6. /*       \ 011110 /          Freely Available<tm> Software.                 */
  7. /*        \ 1011 /                                                          */
  8. /*         ------                                                           */
  9. /*                                                                          */
  10. /*              (C) Copyright 1987-96, Bit Bucket Software Co.              */
  11. /*                                                                          */
  12. /*                 This module was written by Bob Hartman                   */
  13. /*                                                                          */
  14. /*                   BinkleyTerm Mail Control Routines                      */
  15. /*                                                                          */
  16. /*                                                                          */
  17. /*    For complete  details  of the licensing restrictions, please refer    */
  18. /*    to the License  agreement,  which  is published in its entirety in    */
  19. /*    the MAKEFILE and BT.C, and also contained in the file LICENSE.260.    */
  20. /*                                                                          */
  21. /*    USE  OF THIS FILE IS SUBJECT TO THE  RESTRICTIONS CONTAINED IN THE    */
  22. /*    BINKLEYTERM  LICENSING  AGREEMENT.  IF YOU DO NOT FIND THE TEXT OF    */
  23. /*    THIS  AGREEMENT IN ANY OF THE  AFOREMENTIONED FILES,  OR IF YOU DO    */
  24. /*    NOT HAVE THESE FILES,  YOU  SHOULD  IMMEDIATELY CONTACT BIT BUCKET    */
  25. /*    SOFTWARE CO.  AT ONE OF THE  ADDRESSES  LISTED BELOW.  IN NO EVENT    */
  26. /*    SHOULD YOU  PROCEED TO USE THIS FILE  WITHOUT HAVING  ACCEPTED THE    */
  27. /*    TERMS  OF  THE  BINKLEYTERM  LICENSING  AGREEMENT,  OR  SUCH OTHER    */
  28. /*    AGREEMENT AS YOU ARE ABLE TO REACH WITH BIT BUCKET SOFTWARE, CO.      */
  29. /*                                                                          */
  30. /*                                                                          */
  31. /* You can contact Bit Bucket Software Co. at any one of the following      */
  32. /* addresses:                                                               */
  33. /*                                                                          */
  34. /* Bit Bucket Software Co.        FidoNet  1:104/501, 1:343/491             */
  35. /* P.O. Box 460398                AlterNet 7:42/1491                        */
  36. /* Aurora, CO 80046               BBS-Net  86:2030/1                        */
  37. /*                                Internet f491.n343.z1.fidonet.org         */
  38. /*                                                                          */
  39. /* Please feel free to contact us at any time to share your comments about  */
  40. /* our software and/or licensing policies.                                  */
  41. /*                                                                          */
  42. /*--------------------------------------------------------------------------*/
  43.  
  44. /* Include this file before any other includes or defines! */
  45.  
  46. #include "includes.h"
  47.  
  48. static int LOCALFUNC poll_node (ADDRP);
  49. static int LOCALFUNC call_node (ADDRP, int);
  50. static void LOCALFUNC bbs_reader (void);
  51.  
  52. int 
  53. unattended ()
  54. {
  55.     int no_inbound = 0;
  56.     short j;
  57.     int m;
  58.     long init_timer, t = -1L, t1;    /* used for the timeouts  */
  59.     long blank_timer;
  60.     struct _key_fnc_hdr *OldKeyFncHdr;
  61.     int done = 1;                /* if we exit with this, get out of BT      */
  62.     HFILE stream;
  63.     char *p;
  64.  
  65.     unsigned long got;
  66.  
  67.     MAILP pmailT;
  68.  
  69.     un_attended = 1;
  70.  
  71.     comm_bits = BITS_8;
  72.     parity = NO_PARITY;
  73.     stop_bits = STOP_1;
  74.     program_baud ();
  75.  
  76.     OldKeyFncHdr = KbMapSet (&UnattendedKeyFncHdr);
  77.  
  78.     if (fullscreen)
  79.     {
  80.         screen_clear ();
  81.         sb_fillc (callwin, ' ');
  82.         sb_dirty ();
  83.         mailer_banner ();
  84.     }
  85.     else
  86.         opening_banner ();
  87.  
  88.     if ((stream = (HFILE) share_open (PRDCT_PRFX ".BAN", O_RDONLY | O_BINARY, DENY_WRITE)) != (HFILE) - 1)
  89.     {
  90.         /* Note, we do not use "got". Some platforms want it to be a long
  91.            and some want it to be a int. We don't care, so we make it a
  92.            long (see above) so there's enough room, then use a void * so
  93.            the compiler won't complain about an argument we don't even want */
  94.  
  95.         (void) _dos_read (stream, BBSwelcome, WELCOME_LEN, (void *)&got);
  96.         (void) close (stream);
  97.     }
  98.     else
  99.     {
  100.         BBSwelcome[0] = '\0';
  101.     }
  102.  
  103. #ifdef BINKLEY_SOUNDS
  104.     Make_Sound (fnStartSound);
  105. #endif
  106.  
  107.     /* Initialize the random number generator */
  108.     j = (int) time (NULL);
  109.     srand ((unsigned int) j);
  110.  
  111.     status_line (MSG_TXT (M_BINK_BEGIN), ANNOUNCE, COMPILER_NAME);
  112.     set_xy ("");
  113.  
  114.     set_prior (4);                /* Always High    */
  115.     XON_DISABLE ();
  116.     set_prior (2);                /* Regular        */
  117.  
  118.     /* See if someone has set the forced-exit semaphore */
  119.  
  120.     forcexitcheck ();
  121.  
  122.     /* Turn off forced events */
  123.  
  124.     if (noforce)
  125.     {
  126.         find_event ();
  127.         noforce = 0;
  128.     }
  129.     if (redo_dynam)
  130.     {
  131.         for (j = 0; j < num_events; j++)
  132.         {
  133.             e_ptrs[j].behavior &= ~MAT_SKIP;
  134.         }
  135.         redo_dynam = 0;
  136.     }
  137.  
  138.     /*
  139.      * See if we should exit before initializing the modem (and therefore
  140.      * possibly letting a call sneak through)
  141.      */
  142.  
  143.     find_event ();
  144.     do_ready (MSG_TXT (M_READY_INIT));
  145.  
  146.     /* Make sure we have all necessary parameters and that the nodelist
  147.      * index gets read in. If not, then we must exit right now.
  148.      */
  149.  
  150.     if (!net_params || !nodefind (&boss_addr, 0))
  151.         if (boss_addr.Net != 0xffff)
  152.         {
  153.             status_line (MSG_TXT (M_MISCONFIGURED));
  154.             errl_exit (254);
  155.         }
  156.  
  157.     /* Set up outbound mail */
  158.     list_next_event ();
  159.     set_up_outbound ();
  160.  
  161.     if (!CARRIER)
  162.     {
  163.         mdm_init (modem_init);    /* Reinit modem   */
  164.     }
  165.  
  166.     blank_timer = timerset ((unsigned int) blank_time);    /* Set a timer  */
  167.     init_timer = timerset ((unsigned int) 60000);    /* Set a 10 minute timer  */
  168.     t1 = timerset ((unsigned) next_minute ());    /* Set a 1 minute timer   */
  169.     waitfor_line = timerset ((unsigned int) 6000);    /* no collisions for 1 min*/
  170.  
  171. top_of_mail:
  172.  
  173.     un_attended = 1;
  174.     no_inbound = 0;
  175.     m = 1;
  176.  
  177.     /* As long as we don't press a key */
  178.  
  179. bad_char:
  180.  
  181.     more_mail = 1;
  182.     while (!(KEYPRESS () || ctrlc_ctr))
  183.     {
  184.         /* Check for forced exit semaphore */
  185.  
  186.         forcexitcheck ();
  187.  
  188.         /* See if we need to move into the next event */
  189.  
  190.         find_event ();
  191.         /* Show that we are ready */
  192.         if (m)
  193.         {
  194.             if (fullscreen)
  195.             {
  196.                 do_ready (MSG_TXT (M_READY_WAITING));
  197.                 list_next_event ();
  198.             }
  199.             else
  200.                 status_line (MSG_TXT (M_EVENT_WAITING), cur_event + 1);
  201.  
  202.             blank_timer = timerset ((unsigned int) blank_time);    /* Set a timer  */
  203.             init_timer = timerset ((unsigned int) 60000);    /* Set a 10 min timer */
  204.             t1 = timerset ((unsigned) next_minute ());    /* Set a 1 min timer  */
  205.         }
  206.  
  207.         if (timeup (t1))
  208.         {
  209.             put_up_time ();
  210.             list_next_event ();
  211.             t1 = timerset ((unsigned) next_minute ());    /* Set a 1 min timer  */
  212.         }
  213.  
  214.         /* See if blanking interval has elapsed */
  215.         if (timeup (blank_timer))
  216.         {
  217.             blank_timer = timerset ((unsigned int) blank_time);
  218.             screen_blank = 1;
  219.             if (fullscreen)
  220.                 sb_show ();
  221.         }
  222.  
  223.         /* If we haven't gotten anything in 10 minutes, re-init the modem */
  224.         if (timeup (init_timer))
  225.         {
  226.             mdm_init (modem_init);
  227.             init_timer = timerset ((unsigned int) 60000);    /* Set a 10 minute timer */
  228.  
  229.             /*
  230.              * Say that we have more mail so that things entered through other
  231.              * side of a multi-tasker will still go out
  232.              */
  233.  
  234.             set_up_outbound ();
  235.             more_mail = 1;
  236.         }
  237.  
  238.         m = 0;
  239.  
  240.         if (cur_event >= 0)
  241.             no_inbound = (e_ptrs[cur_event].behavior & MAT_OUTONLY);
  242.         else
  243.             no_inbound = 1;
  244.  
  245.         if (t != -1L)
  246.             t = random_time ((cur_event >= 0) ? e_ptrs[cur_event].wait_time : 5);
  247.         else
  248.             t = timerset (1000);
  249.  
  250.         /*  variable 'no_inbound' will be TRUE if we are manually dialing out
  251.          *  or if we are in an event where we do not want incoming stuff.
  252.          */
  253.  
  254.         while ((!timeup (t)) && (!KEYPRESS ()) && !ctrlc_ctr)
  255.         {
  256.             forcexitcheck ();
  257.  
  258.             if (forcerescancheck ())
  259.             {
  260.                 set_up_outbound ();
  261.                 more_mail = 1;
  262.                 goto immed_call;
  263.             }
  264.  
  265.             find_event ();
  266.             time_release ();
  267.  
  268.             if (timeup (t1))
  269.             {
  270.                 put_up_time ();
  271.                 list_next_event ();
  272.                 t1 = timerset ((unsigned) next_minute ());    /* Set a 1 min timer*/
  273.             }
  274.  
  275.             /* If we want inbound, see if there is any. If we send
  276.                 anything, clean up afterwards ...         */
  277.  
  278.             if (!no_inbound)
  279.             {
  280.                 long lstart = timerset (0);
  281.  
  282.                 m = handle_inbound_mail (0);
  283.                 if (m)
  284.                 {
  285.                     xmit_sameplace ();
  286.                     if (fullscreen)
  287.                     {
  288.                         do_ready (MSG_TXT (M_READY_WAITING));
  289.                         list_next_event ();
  290.                     }
  291.                     m = 0;
  292.                 }
  293.  
  294.                 /* Correct dialout by amount of time we spent
  295.                    handling the inbound traffic */
  296.  
  297.                 t += (timerset (0) - lstart);
  298.             }
  299.         }
  300.  
  301. immed_call:
  302.  
  303.         forcexitcheck ();
  304.  
  305.         find_event ();
  306.  
  307.         /* If we have pressed a key, get out */
  308.  
  309.         if (KEYPRESS () || ctrlc_ctr)
  310.             break;
  311.  
  312.         /* If we are not in an event, or if this is a no-outbound
  313.            event, loop again */
  314.  
  315.         if ((cur_event < 0) || (e_ptrs[cur_event].behavior & MAT_NOOUT))
  316.         {
  317.             time_release ();
  318.             continue;
  319.         }
  320.  
  321.         if (more_mail)
  322.             more_mail = xmit_next (&next_addr);
  323.  
  324.         if (more_mail)
  325.             m = call_node (&next_addr, no_inbound);
  326.         else
  327.         {
  328.             /* No more mail to do, was it dynamic? */
  329.             if (e_ptrs[cur_event].behavior & MAT_DYNAM)
  330.             {
  331.                 if (!blank_on_key)
  332.                     screen_blank = 0;
  333.                 e_ptrs[cur_event].behavior |= MAT_SKIP;
  334.                 status_line (":%s %s %d", MSG_TXT (M_END_OF), MSG_TXT (M_DYNAMIC_EVENT), cur_event + 1);
  335.                 t = -1L;
  336.                 goto top_of_mail;
  337.             }
  338.         }
  339.     }
  340.  
  341.     screen_blank = 0;
  342.     if (fullscreen)
  343.         sb_show ();
  344.  
  345.     /* Eat the character we pressed */
  346.     if (ctrlc_ctr || !KEYPRESS ())
  347.     {
  348.         /*
  349.          * Be serious, there had to be a key pressed or we wouldn't be here I
  350.          * know it sounds silly, but ^C will sometimes do crap like this
  351.          */
  352.         status_line (MSG_TXT (M_EXIT_REQUEST));
  353.     }
  354.     else
  355.     {
  356.         blank_timer = timerset ((unsigned int) blank_time);    /* Set a timer  */
  357.         j = (short) KbRemap (FOSSIL_CHAR ());
  358.         if (((unsigned short) j & F_UN_BSE) == F_UN_BSE)
  359.             switch ((unsigned short) j)
  360.             {
  361.             case F_UN_FUNKEY1:
  362.             case F_UN_FUNKEY2:
  363.             case F_UN_FUNKEY3:
  364.             case F_UN_FUNKEY4:
  365.             case F_UN_FUNKEY5:
  366.             case F_UN_FUNKEY6:
  367.             case F_UN_FUNKEY7:
  368.             case F_UN_FUNKEY8:
  369.             case F_UN_FUNKEY9:
  370.             case F_UN_FUNKEY10:
  371.                 j = 1 + (short) ((unsigned short) j - (unsigned short) F_UN_FUNKEY1);
  372.                 status_line (MSG_TXT (M_FUNCTION_KEY), j * 10);
  373.                 errl_exit (j * 10);
  374.                 break;
  375.  
  376.             case F_UN_BLANKSCREEN:
  377.                 screen_blank = 1;
  378.                 if (fullscreen)
  379.                     sb_show ();
  380.                 break;
  381.  
  382.             case F_UN_CLEARHIST:
  383.                 j = hist.which_day;
  384.                 (void) memset (&hist, 0, sizeof (HISTORY));
  385.                 start_hist = hist;
  386.                 hist.which_day = j;
  387.                 if (fullscreen)
  388.                 {
  389.                     do_today ();
  390.                     sb_show ();
  391.                 }
  392.                 break;
  393.  
  394.             case F_UN_MSGEDITOR:
  395.                 bbs_reader ();
  396.                 m = 1;
  397.                 break;
  398.  
  399.             case F_UN_GETFILE:
  400.                 j = sb_popup (10, 5, 7, 70, Do_Get, 0);
  401.                 if (j < 0)
  402.                 {
  403.                     status_line (MSG_TXT (M_NO_GET));
  404.                 }
  405.                 else if (j > 0)
  406.                 {
  407.                     set_up_outbound ();
  408.                     m = 1;
  409.                     more_mail = 1;
  410.                 }
  411.                 break;
  412.  
  413.             case F_UN_REINITMODEM:
  414.                 /* The idea for this code came from Holger Schurig */
  415.                 mdm_hangup ();
  416.                 set_up_outbound ();
  417.                 m = 1;
  418.                 more_mail = 1;
  419.                 break;
  420.  
  421.             case F_UN_SHELL:
  422.                 status_line (MSG_TXT (M_SHELLING));
  423.                 if (fullscreen)
  424.                     gotoxy (0, SB_ROWS);
  425.                 vfossil_cursor (1);
  426.                 (void) cputs (MSG_TXT (M_TYPE_EXIT));
  427.                 LOWER_DTR ();
  428.                 change_prompt ();
  429.                 b_spawn (NULL);
  430.                 if (fullscreen)
  431.                 {
  432.                     screen_clear ();
  433.                     sb_dirty ();
  434.                     opening_banner ();
  435.                     mailer_banner ();
  436.                 }
  437.                 status_line (MSG_TXT (M_BINKLEY_BACK));
  438.                 m = 1;
  439.                 set_up_outbound ();
  440.                 set_prior (4);    /* Always High */
  441.                 RAISE_DTR ();
  442.                 set_prior (2);    /* Regular */
  443.                 break;
  444.  
  445.             case F_UN_KILLNODESMAIL:
  446.                 if (sb_popup (10, 5, 4, 70, Do_Kill, 0))
  447.                 {
  448.                     status_line (MSG_TXT (M_NO_KILL));
  449.                 }
  450.                 else
  451.                 {
  452.                     set_up_outbound ();
  453.                     m = 1;
  454.                     more_mail = 1;
  455.                 }
  456.                 break;
  457.  
  458.             case F_UN_POLLBOSS:
  459.                 (void) poll_node (&boss_addr);
  460.                 m = 1;
  461.                 break;
  462.  
  463.             case F_UN_ANSWER:
  464.                 if (ans_str != NULL)
  465.                     mdm_cmd_string (ans_str, 0);
  466.                 break;
  467.  
  468.             case F_UN_POLLNODE:
  469.                 (void) poll_node ((ADDRP) NULL);
  470.                 m = 1;
  471.                 break;
  472.  
  473.             case F_UN_POLLPKT:
  474.                 j = sb_popup (10, 5, 4, 70, Do_Poll_Packet, 0);
  475.                 if (j > 0)
  476.                 {
  477.                     set_up_outbound ();
  478.                     m = 1;
  479.                     more_mail = 1;
  480.                 }
  481.                 break;
  482.  
  483.             case F_UN_QUITTHISEVENT:
  484.                 if (cur_event >= 0)
  485.                     e_ptrs[cur_event].behavior |= MAT_SKIP;
  486.                 goto top_of_mail;
  487.  
  488.             case F_UN_RESTARTEVENTS:
  489.                 for (j = 0; j < num_events; j++)
  490.                 {
  491.                     /* Don't redo forced events */
  492.                     if (!(e_ptrs[j].behavior & MAT_FORCED))
  493.                     {
  494.                         e_ptrs[j].last_ran = (char) -1;
  495.                         e_ptrs[j].behavior &= ~MAT_SKIP;
  496.                     }
  497.                 }
  498.                 goto top_of_mail;
  499.  
  500.             case F_UN_SENDFILE:
  501.                 j = sb_popup (10, 5, 6, 70, Do_Send, 0);
  502.                 if (j < 0)
  503.                 {
  504.                     status_line (MSG_TXT (M_NO_SEND));
  505.                 }
  506.                 else if (j > 0)
  507.                 {
  508.                     set_up_outbound ();
  509.                     m = 1;
  510.                     more_mail = 1;
  511.                 }
  512.                 break;
  513.  
  514.             case F_UN_TERMINALMODE:
  515.                 status_line (MSG_TXT (M_ENTER_TERMINAL_MODE));
  516.                 done = 0;        /* We won't exit now */
  517.                 goto mail_done;
  518.  
  519.             case F_UN_REPAINTSCREEN:
  520.                 if (fullscreen)
  521.                 {
  522.                     screen_clear ();
  523.                     sb_dirty ();
  524.                     sb_show ();
  525.                 }
  526.                 break;
  527.  
  528.             case F_UN_HELPSCREEN:
  529.                 mailer_help ();
  530.                 m = 1;
  531.                 break;
  532.  
  533.             case F_UN_EXITBINK:
  534.                 status_line (MSG_TXT (M_EXIT_REQUEST));
  535.                 goto mail_done;
  536.  
  537.             case F_UN_ZOOM:
  538.  
  539.                 if (mail_top == NULL)
  540.                 {
  541.                     xmit_reset (0);
  542.                     if (mail_top == NULL)
  543.                         break;
  544.                     m = 1;
  545.                     more_mail = 1;
  546.                     next_mail = mail_top;
  547.                     xmit_window (next_mail);
  548.                 }
  549.                 if (sb_popup (1, 0, (short) (SB_ROWS - 2), 80, Do_Zoom, 0))
  550.                 {
  551.                     m = 1;
  552.                     more_mail = 1;
  553.                     next_mail = mail_top;
  554.                     xmit_window (next_mail);
  555.                 }
  556.                 break;
  557.  
  558.             case F_UN_SHELL1:
  559.             case F_UN_SHELL2:
  560.             case F_UN_SHELL3:
  561.             case F_UN_SHELL4:
  562.             case F_UN_SHELL5:
  563.             case F_UN_SHELL6:
  564.             case F_UN_SHELL7:
  565.             case F_UN_SHELL8:
  566.             case F_UN_SHELL9:
  567.                 j = (short) ((unsigned short) j - (unsigned short) F_UN_SHELL1);
  568.                 if (shells[j] != NULL)
  569.                 {
  570.                     status_line (MSG_TXT (M_KEYBOARD_SHELL), j + 1);
  571.                     mdm_init (modem_busy);
  572.                     exit_DTR ();
  573.                     close_up ();
  574.                     vfossil_cursor (1);
  575.                     b_spawn (shells[j]);
  576.                     come_back ();
  577.                     m = 1;
  578.                     status_line (MSG_TXT (M_END_KEYBOARD_SHELL));
  579.                     screen_clear ();
  580.                     if (fullscreen)
  581.                         sb_dirty ();
  582.                     opening_banner ();
  583.                     mailer_banner ();
  584.                     set_up_outbound ();
  585.                     RAISE_DTR ();
  586.                     mdm_init (modem_init);
  587.                     waitfor_line = timerset ((unsigned int) 6000);
  588.                 }
  589.                 else
  590.                     status_line (MSG_TXT (M_NO_KEYBOARD_SHELL), j + 1);
  591.                 break;
  592.  
  593.             case F_PEND_PGUP:
  594.                 if (next_mail == NULL)
  595.                 {
  596.                     next_mail = mail_top;
  597.                 }
  598.  
  599.                 if (next_mail != NULL)
  600.                 {
  601.                     for (j = 0; j < (SB_ROW_HOLD - 2); j++)
  602.                     {
  603.                         if (next_mail->prev != NULL)
  604.                             next_mail = next_mail->prev;
  605.                     }
  606.                     xmit_window (next_mail);
  607.                 }
  608.                 break;
  609.  
  610.             case F_PEND_PGDN:
  611.                 if (next_mail == NULL)
  612.                 {
  613.                     next_mail = mail_top;
  614.                 }
  615.  
  616.                 if (next_mail != NULL)
  617.                 {
  618.                     for (j = 0; j < (SB_ROW_HOLD - 2); j++)
  619.                     {
  620.                         if (next_mail->next != NULL)
  621.                             next_mail = next_mail->next;
  622.                     }
  623.                     goto limit_down;
  624.                 }
  625.                 break;
  626.  
  627.             case F_PEND_UPAR:
  628.                 if (next_mail == NULL)
  629.                 {
  630.                     next_mail = mail_top;
  631.                 }
  632.  
  633.                 if (next_mail != NULL)
  634.                 {
  635.                     if (next_mail->prev != NULL)
  636.                         next_mail = next_mail->prev;
  637.                     xmit_window (next_mail);
  638.                 }
  639.                 break;
  640.  
  641.             case F_PEND_DNAR:
  642.                 if (next_mail == NULL)
  643.                 {
  644.                     next_mail = mail_top;
  645.                 }
  646.  
  647.                 if (next_mail != NULL)
  648.                 {
  649.                     if (next_mail->next != NULL)
  650.                         next_mail = next_mail->next;
  651.  
  652. limit_down:
  653.                     /* Common between PEND_PGDN and PEND_DNAR */
  654.                     /* Don't allow travel below the end       */
  655.  
  656.                     pmailT = next_mail;
  657.  
  658.                     for (j = 0; j < (SB_ROW_HOLD - 3); j++)
  659.                     {
  660.                         if (pmailT->next != NULL)
  661.                             pmailT = pmailT->next;
  662.                     }
  663.  
  664.                     if (pmailT->next == NULL)    /* Past the end? */
  665.                     {
  666.                         next_mail = pmailT;
  667.                         goto do_end;    /* Yes, find it  */
  668.                     }
  669.                     xmit_window (next_mail);
  670.                 }
  671.                 break;
  672.  
  673.             case F_PEND_HOME:
  674.                 next_mail = mail_top;
  675.                 xmit_window (next_mail);
  676.                 break;
  677.  
  678.             case F_PEND_END:
  679.                 if (next_mail == NULL)
  680.                 {
  681.                     next_mail = mail_top;
  682.                 }
  683.  
  684.                 if (next_mail != NULL)
  685.                 {
  686.                     while (next_mail->next != NULL)
  687.                     {
  688.                         next_mail = next_mail->next;
  689.                     }
  690. do_end:
  691.                     /* Common between PEND_END, PEND_PGDN and PEND_DNAR */
  692.                     /* We are at end of list, find the top of window    */
  693.  
  694.                     for (j = 0; j < (SB_ROW_HOLD - 3); j++)
  695.                     {
  696.                         if (next_mail->prev != NULL)
  697.                             next_mail = next_mail->prev;
  698.                     }
  699.                 }
  700.                 xmit_window (next_mail);
  701.                 break;
  702.  
  703.             case F_UN_CALLRIGHTNOW:
  704.                 if (cur_event >= 0)
  705.                     if (e_ptrs[cur_event].behavior & MAT_NOOUT)
  706.                     {
  707.                         status_line (MSG_TXT (M_NO_CALLS_NOW));
  708.                         goto immed_call;
  709.                     }
  710.  
  711.                 status_line (MSG_TXT (M_IMMEDIATE_CALL));
  712.                 m = 0;
  713.                 more_mail = 1;
  714.                 goto immed_call;
  715.  
  716.             case F_CALLWIN_DNAR:
  717.                 if (fullscreen && callwin->lastshown != callwin->lastline && scrllines > callwin->lines)
  718.                 {
  719.                     callwin->lastshown += callwin->linesize;
  720.                     sb_scrl (callwin, 1);
  721.                     sb_move (callwin, callwin->lines, 2);
  722.                     sb_puts (callwin, callwin->lastshown);
  723.                     sb_show ();
  724.                 }
  725.                 break;
  726.  
  727.             case F_CALLWIN_UPAR:
  728.                 if (fullscreen && callwin->lastshown != callwin->buffer && scrllines > callwin->lines)
  729.                 {
  730.                     int i1 = (callwin->lastshown - callwin->buffer);
  731.                     int i2 = (callwin->lines - 1) * callwin->linesize;
  732.  
  733.                     if (i2 < i1)
  734.                     {
  735.                         p = callwin->lastshown - (callwin->lines * callwin->linesize);
  736.                         callwin->lastshown -= callwin->linesize;
  737.                         sb_scrl (callwin, -1);
  738.                         sb_move (callwin, 1, 2);
  739.                         sb_puts (callwin, p);
  740.                     }
  741.                     sb_show ();
  742.                 }
  743.                 break;
  744.  
  745.             case F_CALLWIN_PGDN:
  746.                 if (fullscreen && callwin->lastshown != callwin->lastline && scrllines > callwin->lines)  
  747.                 {
  748.                     p = callwin->lastshown + (callwin->lines * callwin->linesize);
  749.  
  750.                     if (p >= callwin->lastline) 
  751.                         p = callwin->lastline;
  752. do_callwin:
  753.                     if (p != callwin->lastshown)
  754.                     {
  755.                         callwin->lastshown = p;
  756.                         sb_scrl (callwin, 0);
  757.  
  758.                         for (j = callwin->lines; j > 0 && p >= callwin->buffer; j--) 
  759.                         {
  760.                             sb_move (callwin, j, 2);
  761.                             sb_puts (callwin, p);
  762.                             p -= callwin->linesize;
  763.                         }
  764.                         sb_show ();
  765.                     }
  766.                 }
  767.                 break;
  768.  
  769.             case F_CALLWIN_PGUP:
  770.                 if (fullscreen && scrllines > callwin->lines) 
  771.                 {
  772.                     int i1 = (callwin->lastshown - callwin->buffer);
  773.                     int i2 = (callwin->lines - 1) * callwin->linesize;
  774.  
  775.                     if (i2 < i1)
  776.                     {
  777.                         if ((i1 - i2) < i2)
  778.                             p = callwin->buffer + i2;
  779.                         else
  780.                             p = callwin->buffer + i1 - i2;
  781.                         goto do_callwin;
  782.                     }
  783.                 }
  784.                 break;
  785.  
  786.             case F_CALLWIN_TOP:
  787.                 if (fullscreen && scrllines > callwin->lines) 
  788.                 {
  789.                     p = callwin->buffer + ((callwin->lines - 1) * callwin->linesize);
  790.  
  791.                     if (p > callwin->lastline)
  792.                         p = callwin->lastline;
  793.  
  794.                     goto do_callwin;
  795.                 }
  796.                 break;
  797.  
  798.             case F_CALLWIN_END:
  799.                 if (fullscreen && scrllines > callwin->lines) 
  800.                 {
  801.                     p = callwin->lastline;
  802.                     goto do_callwin;
  803.                 }
  804.                 break; 
  805.  
  806.             default:
  807.                 status_line (MSG_TXT (M_JUNK_CHARACTER));
  808.                 m = 1;
  809.                 break;
  810.             }
  811.         else
  812.             switch (toupper (j & 0xff))
  813.             {
  814.             case 3:
  815.                 status_line (MSG_TXT (M_EXIT_REQUEST));
  816.                 goto mail_done;
  817.  
  818.             case 0x20:
  819.                 m = 1;
  820.                 break;
  821.  
  822.             default:
  823.                 status_line (MSG_TXT (M_JUNK_CHARACTER));
  824.                 m = 1;
  825.                 break;
  826.             }
  827.         goto bad_char;
  828.     }
  829.  
  830. mail_done:
  831.  
  832.     write_sched ();
  833.     status_line (MSG_TXT (M_BINK_END), ANNOUNCE, COMPILER_NAME);
  834.     un_attended = 0;
  835.     if (fullscreen)
  836.     {
  837.         gotoxy (0, SB_ROWS);
  838.     }
  839.     set_prior (4);                /* Always High */
  840.     XON_ENABLE ();
  841.     set_prior (2);                /* Regular */
  842.     (void) KbMapSet (OldKeyFncHdr);
  843.  
  844.     return (done);
  845. }
  846.  
  847. static void LOCALFUNC 
  848. bbs_reader (void)
  849. {
  850.     if (BBSreader != NULL)
  851.     {
  852.         vfossil_cursor (1);
  853.         status_line (MSG_TXT (M_DISABLE_MODEM));
  854.         mdm_init (modem_busy);
  855.         exit_DTR ();
  856.         status_line (MSG_TXT (M_BEGIN_MESSAGE_READER));
  857.         vfossil_close ();
  858.         b_spawn (BBSreader);
  859.         vfossil_init ();
  860.         if (fullscreen)
  861.         {
  862.             screen_clear ();
  863.             sb_dirty ();
  864.             opening_banner ();
  865.             mailer_banner ();
  866.         }
  867.         status_line (MSG_TXT (M_END_MESSAGE_READER));
  868.         set_up_outbound ();
  869.         more_mail = 1;
  870.         status_line (MSG_TXT (M_ENABLE_MODEM));
  871.         RAISE_DTR ();
  872.         mdm_init (modem_init);
  873.         waitfor_line = timerset ((unsigned int) 6000);
  874.     }
  875.     else
  876.     {
  877.         set_xy (NULL);
  878.         status_line (MSG_TXT (M_NO_MESSAGE_READER));
  879.         set_xy (NULL);
  880.     }
  881. }
  882.  
  883. /*
  884.  * Poll a node. If address is supplied, use it. Otherwise,
  885.  * make a popup and ask for it.
  886.  */
  887.  
  888. static int LOCALFUNC 
  889. poll_node (ADDRP address)
  890. {
  891.     int m;
  892.     char jbuf[90];
  893.  
  894.     if (address == (ADDRP) NULL)
  895.     {
  896.         status_line (MSG_TXT (M_POLL_MODE));
  897.  
  898.         if (!fullscreen)
  899.         {
  900.             scr_printf ("\r\n");
  901.             clear_eol ();
  902.             scr_printf (MSG_TXT (M_ENTER_NET_NODE));
  903.             m = get_number (jbuf);
  904.             if (m)
  905.             {
  906.                 m = find_address (jbuf, &next_addr);
  907.             }
  908.             if (!(m >= 1 && nodefind (&next_addr, 1)))
  909.                 return (-1);
  910.         }
  911.         else if (!sb_popup (10, 5, 4, 70, Do_Poll, 0))
  912.         {
  913.             status_line (MSG_TXT (M_POLL_COMPLETED));
  914.             return (-1);
  915.         }
  916.     }
  917.     else
  918.         next_addr = *address;
  919.  
  920.     doing_poll = 1;
  921.     if (fullscreen)
  922.     {
  923.         sprintf (junk,
  924.             "%s %s",
  925.             MSG_TXT (M_CURRENTLY_POLLING),
  926.             Full_Addr_Str (&next_addr));
  927.         sb_move (filewin, 1, 2);
  928.         sb_puts (filewin, junk);
  929.     }
  930.     set_prior (4);                /* Always High */
  931.     if ((do_mail (&next_addr, 1) == 1) && sent_mail)
  932.     {
  933.         next_mail = find_mail (&next_addr);
  934.         (void) bad_call (&next_addr, -1);
  935.         xmit_delete ();
  936.     }
  937.     set_prior (2);                /* Regular */
  938.     doing_poll = 0;
  939.  
  940.     status_line (MSG_TXT (M_POLL_COMPLETED));
  941.     if (fullscreen)
  942.     {
  943.         mailer_banner ();
  944.         clear_filetransfer ();
  945.     }
  946.     RAISE_DTR ();
  947.     mdm_init (modem_init);
  948.     return (0);
  949. }
  950.  
  951. /*
  952.  * Call a node. If we get through, do call accounting. If
  953.  * we have a dialout collision, try to get the inbound.
  954.  */
  955.  
  956. static int LOCALFUNC 
  957. call_node (ADDRP address, int no_inbound)
  958. {
  959.     MAILP mp;
  960.     int m;
  961.  
  962.     /* save the next call in the list in case we exit */
  963.  
  964.     if ((next_mail == NULL) || (next_mail->next == NULL))
  965.     {
  966.         mp = mail_top;
  967.     }
  968.     else
  969.     {
  970.         mp = next_mail->next;
  971.     }
  972.     hist.next_addr = mp->mail_addr;
  973.  
  974.     /* If this is a CM call, tell do_mail not to pay
  975.        attention to the nodelist flags! */
  976.  
  977.     if ((e_ptrs[cur_event].behavior & (MAT_CM | MAT_HIPRICM))
  978.         && (next_mail->mailtypes & MAIL_CRASH))
  979.         m = -1;
  980.     else
  981.         m = 0;
  982.  
  983.     set_prior (4);                /* Always High    */
  984.     m = do_mail (address, m);
  985.     set_prior (2);                /* Regular        */
  986.  
  987. /*
  988.  * If there was a session, handle bad-call accounting
  989.  * based on whether the session was a complete success
  990.  * or not. Then take an exit if appropriate, based on
  991.  * what actually arrived here.
  992.  */
  993.     if (m > 0)
  994.     {
  995.         if (m == 1)                /* There was a good session */
  996.         {
  997.             if (!sent_mail)
  998.             {
  999.                 /* We connected but the transfer didn't work */
  1000.                 (void) bad_call (address, 1);
  1001.             }
  1002.             else
  1003.             {
  1004.                 /* We got through, so delete his status file */
  1005.                 (void) bad_call (address, -1);
  1006.                 xmit_delete ();
  1007.             }
  1008.         }
  1009.  
  1010.         if (m == 2)                /* Nothing happened */
  1011.             (void) bad_call (address, 2);
  1012.  
  1013.         /* Take an exit if we got something in */
  1014.  
  1015.         if (got_arcmail || got_packet || got_mail)
  1016.             receive_exit ();
  1017.         mailer_banner ();
  1018.     }
  1019.     else if (m < 0)
  1020.     {
  1021.         if (m == -1)
  1022.             status_line (MSG_TXT (M_INCOMING_CALL));
  1023.  
  1024.         /* Call collision or NO-DIAL-TONE. Try to answer the
  1025.            call in time to catch the remote. Exception: if it
  1026.            has been less than a minute since unbusying the line. */
  1027.  
  1028.         if (!no_inbound && timeup (waitfor_line))
  1029.         {
  1030.             m = handle_inbound_mail (1);
  1031.             if (m)
  1032.                 xmit_sameplace ();
  1033.         }
  1034.     }
  1035.  
  1036.     return (m);
  1037. }
  1038.