home *** CD-ROM | disk | FTP | other *** search
/ Super Net 1 / SUPERNET_1.iso / PC / OTROS / EXTRAS / UUCODE / UUPC / TEST / UPC12ES2.ZIP / UUCICO / modem.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-11-15  |  37.4 KB  |  1,041 lines

  1. /*--------------------------------------------------------------------*/
  2. /*    m o d e m . c                                                   */
  3. /*                                                                    */
  4. /*    High level modem control routines for UUPC/extended             */
  5. /*--------------------------------------------------------------------*/
  6.  
  7. /*--------------------------------------------------------------------*/
  8. /*       Changes Copyright (c) 1989-1993 by Kendra Electronic         */
  9. /*       Wonderworks.                                                 */
  10. /*                                                                    */
  11. /*       All rights reserved except those explicitly granted by       */
  12. /*       the UUPC/extended license agreement.                         */
  13. /*--------------------------------------------------------------------*/
  14.  
  15. /*--------------------------------------------------------------------*/
  16. /*                          RCS Information                           */
  17. /*--------------------------------------------------------------------*/
  18.  
  19. /*
  20.  *    $Id: modem.c 1.37 1993/11/15 05:43:29 ahd Exp $
  21.  *
  22.  *    Revision history:
  23.  *    $Log: modem.c $
  24.  * Revision 1.37  1993/11/15  05:43:29  ahd
  25.  * Drop BPS rate from connect messages
  26.  *
  27.  * Revision 1.36  1993/11/14  20:51:37  ahd
  28.  * Drop modem speed from network dialing/connection messages
  29.  * Normalize internal speed for network links to 115200 (a large number)
  30.  *
  31.  * Revision 1.35  1993/10/28  12:19:01  ahd
  32.  * Cosmetic time formatting twiddles and clean ups
  33.  *
  34.  * Revision 1.35  1993/10/28  12:19:01  ahd
  35.  * Cosmetic time formatting twiddles and clean ups
  36.  *
  37.  * Revision 1.34  1993/10/12  01:32:46  ahd
  38.  * Normalize comments to PL/I style
  39.  *
  40.  * Revision 1.33  1993/10/09  22:21:55  rhg
  41.  * ANSIfy source
  42.  *
  43.  * Revision 1.31  1993/10/03  22:34:33  ahd
  44.  * Insure priority values are reset when loading modem information
  45.  *
  46.  * Revision 1.30  1993/10/03  20:43:08  ahd
  47.  * Move slowWrite to script.c
  48.  *
  49.  * Revision 1.29  1993/10/01  01:17:44  ahd
  50.  * Use atol() for reading port speed
  51.  *
  52.  * Revision 1.28  1993/09/29  13:18:06  ahd
  53.  * Clear raise before calling script processor in shutDown
  54.  *
  55.  * Revision 1.28  1993/09/29  13:18:06  ahd
  56.  * Clear raise before calling script processor in shutDown
  57.  *
  58.  * Revision 1.27  1993/09/29  05:25:21  ahd
  59.  * Correct resetting of raised flag
  60.  *
  61.  * Revision 1.26  1993/09/29  04:49:20  ahd
  62.  * Allow unique signal handler for suspend port processing
  63.  *
  64.  * Revision 1.25  1993/09/28  01:38:19  ahd
  65.  * Add configurable timeout for conversation start up phase
  66.  *
  67.  * Revision 1.24  1993/09/27  04:04:06  ahd
  68.  * Normalize references to modem speed to avoid incorrect displays
  69.  *
  70.  * Revision 1.23  1993/09/27  00:45:20  ahd
  71.  * Add suspend of serial port processing from K. Rommel
  72.  *
  73.  * Revision 1.22  1993/09/25  03:07:56  ahd
  74.  * Invoke set priority functions
  75.  *
  76.  * Revision 1.21  1993/09/23  03:26:51  ahd
  77.  * Never try to autobaud a network connection
  78.  *
  79.  * Revision 1.20  1993/09/20  04:46:34  ahd
  80.  * OS/2 2.x support (BC++ 1.0 support)
  81.  * TCP/IP support from Dave Watt
  82.  * 't' protocol support
  83.  *
  84.  * Revision 1.19  1993/08/03  03:11:49  ahd
  85.  * Add Description= line
  86.  *
  87.  * Revision 1.18  1993/07/13  01:13:32  ahd
  88.  * Correct message for systems waiting forever
  89.  *
  90.  * Revision 1.17  1993/07/05  14:47:05  ahd
  91.  * Drop obsolete  tag from "variablepacket"
  92.  * Set default timeout of 30 seconds for answer timeout
  93.  *
  94.  * Revision 1.16  1993/06/16  04:03:25  ahd
  95.  * Lower max wait time for NT
  96.  *
  97.  * Revision 1.15  1993/05/30  15:25:50  ahd
  98.  * Multiple driver support
  99.  *
  100.  * Revision 1.14  1993/05/30  00:04:53  ahd
  101.  * Multiple communications drivers support
  102.  *
  103.  * Revision 1.13  1993/04/15  03:21:06  ahd
  104.  * Add CD() call to hot login procedure
  105.  *
  106.  * Revision 1.12  1993/04/11  00:34:11  ahd
  107.  * Global edits for year, TEXT, etc.
  108.  *
  109.  * Revision 1.11  1993/04/05  04:35:40  ahd
  110.  * Set clear abort processing flag (norecover) from ulib.c
  111.  *
  112.  * Revision 1.10  1993/03/06  23:04:54  ahd
  113.  * make modem connected messages consistent
  114.  *
  115.  * Revision 1.9  1993/01/23  19:08:09  ahd
  116.  * Add additional shutDown() commands even when modem does not init
  117.  *
  118.  * Revision 1.8  1992/12/30  13:11:44  dmwatt
  119.  * Check for NULL brand pointer before comparing
  120.  *
  121.  * Revision 1.7  1992/12/18  12:05:57  ahd
  122.  * Flag variable packet as obsolete
  123.  *
  124.  * Revision 1.6  1992/11/28  19:51:16  ahd
  125.  * Add program exit time to waiting for callin message
  126.  * Make time parameter to callin() const
  127.  *
  128.  * Revision 1.5  1992/11/22  21:20:45  ahd
  129.  * Use strpool for const string allocation
  130.  *
  131.  * Revision 1.4  1992/11/19  03:01:21  ahd
  132.  * drop rcsid
  133.  *
  134.  * Revision 1.3  1992/11/18  03:48:24  ahd
  135.  * Move check of call window to avoid premature lock file overhead
  136.  *
  137.  * Revision 1.2  1992/11/15  20:12:17  ahd
  138.  * Clean up modem file support for different protocols
  139.  *
  140.  * Revision 1.1  1992/11/12  12:32:18  ahd
  141.  * Initial revision
  142.  *
  143.  */
  144.  
  145. /*--------------------------------------------------------------------*/
  146. /*                        System include files                        */
  147. /*--------------------------------------------------------------------*/
  148.  
  149. #include <limits.h>
  150. #include <stdio.h>
  151. #include <stdlib.h>
  152. #include <string.h>
  153. #include <ctype.h>
  154. #include <time.h>
  155. #include <limits.h>
  156. #include <sys/types.h>
  157.  
  158. /*--------------------------------------------------------------------*/
  159. /*                    UUPC/extended include files                     */
  160. /*--------------------------------------------------------------------*/
  161.  
  162. #include "lib.h"
  163. #include "hostable.h"
  164. #include "catcher.h"
  165. #include "checktim.h"
  166. #include "commlib.h"
  167. #include "dater.h"
  168. #include "dcp.h"
  169. #include "dcpsys.h"
  170. #include "hlib.h"
  171. #include "modem.h"
  172. #include "script.h"
  173. #include "security.h"
  174. #include "ssleep.h"
  175. #include "suspend.h"
  176. #include "usrcatch.h"
  177.  
  178. /*--------------------------------------------------------------------*/
  179. /*                          Global variables                          */
  180. /*--------------------------------------------------------------------*/
  181.  
  182. char *M_device = NULL;          /*Public to show in login banner     */
  183.  
  184. static char **answer, **initialize, **dropline, **ring, **connect;
  185. static char **noconnect;
  186. static char *dialPrefix, *dialSuffix;
  187. static char *M_suite;
  188. static char *dummy;
  189.  
  190. static KEWSHORT dialTimeout, modemTimeout, scriptTimeout;
  191. static KEWSHORT answerTimeout;
  192. static BPS inspeed;
  193. static KEWSHORT gWindowSize, gPacketSize;
  194. static KEWSHORT vWindowSize, vPacketSize;
  195. static KEWSHORT GWindowSize, GPacketSize;
  196.  
  197. KEWSHORT M_charDelay;
  198. KEWSHORT M_fPacketSize;
  199. KEWSHORT M_gPacketTimeout;       /* "g" procotol                  */
  200. KEWSHORT M_fPacketTimeout;       /* "f" procotol                  */
  201. KEWSHORT M_tPacketTimeout;       /* "t" procotol                  */
  202. KEWSHORT M_startupTimeout;       /* pre-procotol exchanges        */
  203. KEWSHORT M_MaxErr= 10;        /* Allowed errors per single packet    */
  204. KEWSHORT M_MaxErr;            /* Allowed errors per single packet    */
  205. KEWLONG  M_xfer_bufsize;      /* Buffering used for file transfers */
  206. static KEWSHORT M_priority = 999;
  207. static KEWSHORT M_prioritydelta = 999;
  208.  
  209. boolean bmodemflag[MODEM_LAST];
  210.  
  211. static FLAGTABLE modemFlags[] = {
  212.    { "carrierdetect",  MODEM_CD,          B_LOCAL },
  213.    { "direct",         MODEM_DIRECT,      B_LOCAL },
  214.    { "fixedspeed",     MODEM_FIXEDSPEED,  B_LOCAL },
  215.    { "variablepacket", MODEM_VARIABLEPACKET, B_LOCAL },
  216.    { "largepacket",    MODEM_LARGEPACKET, B_LOCAL | B_OBSOLETE },
  217.    { nil(char) }
  218. }           ;
  219.  
  220. static CONFIGTABLE modemtable[] = {
  221.    { "answer",        (char **) &answer,       B_LIST   | B_UUCICO },
  222.    { "answertimeout", (char **) &answerTimeout,B_SHORT| B_UUCICO },
  223.    { "biggpacketsize",(char **) &GPacketSize,  B_SHORT| B_UUCICO },
  224.    { "biggwindowsize",(char **) &GWindowSize,  B_SHORT| B_UUCICO },
  225.    { "chardelay",     (char **) &M_charDelay,  B_SHORT| B_UUCICO },
  226.    { "connect",       (char **) &connect,      B_LIST   | B_UUCICO },
  227.    { "description",   &dummy,                  B_TOKEN  },
  228.    { "device",        &M_device,               B_TOKEN| B_UUCICO | B_REQUIRED },
  229.    { "dialprefix",    &dialPrefix,B_STRING | B_UUCICO | B_REQUIRED },
  230.    { "dialsuffix",    &dialSuffix,             B_STRING | B_UUCICO },
  231.    { "dialtimeout",   (char **) &dialTimeout,  B_SHORT| B_UUCICO },
  232.    { "fpacketsize",   (char **) &M_fPacketSize,B_SHORT| B_UUCICO },
  233.    { "fpackettimeout",(char **) &M_fPacketTimeout, B_SHORT | B_UUCICO },
  234.    { "gpacketsize",   (char **) &gPacketSize,  B_SHORT| B_UUCICO },
  235.    { "gpackettimeout",(char **) &M_gPacketTimeout, B_SHORT | B_UUCICO },
  236.    { "gwindowsize",   (char **) &gWindowSize,  B_SHORT| B_UUCICO },
  237.    { "hangup",        (char **) &dropline,     B_LIST   | B_UUCICO },
  238.    { "initialize",    (char **) &initialize,   B_LIST   | B_UUCICO },
  239.    { "inspeed",       (char **) &inspeed,      B_LONG   | B_UUCICO },
  240.    { "maximumerrors", (char **) &M_MaxErr,     B_SHORT| B_UUCICO },
  241.    { "modemtimeout",  (char **) &modemTimeout, B_SHORT| B_UUCICO },
  242.    { "noconnect",     (char **) &noconnect,    B_LIST   | B_UUCICO },
  243.    { "options",       (char **) bmodemflag,    B_ALL    | B_BOOLEAN},
  244.    { "porttimeout",   NULL,                    B_OBSOLETE },
  245.    {"priority",       (char **) &M_priority,     B_SHORT |B_UUCICO},
  246.    {"prioritydelta",  (char **) &M_prioritydelta,B_SHORT |B_UUCICO},
  247.    { "ring",          (char **) &ring,         B_LIST   | B_UUCICO },
  248.    { "scripttimeout", (char **) &scriptTimeout,B_SHORT| B_UUCICO },
  249.    { "startuptimeout",(char **) &M_startupTimeout, B_SHORT | B_UUCICO },
  250.    { "suite",         &M_suite,                B_TOKEN  | B_UUCICO },
  251.    { "transferbuffer",(char **) &M_xfer_bufsize, B_LONG| B_UUCICO },
  252.    { "tpackettimeout",(char **) &M_tPacketTimeout, B_SHORT | B_UUCICO },
  253.    { "version",       &dummy,                  B_TOKEN  },
  254.    { "vpacketsize",   (char **) &vPacketSize,  B_SHORT| B_UUCICO },
  255.    { "vwindowsize",   (char **) &vWindowSize,  B_SHORT| B_UUCICO },
  256.    { nil(char) }
  257. }; /* modemtable */
  258.  
  259. /*--------------------------------------------------------------------*/
  260. /*                    Internal function prototypes                    */
  261. /*--------------------------------------------------------------------*/
  262.  
  263. static boolean dial(char *number, const BPS speed);
  264.  
  265. static boolean sendlist( char **list, int timeout, int lasttimeout,
  266.                          char **failure);
  267.  
  268. static boolean sendalt( char *string, int timeout, char **failure);
  269.  
  270. static void autobaud( const BPS speed);
  271.  
  272. /*--------------------------------------------------------------------*/
  273. /*              Define current file name for references               */
  274. /*--------------------------------------------------------------------*/
  275.  
  276. currentfile();
  277.  
  278. /*--------------------------------------------------------------------*/
  279. /*    c a l l u p                                                     */
  280. /*                                                                    */
  281. /*    script processor - nothing fancy!                               */
  282. /*--------------------------------------------------------------------*/
  283.  
  284. CONN_STATE callup( void )
  285. {
  286.    char *exp;
  287.    int i;
  288.    BPS speed = 115200;              /* Bogus network speed default   */
  289.    time_t now;
  290.  
  291. /*--------------------------------------------------------------------*/
  292. /*             Announce we are trying to call the system              */
  293. /*--------------------------------------------------------------------*/
  294.  
  295.    time( &now );
  296.    if ( IsNetwork() )
  297.       printmsg(1,"callup: Connecting to %s via %s on %.24s",
  298.                 rmtname,
  299.                 flds[FLD_TYPE],
  300.                 ctime( &now ));
  301.    else {
  302.       printmsg(1, "callup: Calling %s via %s at %s on %.24s",
  303.           rmtname,
  304.           flds[FLD_TYPE],
  305.           flds[FLD_SPEED],
  306.           ctime( &now ));
  307.  
  308.       speed = (BPS) atol( flds[FLD_SPEED] );
  309.  
  310.       if (speed < 300)
  311.       {
  312.          printmsg(0,"callup: Modem speed %s is invalid.",
  313.                      flds[FLD_SPEED]);
  314.          hostp->hstatus = invalid_device;
  315.          return CONN_INITIALIZE;
  316.  
  317.       } /* if (speed < 300) */
  318.  
  319.    } /* else */
  320.  
  321. /*--------------------------------------------------------------------*/
  322. /*                         Dial the telephone                         */
  323. /*--------------------------------------------------------------------*/
  324.  
  325.    if (! dial(flds[FLD_PHONE],speed))
  326.       return CONN_DROPLINE;
  327.  
  328. /*--------------------------------------------------------------------*/
  329. /*             The modem is connected; now login the host             */
  330. /*--------------------------------------------------------------------*/
  331.  
  332.    for (i = FLD_EXPECT; i < kflds; i += 2)
  333.    {
  334.  
  335.       exp = flds[i];
  336.       printmsg(2, "expecting %d of %d \"%s\"", i, kflds, exp);
  337.       if (!sendalt( exp, scriptTimeout , noconnect))
  338.       {
  339.          printmsg(0, "SCRIPT FAILED");
  340.          hostp->hstatus =  script_failed;
  341.          return CONN_DROPLINE;
  342.       } /* if */
  343.  
  344.       printmsg(2, "callup: sending %d of %d \"%s\"",
  345.                    i + 1, kflds, flds[i + 1]);
  346.       sendstr(flds[i + 1]);
  347.  
  348.    } /*for*/
  349.  
  350.    return CONN_PROTOCOL;
  351.  
  352. } /*callup*/
  353.  
  354. /*--------------------------------------------------------------------*/
  355. /*    c a l l h o t                                                   */
  356. /*                                                                    */
  357. /*    Initialize processing when phone is already off the hook        */
  358. /*--------------------------------------------------------------------*/
  359.  
  360. CONN_STATE callhot( const BPS xspeed )
  361. {
  362.    BPS speed;
  363.  
  364. /*--------------------------------------------------------------------*/
  365. /*                        Open the serial port                        */
  366. /*--------------------------------------------------------------------*/
  367.  
  368.    if (E_inmodem == NULL)
  369.    {
  370.       printmsg(0,"callin: No modem name supplied for incoming calls!");
  371.       panic();
  372.    } /* if */
  373.  
  374. /*--------------------------------------------------------------------*/
  375. /*                        Set the modem speed                         */
  376. /*--------------------------------------------------------------------*/
  377.  
  378.    if ( xspeed == 0)
  379.       speed = inspeed;
  380.    else
  381.       speed = xspeed;
  382.  
  383. /*--------------------------------------------------------------------*/
  384. /*                    Open the communications port                    */
  385. /*--------------------------------------------------------------------*/
  386.  
  387.    norecovery = FALSE;           /* Shutdown gracefully as needed     */
  388.    if (activeopenline(M_device, speed, bmodemflag[MODEM_DIRECT] ))
  389.       panic();
  390.  
  391. /*--------------------------------------------------------------------*/
  392. /*                          Initialize stats                          */
  393. /*--------------------------------------------------------------------*/
  394.  
  395.    memset( &remote_stats, 0, sizeof remote_stats);
  396.                               /* Clear remote stats for login        */
  397.    time(&remote_stats.ltime); /* Remember time of last attempt conn  */
  398.    remote_stats.calls ++ ;
  399.  
  400.    if (bmodemflag[MODEM_CD])
  401.       CD();                   /* Set the carrier detect flags        */
  402.  
  403.    return CONN_HOTLOGIN;
  404.  
  405. } /* callhot */
  406.  
  407. /*--------------------------------------------------------------------*/
  408. /*    c a l l i n                                                     */
  409. /*                                                                    */
  410. /*    Answer the modem in passive mode                                */
  411. /*--------------------------------------------------------------------*/
  412.  
  413. CONN_STATE callin( const time_t exit_time )
  414. {
  415.    char c;                    /* A character for input buffer        */
  416.  
  417.    int    offset;             /* Time to wait for telephone          */
  418.    time_t now, left;
  419.  
  420. /*--------------------------------------------------------------------*/
  421. /*    Determine how long we can wait for the telephone, up to         */
  422. /*    SHRT_MAX seconds.  Aside from Turbo C limits, this insures we   */
  423. /*    kick the modem once in a while.                                 */
  424. /*--------------------------------------------------------------------*/
  425.  
  426.       if ((now = time(NULL)) > exit_time) /* Any time left?          */
  427.          return CONN_EXIT;             /* No --> shutdown            */
  428.  
  429.       if ( (left = exit_time - now) > SHRT_MAX)
  430.          offset = SHRT_MAX;
  431.       else
  432.          offset = (int) left;
  433.  
  434. /*--------------------------------------------------------------------*/
  435. /*                        Open the serial port                        */
  436. /*--------------------------------------------------------------------*/
  437.  
  438.    if (E_inmodem == NULL)
  439.    {
  440.       printmsg(0,"callin: No modem name supplied for incoming calls!");
  441.       panic();
  442.    } /* if */
  443.  
  444. /*--------------------------------------------------------------------*/
  445. /*                    Open the communications port                    */
  446. /*--------------------------------------------------------------------*/
  447.  
  448.    norecovery = FALSE;           /* Shutdown gracefully as needed     */
  449.  
  450. /*--------------------------------------------------------------------*/
  451. /*              Flush the input buffer of any characters              */
  452. /*--------------------------------------------------------------------*/
  453.  
  454.    if ( IsNetwork() )
  455.    {
  456.       if (passiveopenline(M_device, inspeed, bmodemflag[MODEM_DIRECT]))
  457.          panic();
  458.    }
  459.    else {
  460.       if (((ring == NULL) || (inspeed == 0)))
  461.       {
  462.          printmsg(0,"callin: Missing inspeed and/or ring values in modem "
  463.                     "configuration file.");
  464.          panic();
  465.       } /* if */
  466.  
  467.       if (passiveopenline(M_device, inspeed, bmodemflag[MODEM_DIRECT]))
  468.          panic();
  469.  
  470.       while (sread(&c ,1,0)); /* Discard trailing trash from modem
  471.                                  connect message                     */
  472.  
  473. /*--------------------------------------------------------------------*/
  474. /*                        Initialize the modem                        */
  475. /*--------------------------------------------------------------------*/
  476.  
  477.       if (!sendlist( initialize, modemTimeout, modemTimeout, NULL))
  478.       {
  479.          printmsg(0,"callin: Modem failed to initialize");
  480.          shutDown();
  481.          panic();
  482.       }
  483.  
  484.    } /* else */
  485.  
  486. /*--------------------------------------------------------------------*/
  487. /*                   Wait for the telephone to ring                   */
  488. /*--------------------------------------------------------------------*/
  489.  
  490.    printmsg(1,"Monitoring port %s device %s"
  491.                      " for %d minutes until %s",
  492.                      M_device, E_inmodem , (int) (offset / 60),
  493.                      (left > hhmm2sec(10000)) ?
  494.                               "user hits Ctrl-Break" :
  495.                               dater( exit_time , NULL));
  496.  
  497.    interactive_processing = FALSE;
  498.  
  499.    if (IsNetwork())
  500.    {                          /* Network connect is different        */
  501.       if (!WaitForNetConnect(offset))
  502.       {
  503.          interactive_processing = TRUE;
  504.          shutDown();
  505.          if ( suspend_processing )        /* Give up modem for another process?  */
  506.          {
  507.            return CONN_WAIT;
  508.          }
  509.          return CONN_INITIALIZE;
  510.       }
  511.  
  512.       interactive_processing = TRUE;
  513.       printmsg(14, "callin: Modem reports connected");
  514.  
  515.    }
  516.    else {
  517.       if (!sendlist( ring,modemTimeout, offset, noconnect))
  518.       {                          /* Did it ring?                       */
  519.          interactive_processing = TRUE;
  520.          raised = 0;
  521.          shutDown();
  522.          if ( suspend_processing )        /* Give up modem for another process?  */
  523.             return CONN_WAIT;
  524.          else
  525.             return CONN_INITIALIZE;     /* No --> Return to caller    */
  526.       }
  527.  
  528.       interactive_processing = TRUE;
  529.  
  530.       setPrty(M_priority, M_prioritydelta );
  531.                               /* Into warp drive for actual transfers  */
  532.  
  533.       if(!sendlist(answer, modemTimeout,answerTimeout, noconnect))
  534.       {                           /* Pick up the telephone            */
  535.          printmsg(1,"callin: Modem failed to connect to incoming call");
  536.          shutDown();
  537.          return CONN_INITIALIZE;
  538.       }
  539.  
  540.       printmsg(14, "callin: Modem reports connected");
  541.  
  542.       autobaud(inspeed);      /* autobaud the modem                  */
  543.  
  544. /*--------------------------------------------------------------------*/
  545. /*        Flush the input buffer of any other input characters        */
  546. /*--------------------------------------------------------------------*/
  547.  
  548.       while (sread(&c ,1,0)); /* Discard trailing trash from modem
  549.                                  connect message                     */
  550.  
  551.    } /* else */
  552.  
  553.    memset( &remote_stats, 0, sizeof remote_stats);
  554.                               /* Clear remote stats for login        */
  555.  
  556.    time(&remote_stats.ltime); /* Remember time of last attempt conn  */
  557.    remote_stats.calls ++ ;
  558.  
  559.  
  560.    return CONN_LOGIN;
  561.  
  562. } /* callin */
  563.  
  564. /*--------------------------------------------------------------------*/
  565. /*    g e t m o d e m                                                 */
  566. /*                                                                    */
  567. /*    Read a modem configuration file                                 */
  568. /*--------------------------------------------------------------------*/
  569.  
  570. boolean getmodem( const char *brand)
  571. {
  572.    char filename[FILENAME_MAX];
  573.    static char *modem = NULL;
  574.    FILE *fp;
  575.    CONFIGTABLE *tptr;
  576.    size_t subscript;
  577.    boolean success;
  578.  
  579. /*--------------------------------------------------------------------*/
  580. /*                      Validate the modem name                       */
  581. /*   Added check for validity of modem ptr -- makes NT happier - dmw  */
  582. /*--------------------------------------------------------------------*/
  583.  
  584.    if ((modem != NULL) && equal(modem, brand)) /* Already initialized?*/
  585.       return TRUE;            /* Yes --> Don't process it again      */
  586.  
  587. /*--------------------------------------------------------------------*/
  588. /*                        Initialize the table                        */
  589. /*--------------------------------------------------------------------*/
  590.  
  591.    for (tptr = modemtable; tptr->sym != nil(char); tptr++)
  592.       if (tptr->bits & (B_TOKEN | B_STRING | B_LIST | B_CLIST))
  593.          *(tptr->loc) = nil(char);
  594.  
  595.    for (subscript = 0; subscript < MODEM_LAST; subscript++)
  596.       bmodemflag[subscript] = FALSE;
  597.  
  598.    M_charDelay = 00;          /* Default is no delay between chars    */
  599.    dialTimeout = 40;          /* Default is 40 seconds to dial phone  */
  600.    gPacketSize = SMALL_PACKET;
  601.    vPacketSize = MAXPACK;
  602.    GPacketSize = MAXPACK;
  603.    gWindowSize = 0;
  604.    vWindowSize = 0;
  605.    GWindowSize = 0;
  606.    M_fPacketSize = MAXPACK;
  607.    M_fPacketTimeout = 20;
  608.    M_gPacketTimeout = 10;
  609.    M_tPacketTimeout = 60;
  610.    modemTimeout  = 3;         /* Default is 3 seconds for modem cmds  */
  611.    scriptTimeout = 30;        /* Default is 30 seconds for script data*/
  612.    answerTimeout = 30;        /* Default is 30 seconds to answer phone*/
  613.    M_xfer_bufsize = BUFSIZ;   /* Buffering used for file transfers    */
  614.    M_MaxErr= 10;              /* Allowed errors per single packet     */
  615.    M_suite = NULL;            /* Use default suite for communications  */
  616.    M_startupTimeout = 40;     /* 40 seconds per message to exchange protocols  */
  617.  
  618.    M_priority = 999;
  619.    M_prioritydelta = 999;
  620.  
  621. /*--------------------------------------------------------------------*/
  622. /*                 Open the modem configuration file                  */
  623. /*--------------------------------------------------------------------*/
  624.  
  625.    if (equaln(brand,"COM",3))
  626.    {
  627.       printmsg(0,"Modem type %s is invalid; Snuffles suspects "
  628.                "your %s file is obsolete.", brand, E_systems);
  629.       panic();
  630.    }
  631.  
  632.    sprintf(filename,"%s/%s.MDM",E_confdir, brand);
  633.    if ((fp = FOPEN(filename, "r",TEXT_MODE)) == nil(FILE))
  634.    {
  635.       printmsg(0,"getmodem: Unable to locate configuration for %s",
  636.                brand);
  637.       printerr( filename );
  638.       return FALSE;
  639.    }
  640.  
  641. /*--------------------------------------------------------------------*/
  642. /*                We got the file open, now process it                */
  643. /*--------------------------------------------------------------------*/
  644.  
  645.    printmsg(3,"getmodem: loading modem configuration file %s", filename);
  646.    success = getconfig(fp, MODEM_CONFIG, B_UUCICO, modemtable, modemFlags);
  647.    fclose(fp);
  648.    if (!success)
  649.       return FALSE;
  650.  
  651. /*--------------------------------------------------------------------*/
  652. /*         Verify all required modem parameters were supplied         */
  653. /*--------------------------------------------------------------------*/
  654.  
  655.    success = TRUE;
  656.    for (tptr = modemtable; tptr->sym != nil(char); tptr++) {
  657.       if ((tptr->bits & (B_REQUIRED | B_FOUND)) == B_REQUIRED)
  658.       {
  659.          printmsg(0, "getmodem: configuration parameter \"%s\" must be set.",
  660.             tptr->sym);
  661.          success = FALSE;
  662.       } /* if */
  663.    } /* for */
  664.  
  665.    if ( ! success )           /* Missing any required inputs?         */
  666.       return success;         /* Yes --> Return failure to caller     */
  667.  
  668. /*--------------------------------------------------------------------*/
  669. /*       The strings are valid, try to initialize the pointers to     */
  670. /*       the processing routines.                                     */
  671. /*--------------------------------------------------------------------*/
  672.  
  673.    if ( ! chooseCommunications( M_suite ))
  674.       return FALSE;
  675.  
  676. /*--------------------------------------------------------------------*/
  677. /*       We have success, save modem name for next time to speed      */
  678. /*       initialize.                                                  */
  679. /*--------------------------------------------------------------------*/
  680.  
  681.    modem = newstr(brand);  /* Yes --> Remember it for next time   */
  682.  
  683.    return TRUE;
  684.  
  685. } /* getmodem */
  686.  
  687. /*--------------------------------------------------------------------*/
  688. /*    d i a l                                                         */
  689. /*                                                                    */
  690. /*    Generic modem dialer; only major limitation is that autoabaud   */
  691. /*    strings are not configurable                                    */
  692. /*--------------------------------------------------------------------*/
  693.  
  694. static boolean dial(char *number, const BPS speed)
  695. {
  696.    char buf[81];
  697.  
  698. /*--------------------------------------------------------------------*/
  699. /*                        Open the serial port                        */
  700. /*--------------------------------------------------------------------*/
  701.  
  702.    norecovery = FALSE;           /* Shutdown gracefully as needed     */
  703.  
  704. /*--------------------------------------------------------------------*/
  705. /*              Flush the input buffer of any characters              */
  706. /*--------------------------------------------------------------------*/
  707.  
  708.    if ( IsNetwork() )
  709.    {
  710.       if (activeopenline(number, speed, bmodemflag[MODEM_DIRECT]))
  711.       {
  712.          hostp->hstatus =  nodevice;
  713.          return FALSE;
  714.       }
  715.    }
  716.    else {
  717.  
  718.       if (activeopenline(M_device, speed, bmodemflag[MODEM_DIRECT]))
  719.       {
  720.  
  721.          hostp->hstatus =  nodevice;
  722.          return FALSE;
  723.       }
  724.  
  725.       while (sread(buf,1,0)); /* Discard trailing trash from modem
  726.                                  connect message                     */
  727.  
  728. /*--------------------------------------------------------------------*/
  729. /*                        Initialize the modem                        */
  730. /*--------------------------------------------------------------------*/
  731.  
  732.       if (!sendlist( initialize, modemTimeout, modemTimeout, noconnect))
  733.       {
  734.          printmsg(0,"dial: Modem failed to initialize");
  735.          shutDown();
  736.          hostp->hstatus =  dial_script_failed;
  737.          return FALSE;
  738.       }
  739.  
  740. /*--------------------------------------------------------------------*/
  741. /*           Setup the dial string and then dial the modem            */
  742. /*--------------------------------------------------------------------*/
  743.  
  744.       strcpy(buf, dialPrefix);
  745.       strcat(buf, number);
  746.       if (dialSuffix != NULL)
  747.          strcat(buf, dialSuffix);
  748.  
  749.       sendstr( buf );         /* Send the command to the telephone     */
  750.  
  751.       if (!sendlist(connect,  modemTimeout, dialTimeout, noconnect))
  752.       {
  753.          hostp->hstatus =  dial_failed;
  754.          return FALSE;
  755.       }
  756.  
  757.    }  /* if ( !IsNetwork() ) */
  758.  
  759.    printmsg(3, "dial: Modem reports connected");
  760.  
  761.    time( &remote_stats.lconnect );
  762.    remote_stats.calls ++ ;
  763.  
  764.    if ( !IsNetwork() )
  765.       autobaud(speed);     /* Reset modem speed, if desired          */
  766.  
  767.    setPrty(M_priority, M_prioritydelta );
  768.  
  769. /*--------------------------------------------------------------------*/
  770. /*                      Report success to caller                      */
  771. /*--------------------------------------------------------------------*/
  772.  
  773.    return TRUE;            /* Dial succeeded    */
  774.  
  775. } /* dial */
  776.  
  777. /*--------------------------------------------------------------------*/
  778. /*    a u t o b a u d                                                 */
  779. /*                                                                    */
  780. /*    autobaud a modem which has just connected                       */
  781. /*--------------------------------------------------------------------*/
  782.  
  783. static void autobaud( const BPS speed )
  784. {
  785.    char buf[10];
  786.  
  787.    ssleep(1);                 /*  Allow modem port to stablize       */
  788.  
  789.    if (bmodemflag[MODEM_CD])
  790.       CD();                   /* Set the carrier detect flags        */
  791.  
  792. /*--------------------------------------------------------------------*/
  793. /*                  Autobaud the modem if requested                   */
  794. /*--------------------------------------------------------------------*/
  795.  
  796.    if (!bmodemflag[MODEM_FIXEDSPEED])
  797.    {
  798.       size_t len = 0;
  799.  
  800.       memset( buf, '\0', sizeof( buf ));  /* Zero buffer               */
  801.       while ((len < sizeof buf) && sread( &buf[len],1,0))
  802.          len = strlen( buf );             /* Get speed into buffer     */
  803.  
  804.       if (len > 5)
  805.       {
  806.          char  *token;           /* Pointer to buffer value */
  807.          token = strtok(buf,WHITESPACE);
  808.          if (strlen(token))
  809.          {
  810.             BPS new_speed = (unsigned) atol(token);
  811.             if ((new_speed != speed) && (new_speed > 300))
  812.             {
  813.                printmsg(2, "autobaud: speed select %s", token);
  814.                SIOSpeed(new_speed);
  815.             } /* if */
  816.          } /* if */
  817.       } /* if */
  818.       else
  819.          printmsg(3, "autobaud: unable to speed select, using %d", speed);
  820.    } /* if */
  821.  
  822. } /* autobaud */
  823.  
  824. /*--------------------------------------------------------------------*/
  825. /*    s h u t d o w n                                                 */
  826. /*                                                                    */
  827. /*    Terminate modem processing via hangup                           */
  828. /*--------------------------------------------------------------------*/
  829.  
  830. void shutDown( void )
  831. {
  832.    static boolean recurse = FALSE;
  833.  
  834.    if ( ! portActive )          /* Allowed for Ctrl-Break           */
  835.       return;
  836.  
  837.    if ( !recurse )
  838.    {
  839.       boolean aborted = terminate_processing;
  840.       unsigned long saveRaised = raised;
  841.       recurse = TRUE;
  842.       terminate_processing = FALSE;
  843.       raised = 0;
  844.       hangup();
  845.       resetPrty();               /* Drop out of hyperspace            */
  846.       sendlist( dropline, modemTimeout, modemTimeout, NULL);
  847.       recurse = FALSE;
  848.       terminate_processing |= aborted;
  849.       saveRaised |= raised;
  850.    }
  851.  
  852.    closeline();
  853.    norecovery = TRUE;
  854.  
  855. }  /* shutDown */
  856.  
  857. /*--------------------------------------------------------------------*/
  858. /*    s e n d l i s t                                                 */
  859. /*                                                                    */
  860. /*    Send a NULL terminated list of send/expect strings              */
  861. /*--------------------------------------------------------------------*/
  862.  
  863. static boolean sendlist(   char **list,
  864.                            int timeout,
  865.                            int lasttimeout,
  866.                            char **failure)
  867. {
  868.    boolean expect = TRUE;
  869.  
  870.    if (list == NULL)          /* Was the field supplied?             */
  871.       return TRUE;            /* No --> Must be optional, return     */
  872.  
  873. /*--------------------------------------------------------------------*/
  874. /*     Run through the list, alternating expect and send strings      */
  875. /*--------------------------------------------------------------------*/
  876.  
  877.    while( *list != NULL)
  878.    {
  879.  
  880.       if (expect)
  881.       {
  882.          char *exp = strdup( *list );
  883.          boolean success;
  884.          checkref( exp );
  885.          success = sendalt( exp,
  886.                             (*(++list) == NULL) ? lasttimeout : timeout,
  887.                             failure);
  888.          free( exp );
  889.          if (!success)
  890.             return FALSE;
  891.       }
  892.       else
  893.          sendstr( *list++ );
  894.       expect = ! expect;
  895.    } /* while */
  896.  
  897. /*--------------------------------------------------------------------*/
  898. /*    If we made it this far, success is at hand; return to caller    */
  899. /*--------------------------------------------------------------------*/
  900.  
  901.    return TRUE;
  902. } /* sendlist */
  903.  
  904. /*--------------------------------------------------------------------*/
  905. /*    s e n d a l t                                                   */
  906. /*                                                                    */
  907. /*    Expect a string, with alternates                                */
  908. /*--------------------------------------------------------------------*/
  909.  
  910. static boolean sendalt( char *exp, int timeout, char **failure)
  911. {
  912.    int ok;
  913.  
  914.    for ( ;; )
  915.    {
  916.       char *alternate = strchr(exp, '-');
  917.  
  918.       if (alternate != nil(char))
  919.          *alternate++ = '\0';
  920.  
  921.       ok = expectstr(exp, timeout, failure);
  922.  
  923.       if ( terminate_processing || raised )
  924.       {
  925.          shutDown();
  926.          return FALSE;
  927.       }
  928.  
  929.       if (ok || (alternate == nil(char)))
  930.          return (ok == 1);
  931.  
  932.       if (bmodemflag[MODEM_CD] && ! CD())
  933.       {
  934.          printmsg(0,"sendalt: Serial port reports modem not ready");
  935.          return FALSE;
  936.       }
  937.  
  938.       exp = strchr(alternate, '-');
  939.       if (exp != nil(char))
  940.          *exp++ = '\0';
  941.  
  942.       printmsg(0, "sending alternate");
  943.       sendstr(alternate);
  944.    } /*for*/
  945.  
  946. } /* sendalt */
  947.  
  948. /*--------------------------------------------------------------------*/
  949. /*    G e t G W i n d o w                                             */
  950. /*                                                                    */
  951. /*    Report the size of the allowed window for the "g" protocol      */
  952. /*--------------------------------------------------------------------*/
  953.  
  954. KEWSHORT GetGWindow(  KEWSHORT maxvalue , const char protocol )
  955. {
  956.    KEWSHORT ourWindowSize = 0;
  957.  
  958.    switch( protocol )
  959.    {
  960.       case 'g':
  961.          ourWindowSize = gWindowSize;
  962.          break;
  963.  
  964.       case 'G':
  965.          ourWindowSize = GWindowSize;
  966.          break;
  967.  
  968.       case 'v':
  969.          ourWindowSize = vWindowSize;
  970.          break;
  971.  
  972.       default:
  973.          printmsg(0,"GetGWindow: Invalid protocol %c",protocol);
  974.          panic();
  975.    }
  976.  
  977.    if ( (ourWindowSize < 1 ) || (ourWindowSize > maxvalue))
  978.       return maxvalue;
  979.    else
  980.       return ourWindowSize;
  981.  
  982. } /* GetGWindow */
  983.  
  984. /*--------------------------------------------------------------------*/
  985. /*    G e t G P a c k e t                                             */
  986. /*                                                                    */
  987. /*    Return the allowed packet size for the "g" procotol             */
  988. /*--------------------------------------------------------------------*/
  989.  
  990. KEWSHORT GetGPacket( KEWSHORT maxvalue , const char protocol)
  991. {
  992.    KEWSHORT savePacketSize ;
  993.    KEWSHORT ourPacketSize = 0;
  994.    int bits = 6;              /* Minimum Packet Size is 64 bytes     */
  995.  
  996.    switch( protocol )
  997.    {
  998.       case 'g':
  999.          ourPacketSize = gPacketSize;
  1000.          break;
  1001.  
  1002.       case 'G':
  1003.          ourPacketSize = GPacketSize;
  1004.          break;
  1005.  
  1006.       case 'v':
  1007.          ourPacketSize = vPacketSize;
  1008.          break;
  1009.  
  1010.       default:
  1011.          printmsg(0,"GetGPacket: Invalid protocol %c",protocol);
  1012.          panic();
  1013.    }
  1014.  
  1015.    savePacketSize = ourPacketSize;
  1016.  
  1017. /*--------------------------------------------------------------------*/
  1018. /*                 Insure the value is a power of two                 */
  1019. /*--------------------------------------------------------------------*/
  1020.  
  1021.    while( (ourPacketSize >> (bits+1)) > 0 )
  1022.       bits++;
  1023.  
  1024.    ourPacketSize = (KEWSHORT) ((ourPacketSize >> bits) << bits);
  1025.    if ( savePacketSize != ourPacketSize )
  1026.       printmsg(0,"packetsize for %c protocol rounded down from %d to %d",
  1027.                protocol,
  1028.                (int) savePacketSize, (int) ourPacketSize );
  1029.  
  1030. /*--------------------------------------------------------------------*/
  1031. /*    Return the smaller of the argument (the largest packet size     */
  1032. /*    the packet driver supports) or what the modem file allows.      */
  1033. /*--------------------------------------------------------------------*/
  1034.  
  1035.    if ( (ourPacketSize < 1 ) || (ourPacketSize > maxvalue))
  1036.       return maxvalue;
  1037.    else
  1038.       return ourPacketSize;
  1039.  
  1040. } /* GetGPacket */
  1041.