home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / ncr9800 / ckvdia.c < prev    next >
C/C++ Source or Header  |  2020-01-01  |  41KB  |  1,102 lines

  1. char     *dialv = "Dial Command, V2.0(010) 10 May 90";
  2.  
  3. /*  C K V D I A  --  Dialing program for connection to remote system */
  4.  
  5. /**********************************************************************
  6. *                                                                     *
  7. * IVS / MCS-Kermit REL 2                                              *
  8. * source code                                                         *
  9. *                                                                     *
  10. * Change History:                                                     *
  11. *                                                                     *
  12. *                1. Modify C-Kermit(4E) source code to                *
  13. *                   produce new module for MCS/IVS-Kermit             *
  14. *                   ORIGINAL RELEASE                                  *
  15. *                   June 22, 1990                                     *
  16. *                                                                     *
  17. *                                                                     *
  18. ***********************************************************************/
  19.  
  20.  
  21. /*
  22.  Original author: Herm Fischer (HFISCHER@USC-ECLB).
  23.  Contributed to Columbia University for inclusion in C-Kermit.
  24.  Copyright (C) 1985, Herman Fischer, 16400 Ventura Blvd, Encino CA 91436.
  25.  Permission is granted to any individual or institution to use, copy, or
  26.  redistribute this software so long as it is not sold for profit, provided this
  27.  copyright notice is retained.
  28.  
  29.  ------
  30.  
  31.  This module should work under all versions of NCR-VRX.  It calls externally
  32.  defined system-depended functions for i/o, but depends upon the existence
  33.  of various modem control functions.
  34.  
  35.  This module, and the supporting routines in the ckutio.c module, assume
  36.  that the computer and modem properly utilize the following data communi-
  37.  cations signals (that means one should prepare the modem to use, not
  38.  circumvent, these signals):
  39.  
  40.      Data Terminal Ready:  This signal is asserted by the computer
  41.      when Kermit is about to ask the modem to dial a call, and is
  42.      removed when Kermit wishes to have the modem hang up a call.
  43.      The signal is asserted both while Kermit is asking the modem
  44.      to dial a specific number, and after connection, while Kermit
  45.      is in a data exchange mode.
  46.  
  47.      Carrier detect:  This signal must be asserted by the modem when
  48.      a carrier is detected from a remote modem on a communications
  49.      circuit.  It must be removed by the modem when the circuit
  50.      disconnects or is hung up.  (Carrier detect is ignored while
  51.      Kermit is asking the modem to dial the call, because there is
  52.      no consistant usage of this signal during the dialing phase
  53.      among different modem manufacturers.)
  54.  
  55. */
  56.  
  57. /*
  58.  * Modifications:
  59.  *
  60.  *      21-Jul-85       Fixed failure returns hanging on no carrier signal
  61.  *                      Requires tthang change too (ckutio.c revision)
  62.  *                                                      -- Herm Fischer
  63.  *
  64.  *      28-Jun-85       Fixed bug with defaulting the modem-failure message
  65.  *                      in lbuf.
  66.  *                                                      -- Dan Schullman
  67.  *
  68.  *      27-Jun-85       Merged in code from Joe Orost at Berkeley for
  69.  *                      supporting the US Robotics modem, which included
  70.  *                      changing the single characters in MDMINF into
  71.  *                      multi-character strings and modifying waitFor.
  72.  *                                                      -- Dan Schullman
  73.  *
  74.  *      26-Jun-85       Allow interrupts to be used to abort dialing,
  75.  *                      and ring the bell when a connection is made.
  76.  *                      Reorganized some of the failure paths to use the
  77.  *                      same code, and now close the line on failures.
  78.  *                      Allow use of stored numbers with the DF100 and
  79.  *                      DF200 modems.  Handlers now declared after the
  80.  *                      call to setjmp.
  81.  *                                                      -- Dan Schullman
  82.  *
  83.  *      24-May-85       DF03, DF100-series, DF200-series, and "unknown" modem
  84.  *                      support added.  Also restructured the various data
  85.  *                      tables, fixed some bugs related to missing data and
  86.  *                      missing case labels, and modified the failure message
  87.  *                      to display the "reason" given by the modem.
  88.  *                                                      -- Dan Schullman
  89.  *      16-Mar-87       Support for the ATT7300 UNIX PC internal modem was
  90.  *                      added.
  91.  *                                                      -- Richard E. Hill
  92.  *
  93.  *      14-Mar-88       Rewrite code for ATT7300 (here and in ckutio.c)
  94.  *                      Avoids dial(3c) with it's LCK files, hangs up line
  95.  *                      correctly, enables user interrupts and timeouts,
  96.  *                      turns on/off the system getty() login procedure.
  97.  *                      Correct Hayes command sequence at little.
  98.  *                      Procedures: attdial, atthang, ongetty, offgetty.
  99.  *                      Parts adapted from work of Richard E. Hill and
  100.  *                      Kevin O'Gorman.
  101.  *                                                      -- Joe R. Doupnik
  102.  *
  103.  * 13-Jan-89 Add IBM/Siemens/Rolm CBX dialing support.  - F. da Cruz
  104.  *
  105.  */
  106.  
  107. /*
  108.  * To add support for another modem, do the following:
  109.  *
  110.  *      Define a modem number symbol (n_XXX) for it, keeping the list
  111.  *      in alphabetical and numerical order, and renumbering the values
  112.  *      as necessary.
  113.  *
  114.  *      Create a MDMINF structure for it, again keeping the list alphabetical
  115.  *      for sanity's sake.
  116.  *
  117.  *      Add the address of the MDMINF structure to the ptrtab array, again
  118.  *      in alphabetical and numerical order.
  119.  *
  120.  *      Add the "user visible" modem name and corresponding modem number to
  121.  *      the mdmtab array, again in alphabetical order.
  122.  *
  123.  *      Read through the code and add modem-specific sections as necessary.
  124.  */
  125.  
  126. /*
  127.  * The intent of the "unknown" modem is hopefully to allow KERMIT to support
  128.  * unknown modems by having the user type the entire autodial sequence
  129.  * (possibly including control characters, etc.) as the "phone number".
  130.  * The only reason that the CONNECT command cannot be used to do this is
  131.  * that a remote line cannot normally be opened unless carrier is present.
  132.  *
  133.  * The protocol and other characteristics of this modem are unknown, with
  134.  * some "reasonable" values being chosen for some of them.  The only way to
  135.  * detect if a connection is made is to look for carrier present.
  136.  *
  137.  * SUPPORT IS CURRENTLY ONLY PARTIALLY SKETCHED OUT FOR THIS.  ALSO, IT
  138.  * SHOULD PERHAPS BE HANDLED MUCH EARLIER, SIMPLY READING USER INPUT AND
  139.  * SENDING IT TO THE MODEM AND ECHOING MODEM RESPONSES BACK TO THE USER,
  140.  * ALL THE TIME LOOKING FOR CARRIER.  OF COURSE, THE PROBLEM THEN BECOMES
  141.  * ONE OF ALLOWING THE USER TO CANCEL THE DIALING.  WE COULD CHOOSE SOME
  142.  * PHRASE THAT WOULD PRESUMABLY NEVER BE A PART OF A VALID AUTODIAL SEQUENCE
  143.  * (E.G., "QUIT" and "quit"). -- DS
  144.  */
  145. #include "ckcdeb.h"
  146. #include <stdio.h>
  147. #include <ctype.h>
  148. #include <signal.h>
  149. #include "ckcker.h"
  150. #include "ckucmd.h"
  151. #include "kermisc.h"
  152. #include <setjmp.h>                     /* Longjumps */
  153. #ifdef MCS_FLAG
  154. #include "mcs.h"
  155. #endif
  156.  
  157. extern int     flow, local, mdmtyp, quiet, speed, parity, seslog, ttyfd;
  158. extern char    ttname[], sesfil[], deblog;
  159. extern void    errhdlr();
  160.  
  161. #define MDMINF  struct mdminf
  162.  
  163. MDMINF          /* structure for modem-specific information */
  164. {
  165.      int     dial_time;      /* time modem allows for dialing (secs) */
  166.      char     *pause_chars;   /* character(s) to tell modem to pause */
  167.      int     pause_time;     /* time associated with pause chars (secs) */
  168.      char     *wake_str;      /* string to wakeup modem & put in cmd mode */
  169.      int     wake_rate;      /* delay between wake_str characters (msecs) */
  170.      char     *wake_prompt;   /* string prompt after wake_str */
  171.      char     *dmode_str;     /* string to put modem in dialing mode */
  172.      char     *dmode_prompt;  /* string prompt for dialing mode */
  173.      char     *dial_str;      /* dialing string, with "%s" for number */
  174.      int     dial_rate;      /* delay between dialing characters (msecs) */
  175. };
  176.  
  177.  
  178. /*
  179.  * Define symbolic modem numbers.
  180.  *
  181.  * The numbers MUST correspond to the ordering of entries
  182.  * within the ptrtab array, and start at one (1).
  183.  *
  184.  * It is assumed that there are relatively few of these
  185.  * values, and that the high(er) bytes of the value may
  186.  * be used for modem-specific mode information.
  187.  *
  188.  * REMEMBER that only the first eight characters of these
  189.  * names are guaranteed to be unique.
  190.  */
  191.  
  192. #define         n_CERMETEK       1
  193. #define         n_DF03           2
  194. #define         n_DF100          3
  195. #define         n_DF200          4
  196. #define         n_GDC            5
  197. #define         n_HAYES          6
  198. #define         n_PENRIL         7
  199. #define         n_RACAL          8
  200. #define         n_UNKNOWN        9
  201. #define         n_USROBOT       10
  202. #define         n_VENTEL        11
  203. #define         n_CONCORD       12
  204. #define         n_ATTUPC        13      /* aka NCR-VRX PC and ATT7300 */
  205. #define         n_ROLM          14      /* Rolm CBX */
  206.  
  207. /*
  208.  * Declare modem "variant" numbers for any of the above for which it is
  209.  * necessary to note various operational modes, using the second byte
  210.  * of a modem number.
  211.  *
  212.  * It is assumed that such modem modes share the same modem-specific
  213.  * information (see MDMINF structure) but may differ in some of the actions
  214.  * that are performed.
  215.  */
  216. #define         n_HAYESNV       ( n_HAYES + ( 1<<8 ) )
  217.  
  218. /*
  219.  * Declare structures containing modem-specific information.
  220.  *
  221.  * REMEMBER that only the first SEVEN characters of these
  222.  * names are guaranteed to be unique.
  223.  */
  224.  
  225. static
  226. MDMINF CERMETEK =       /* information for "Cermetek Info-Mate 212 A" modem */
  227. {
  228.      20,                 /* dial_time */
  229.      "BbPpTt",           /* pause_chars */
  230.      0,                  /* pause_time */        /** unknown -- DS **/
  231.      "  XY\016R\r",      /* wake_str */
  232.      200,                /* wake_rate */
  233.      "",                 /* wake_prompt */
  234.      "",                 /* dmode_str */
  235.      "",                 /* dmode_prompt */
  236.      "\016D '%s'\r",     /* dial_str */
  237.      200                 /* dial_rate */
  238. };
  239.  
  240.  
  241. static
  242. MDMINF DF03 =           /* information for "DEC DF03-AC" modem */
  243. {
  244.      27,                 /* dial_time */
  245.      "=",                /* pause_chars */  /* wait for second dial tone */
  246.      15,                 /* pause_time */
  247.      "\001\002",         /* wake_str */
  248.      0,                  /* wake_rate */
  249.      "",                 /* wake_prompt */
  250.      "",                 /* dmode_str */
  251.      "",                 /* dmode_prompt */
  252.      "%s",               /* dial_str */
  253.      0                   /* dial_rate */
  254. };
  255.  
  256.  
  257. static
  258. MDMINF DF100 =          /* information for "DEC DF100-series" modem */
  259. /*
  260.                          * The telephone "number" can include "P"s and/or "T"s
  261.                          * within it to indicate that subsequent digits are
  262.                          * to be dialed using pulse or tone dialing.  The
  263.                          * modem defaults to pulse dialing.  You may modify
  264.                          * the dial string below to explicitly default all
  265.                          * dialing to pulse or tone, but doing so prevents
  266.                          * the use of phone numbers that you may have stored
  267.                          * in the modem's memory.
  268.                          */
  269. {
  270.      30,                 /* dial_time */
  271.      "=",                /* pause_chars */ /* wait for second dial tone */
  272.      15,                 /* pause_time */
  273.      "\001",             /* wake_str */
  274.      0,                  /* wake_rate */
  275.      "",                 /* wake_prompt */
  276.      "",                 /* dmode_str */
  277.      "",                 /* dmode_prompt */
  278.      "%s#",              /* dial_str */
  279.      0                   /* dial_rate */
  280. };
  281.  
  282.  
  283. static
  284. MDMINF DF200 =          /* information for "DEC DF200-series" modem */
  285. /*
  286.                          * The telephone "number" can include "P"s and/or "T"s
  287.                          * within it to indicate that subsequent digits are
  288.                          * to be dialed using pulse or tone dialing.  The
  289.                          * modem defaults to pulse dialing.  You may modify
  290.                          * the dial string below to explicitly default all
  291.                          * dialing to pulse or tone, but doing so prevents
  292.                          * the use of phone numbers that you may have stored
  293.                          * in the modem's memory.
  294.                          */
  295. {
  296.      30,                 /* dial_time */
  297.      "=W",               /* pause_chars */   /* =: second tone; W: 5 secs */
  298.      15,                 /* pause_time */    /* worst case */
  299.      "\002",             /* wake_str */      /* allow stored number usage */
  300.      0,                  /* wake_rate */
  301.      "",                 /* wake_prompt */
  302.      "",                 /* dmode_str */
  303.      "",                 /* dmode_prompt */
  304.      "%s!",              /* dial_str */
  305.      0                   /* dial_rate */
  306. };
  307.  
  308.  
  309. static
  310. MDMINF GDC =            /* information for "GeneralDataComm 212A/ED" modem */
  311. {
  312.      32,                 /* dial_time */
  313.      "%",                /* pause_chars */
  314.      3,                  /* pause_time */
  315.      "\r\r",             /* wake_str */
  316.      500,                /* wake_rate */
  317.      "$",                /* wake_prompt */
  318.      "D\r",              /* dmode_str */
  319.      ":",                /* dmode_prompt */
  320.      "T%s\r",            /* dial_str */
  321.      0                   /* dial_rate */
  322. };
  323.  
  324.  
  325. static
  326. MDMINF HAYES =          /* information for "Hayes" modem */
  327. {
  328.      35,                 /* dial_time */
  329.      ",",                /* pause_chars */
  330.      2,                  /* pause_time */
  331.      "AT\r",             /* wake_str */
  332.      0,                  /* wake_rate */
  333.      "",                 /* wake_prompt */
  334.      "",                 /* dmode_str */
  335.      "",                 /* dmode_prompt */
  336.      "ATD%s\r",          /* dial_str, note: user can supply D or T */
  337.      0                   /* dial_rate */
  338. };
  339.  
  340.  
  341. static
  342. MDMINF PENRIL =         /* information for "Penril" modem */
  343. {
  344.      50,                 /* dial_time */
  345.      "",                 /* pause_chars */       /** unknown -- HF **/
  346.      0,                  /* pause_time */
  347.      "\r\r",             /* wake_str */
  348.      300,                /* wake_rate */
  349.      ">",                /* wake_prompt */
  350.      "k\r",              /* dmode_str */
  351.      ":",                /* dmode_prompt */
  352.      "%s\r",             /* dial_str */
  353.      0                   /* dial_rate */
  354. };
  355.  
  356.  
  357. static
  358. MDMINF RACAL =          /* information for "Racal Vadic" modem */
  359. {
  360.      35,                 /* dial_time */
  361.      "Kk",               /* pause_chars */
  362.      5,                  /* pause_time */
  363.      "\005\r",           /* wake_str */
  364.      50,                 /* wake_rate */
  365.      "*",                /* wake_prompt */
  366.      "D\r",              /* dmode_str */
  367.      "?",                /* dmode_prompt */
  368.      "%s\r",             /* dial_str */
  369.      0                   /* dial_rate */
  370. };
  371.  
  372.  
  373. static
  374. MDMINF UNKNOWN =        /* information for "Unknown" modem */
  375. {
  376.      30,                 /* dial_time */
  377.      "",                 /* pause_chars */
  378.      0,                  /* pause_time */
  379.      "",                 /* wake_str */
  380.      0,                  /* wake_rate */
  381.      "",                 /* wake_prompt */
  382.      "",                 /* dmode_str */
  383.      "",                 /* dmode_prompt */
  384.      "%s\r",             /* dial_str */
  385.      0                   /* dial_rate */
  386. };
  387.  
  388.  
  389. static
  390. MDMINF USROBOT =        /* information for "US Robotics 212A" modem */
  391. {
  392.      30,                 /* dial_time */
  393.      ",",                /* pause_chars */
  394.      2,                  /* pause_time */
  395.      "ATS2=01\r",        /* wake_str */
  396.      0,                  /* wake_rate */
  397.      "OK\r",             /* wake_prompt */
  398.      "",                 /* dmode_str */
  399.      "",                 /* dmode_prompt */
  400.      "ATTD%s\r",         /* dial_str */
  401.      0                   /* dial_rate */
  402. };
  403.  
  404.  
  405. static
  406. MDMINF VENTEL =         /* information for "Ventel" modem */
  407. {
  408.      20,                 /* dial_time */
  409.      "%",                /* pause_chars */
  410.      5,                  /* pause_time */
  411.      "\r\r\r",           /* wake_str */
  412.      300,                /* wake_rate */
  413.      "$",                /* wake_prompt */
  414.      "",                 /* dmode_str */
  415.      "",                 /* dmode_prompt */
  416.      "<K%s\r>",          /* dial_str */
  417.      0                   /* dial_rate */
  418. };
  419.  
  420.  
  421. static
  422. MDMINF CONCORD =        /* Info for Condor CDS 220 2400b modem */
  423. {
  424.      35,                 /* dial_time */
  425.      ",",                /* pause_chars */
  426.      2,                  /* pause_time */
  427.      "\r\r",             /* wake_str */
  428.      20,                 /* wake_rate */
  429.      "CDS >",            /* wake_prompt */
  430.      "",                 /* dmode_str */
  431.      "",                 /* dmode_prompt */
  432.      "<D M%s\r>",        /* dial_str */
  433.      0                   /* dial_rate */
  434. };
  435.  
  436.  
  437. static
  438. MDMINF ATTUPC = /* dummy information for "ATT7300/NCR-VRX PC" internal modem */
  439. {
  440.      20,                 /* dial_time */
  441.      "",                 /* pause_chars */
  442.      0,                  /* pause_time */
  443.      "",                 /* wake_str */
  444.      0,                  /* wake_rate */
  445.      "",                 /* wake_prompt */
  446.      "",                 /* dmode_str */
  447.      "",                 /* dmode_prompt */
  448.      "%s\r",             /* dial_str */
  449.      0                   /* dial_rate */
  450. };
  451.  
  452.  
  453. static
  454. MDMINF ROLM =           /* IBM (Siemens) / Rolm CBX */
  455. {
  456.      60,                 /* dial_time */
  457.      "",                 /* pause_chars */
  458.      0,                  /* pause_time */
  459.      "\r\r",             /* wake_str */
  460.      5,                  /* wake_rate */
  461.      "MODIFY?",          /* wake_prompt */
  462.      "",                 /* dmode_str */
  463.      "",                 /* dmode_prompt */
  464.      "CALL %s\r",        /* dial_str */
  465.      0                   /* dial_rate */
  466. };
  467.  
  468.  
  469. /*
  470.  * Declare table for converting modem numbers to information pointers.
  471.  *
  472.  * The entries MUST be in ascending order by modem number, without any
  473.  * "gaps" in the numbers, and starting from one (1).
  474.  *
  475.  * This table should NOT include entries for the "variant" modem numbers,
  476.  * since it is assumed that they share the same information as the normal
  477.  * value.
  478.  */
  479. static
  480. MDMINF *ptrtab[] =
  481. {
  482.      &CERMETEK, &DF03, &DF100, &DF200, &GDC, &HAYES, &PENRIL, &RACAL,
  483.      &UNKNOWN, &USROBOT, &VENTEL, &CONCORD,
  484.      &ATTUPC, /* ATT7300 internal modem, jrd*/
  485.      &ROLM    /* Rolm CBX, fdc */
  486. };
  487.  
  488.  
  489. /*
  490.  * Declare modem names and associated numbers for command parsing,
  491.  * and also for doing number-to-name translation.
  492.  *
  493.  * The entries MUST be in alphabetical order by modem name.
  494.  */
  495. struct keytab mdmtab[] =
  496. {
  497.      "att7300",          n_ATTUPC,       0,
  498.      "cermetek",         n_CERMETEK,     0,
  499.      "concord",          n_CONCORD,      0,
  500.      "df03-ac",          n_DF03,         0,
  501.      "df100-series",     n_DF100,        0,
  502.      "df200-series",     n_DF200,        0,
  503.      "direct",           0,              0,
  504.      "gendatacomm",      n_GDC,          0,
  505.      "hayes",            n_HAYES,        0,
  506.      "penril",           n_PENRIL,       0,
  507.      "racalvadic",       n_RACAL,        0,
  508.      "rolm",             n_ROLM,         0,
  509.      "unknown",          n_UNKNOWN,      0,
  510.      "usrobotics-212a",  n_USROBOT,      0,
  511.      "ventel",           n_VENTEL,       0
  512. };
  513.  
  514.  
  515. int     nmdm = (sizeof(mdmtab)
  516.  / sizeof(struct keytab )
  517. );    /* number of modems */
  518.  
  519. #define DIALING 4               /* for ttpkt parameter */
  520. #define CONNECT 5
  521.  
  522. #define CONNECTED 1             /* for completion status */
  523. #define FAILED    2
  524.  
  525. /*
  526.  * Failure reasons for use with the 'longjmp' exit.
  527.  */
  528. #define F_time          1       /* timeout */
  529. #define F_int           2       /* interrupt */
  530. #define F_modem         3       /* modem-detected failure */
  531. #define F_minit         4       /* cannot initialize modem */
  532.  
  533. static
  534. char     *F_reason[5] = {           /* failure reasons for message */
  535.      "Unknown",  "Timeout", "Interrupt", "Modem", "Initialize" };
  536.  
  537.  
  538. static int     tries = 0;
  539.  
  540. #define LBUFL 100
  541. static char     lbuf[LBUFL];
  542.  
  543. static jmp_buf sjbuf;
  544.  
  545. static SIGTYP (*savAlrm)();     /* for saving alarm handler */
  546. static SIGTYP (*savInt)();      /* for saving interrupt handler */
  547.  
  548. dialtime()
  549. {                    /* timer interrupt handler */
  550.      longjmp( sjbuf, F_time );
  551. }
  552.  
  553.  
  554. dialint()                       /* user-interrupt handler */
  555. {
  556.      longjmp( sjbuf, F_int );
  557. }
  558.  
  559.  
  560. static
  561. ttolSlow(s, millisec)
  562. char     *s;
  563. int     millisec;
  564. {  /* output s-l-o-w-l-y */
  565.      for (; *s; s++) {
  566.           ttoc(*s);
  567.           msleep(millisec);
  568.      }
  569. }
  570.  
  571.  
  572. /*
  573.  * Wait for a string of characters.
  574.  *
  575.  * The characters are waited for individually, and other characters may
  576.  * be received "in between".  This merely guarantees that the characters
  577.  * ARE received, and in the order specified.
  578.  */
  579. static
  580. waitFor(s)
  581. char     *s;
  582. {
  583.      CHAR c;
  584.      while ( c = *s++)                  /* while more characters remain... */
  585.           while ( ( ttinc(0) & 0177 ) != c )
  586.                ;    /* wait for the character */
  587. }
  588.  
  589.  
  590. static
  591. didWeGet(s, r)
  592. char     *s, *r;
  593. {    /* Looks in string s for response r */
  594.      int     lr = strlen(r);         /*  0 means not found, 1 means found it */
  595.      int     i;
  596.      if (deblog)
  597.           debug(F110, "didWeGet", r, 0);
  598.      if (deblog)
  599.           debug(F110, " in", s, 0);
  600.      for (i = strlen(s) - lr; i >= 0; i--)
  601.           if ( s[i] == r[0] )
  602.                if ( !strncmp(s + i, r, lr) )
  603.                     return( 1 );
  604.      return( 0 );
  605. }
  606.  
  607.  
  608. /* R E S E T -- Reset alarms, etc. on exit. */
  609.  
  610. static
  611. reset ()
  612. {
  613.      ALARM(0);
  614.      SIGNAL(SIGALRM, savAlrm);            /* restore alarm handler */
  615.      SIGNAL(SIGINT, savInt);              /* restore interrupt handler */
  616. }
  617.  
  618.  
  619. /*  C K D I A L  --  Dial up the remote system */
  620.  
  621. ckdial(telnbr)
  622. char     *telnbr;
  623. {
  624.  
  625.      char     c;
  626.      char     *i, *j;
  627.      int     waitct, status;
  628.      char     errmsg[50], *erp;
  629.      MDMINF * pmdminf;    /* pointer to modem-specific info */
  630.      int     augmdmtyp;   /* "augmented" modem type, to handle modem modes */
  631.      int     mdmEcho = 0; /* assume modem does not echo */
  632.      int     n, n1;
  633.      char     *pc;           /* pointer to a character */
  634.  
  635.      if (!mdmtyp) {
  636. #ifndef MCS_FLAG
  637.           printf("Sorry, you must 'set modem' first\n");
  638. #else
  639.           mcs_printf("Sorry, you must 'set modem' first\n");
  640. #endif
  641.           return(-2);
  642.      }
  643.      if (!local) {
  644. #ifndef MCS_FLAG
  645.           printf("Sorry, you must 'set line' first\n");
  646. #else
  647.           mcs_printf("Sorry, you must 'set line' first\n");
  648. #endif
  649.           return(-2);
  650.      }
  651.      if (speed < 0) {
  652. #ifndef MCS_FLAG
  653.           printf("Sorry, you must 'set speed' first\n");
  654. #else
  655.           mcs_printf("Sorry, you must 'set speed' first\n");
  656. #endif
  657.           return(-2);
  658.      }
  659.      if (deblog)
  660.           debug(F110, "dial", telnbr, 0);
  661.  
  662.      /* Carrier no-wait can be invalidated by ckutio fun and games, jrd */
  663.      if (ttopen(ttname, &local, mdmtyp) < 0) { /* Open, no carrier wait */
  664.           erp = errmsg;
  665.           sprintf(erp, "ckdail: Can't open %s", ttname);
  666.           perror(errmsg);
  667.           return(-2);
  668.      }
  669.      pmdminf = ptrtab[mdmtyp-1];     /* set pointer to modem info */
  670.      augmdmtyp = mdmtyp;             /* initialize "augmented" modem type */
  671.  
  672.      /* cont'd... */
  673.  
  674.      /* interdigit waits for tone dial */
  675.      /* ...dial, cont'd */
  676.  
  677.  
  678.      waitct = 1 * strlen(telnbr) ;     /* compute time to dial worst case */
  679.      waitct += pmdminf->dial_time;   /* dialtone + completion wait times */
  680.      for (i = telnbr; *i; i++)         /* add in pause characters time */
  681.           for (j = pmdminf->pause_chars; *j; j++)
  682.                if (*i == *j) {
  683.                     waitct += pmdminf->pause_time;
  684.                     break;
  685.                }
  686.  
  687. #ifndef MCS_FLAG
  688.      printf("Dialing thru %s, speed %d, number %s.\r\n", ttname,
  689.          speed, telnbr);
  690.      printf("The timeout for completing the call is %d seconds.\r\n",
  691.           waitct);
  692.      printf("Type the interrupt character (^C) to cancel the dialing.\r\n");
  693. #else
  694.      sprintf(print_str,"Dialing thru %s, speed %d, number %s.\r\n", ttname,
  695.          speed, telnbr);
  696.      mcs_printf(print_str);
  697.      mcs_printf("The timeout for completing the call is %d seconds.\r\n",
  698.           waitct);
  699.      mcs_printf(
  700.         "Type the interrupt character (^C) to cancel the dialing.\r\n");
  701. #endif
  702.      if (deblog)
  703.           debug(F101, ttname, "", speed);
  704.      if (deblog)
  705.           debug(F101, "timeout", "", waitct);
  706.  
  707.      /* Hang up the modem (in case it wasn't "on hook") */
  708.  
  709.      if ( tthang() < 0 ) {
  710. #ifndef MCS_FLAG
  711.           printf("Sorry, Can't hang up tty line\n");
  712. #else
  713.           mcs_printf("Sorry, Can't hang up tty line\n");
  714. #endif
  715.           return(-2);
  716.      }
  717.  
  718.      /* Condition console terminal and communication line */
  719.      /* place line into "clocal" dialing state */
  720.      if ( ttpkt(speed, DIALING, parity) < 0 )  {
  721. #ifndef MCS_FLAG
  722.           printf("Sorry, Can't condition communication line\n");
  723. #else
  724.           mcs_printf("Sorry, Can't condition communication line\n");
  725. #endif
  726.           return(-2);
  727.      }
  728.  
  729.      /*
  730.  * Establish jump vector, or handle "failure" jumps.
  731.  */
  732.  
  733.      if ( n = setjmp(sjbuf) )         /* if a "failure jump" was taken... */ {
  734.           ALARM ( 0 );                /* disable timeouts */
  735.  
  736.           if ( n1 = setjmp(sjbuf) )   /* failure while handling failure */ {
  737. #ifndef MCS_FLAG
  738.                printf ( "%s failure while handling failure.\r\n",
  739.                     F_reason[n1] );
  740. #else
  741.                mcs_printf ( "%s failure while handling failure.\r\n",
  742.                     F_reason[n1] );
  743. #endif
  744.           } else /* first (i.e., non-nested) failure */            {
  745.                SIGNAL ( SIGALRM, dialtime );   /* be sure to catch signals */
  746.                if ( SIGNAL ( SIGINT, SIG_IGN ) != SIG_IGN )
  747.                     SIGNAL ( SIGINT, dialint );
  748.                ALARM ( 10 );               /* be sure to exit this section */
  749.                ttclos ();                  /* hangup and close the line */
  750.           }
  751.           switch ( n )                /* type of failure */ {
  752.           case F_time:                /* timed out */
  753.                 {
  754. #ifndef MCS_FLAG
  755.                     printf("No connection made in the allotted time.\r\n");
  756. #else
  757.                     mcs_printf("No connection made in the allotted time.\r\n");
  758. #endif
  759.                     if (deblog)
  760.                          debug(F110, "dial", "timeout",
  761.                               0);
  762.                     break;
  763.                }
  764.           case F_int:                 /* dialing interrupted */
  765.                 {
  766. #ifndef MCS_FLAG
  767.                     printf ( "Dialing interrupted.\r\n" );
  768. #else
  769.                     mcs_printf ( "Dialing interrupted.\r\n" );
  770. #endif
  771.                     if (deblog)
  772.                          debug(F110, "dial", "interrupted",
  773.                               0);
  774.                     break;
  775.                }
  776.           case F_modem:               /* modem detected a failure */
  777.                 {
  778. #ifndef MCS_FLAG
  779.                     printf ( "Failed (\"" );
  780. #else
  781.                     mcs_printf ( "Failed (\"" );
  782. #endif
  783.                     for ( pc = lbuf; *pc; pc++)
  784.                          if ( isprint(*pc) )
  785.                               putchar(*pc);   /* display printable reason */
  786. #ifndef MCS_FLAG
  787.                     printf ( "\").\r\n" );
  788. #else
  789.                     mcs_printf ( "\").\r\n" );
  790. #endif
  791.                     if (deblog)
  792.                          debug(F110, "dial", lbuf, 0);
  793.                     break;
  794.                }
  795.           case F_minit:               /* cannot initialize modem */
  796.                 {
  797. #ifndef MCS_FLAG
  798.                     printf ( "Cannot initialize modem.\r\n" );
  799. #else
  800.                     mcs_printf ( "Cannot initialize modem.\r\n" );
  801. #endif
  802.                     if (deblog)
  803.                          debug(F110, "dial", "modem init",
  804.                               0);
  805.                     break;
  806.                }
  807.           }
  808.           reset();                        /* reset alarms, etc. */
  809.           return ( -2 );                  /* exit with failure code */
  810.      }
  811.  
  812.      /*
  813.  * Set timer and interrupt handlers.
  814.  */
  815.      ttflui();                   /* flush input buffer if any */
  816.  
  817.      savAlrm = SIGNAL(SIGALRM, dialtime); /* set alarm handler */
  818.      if ( ( savInt = SIGNAL ( SIGINT, SIG_IGN ) ) != SIG_IGN )
  819.           SIGNAL ( SIGINT, dialint );     /* set int handler if not ignored */
  820.      ALARM(10);                  /* give modem 10 seconds to wake up */
  821.  
  822.      /*
  823.  * Put modem in command mode.
  824.  */
  825.  
  826. #define OKAY 1                  /* modem attention attempt status */
  827. #define IGNORE 2
  828. #define GOT_O -2
  829. #define GOT_A -3
  830.  
  831.      switch (augmdmtyp) {
  832.  
  833.      case n_HAYES:
  834.      case n_HAYESNV:
  835.           while (tries++ < 4) {
  836.                ttol( HAYES.wake_str, strlen(HAYES.wake_str) );     /* wakeup */
  837.                status = 0;
  838.                while ( status <= 0 ) {
  839.                     switch (ttinc(0) & 0177) {
  840.                     case 'A':                   /* echoing, ignore */
  841.                          status = GOT_A;
  842.                          break;
  843.                     case 'T':
  844.                          if (status == GOT_A) {
  845.                               mdmEcho = 1;        /* expect echoing later */
  846.                               status = 0;
  847.                               break;
  848.                          }
  849.                          status = IGNORE;
  850.                          break;
  851.                     case '\n':
  852.                     case '\r':
  853.                          status = 0;
  854.                          break;
  855.                     case '0':                   /* numeric result code */
  856.                          augmdmtyp = n_HAYESNV;  /* nonverbal result codes */
  857.                          status = OKAY;
  858.                          break;
  859.                     case 'O':                   /* maybe English result code*/
  860.                          status = GOT_O;
  861.                          break;
  862.                     case 'K':
  863.                          if (status == GOT_O) {
  864.                               augmdmtyp = n_HAYES;
  865.                               status = OKAY;
  866.                               break;
  867.                          }                       /* else its default anyway */
  868.                     default:
  869.                          status = IGNORE;
  870.                          break;
  871.                     }
  872.                }
  873.                if (status == OKAY)
  874.                     break;
  875.                if (status == IGNORE)
  876.                     ttflui();
  877.                sleep(1);           /* wait before retrying */
  878.           }
  879.           if (status != 0)
  880.                break;
  881.           longjmp( sjbuf, F_minit );      /* modem-initialization failure */
  882.  
  883.           /* cont'd... */
  884.  
  885.           /* interdigit waits for tone dial */
  886.           /* ...dial, cont'd */
  887.  
  888.      default:                    /* place modem into command mode */
  889.           ttolSlow(pmdminf->wake_str, pmdminf->wake_rate);
  890.           waitFor(pmdminf->wake_prompt);
  891.           break;
  892.      }
  893.      ALARM(0);                   /* turn off alarm */
  894.      msleep(500);                /* give things settling time */
  895.      ALARM(10);                  /* alarm on dialing prompts */
  896.  
  897.  
  898.      /* Dial the number */
  899.      /* put modem into dialing mode */
  900.      ttolSlow(pmdminf->dmode_str, pmdminf->dial_rate);
  901.      if (pmdminf->dmode_prompt) {        /* wait for prompt, if any expected */
  902.           waitFor(pmdminf->dmode_prompt);
  903.           msleep(300);
  904.      }
  905.  
  906.      ALARM(0);                   /* turn off alarm on dialing prompts */
  907.      ALARM(waitct);              /* time to allow for connecting */
  908.      ttflui();                   /* clear out stuff from waking modem up */
  909.      sprintf(lbuf, pmdminf->dial_str, telnbr); /* form dialing string */
  910.      if (deblog)
  911.           debug(F110, "dialing", lbuf);
  912.      ttolSlow(lbuf, pmdminf->dial_rate);  /* send dialing string */
  913.  
  914.      if (augmdmtyp == n_RACAL) { /* acknowledge printout of dialing string */
  915.           sleep(3);
  916.           ttflui();
  917.           ttoc('\r');
  918.      }
  919.  
  920.      /* cont'd... */
  921.  
  922.      /* interdigit waits for tone dial */
  923.      /* ...dial, cont'd */
  924.  
  925.  
  926.      /* Check for connection */
  927.  
  928.      /*
  929.  * I believe we also need to look for carrier in order to determine if a
  930.  * connection has been made.  In fact, for many we may only want to look for
  931.  * the "failure" responses in order to short-circuit the timeout, and let
  932.  * carrier be the determination of whether a connection has been made. -- DS
  933.  */
  934.  
  935.      status = 0;
  936.      strcpy(lbuf, "No Connection");       /* default failure reason */
  937.      while (status == 0) {
  938.           switch (augmdmtyp) {
  939.           default:
  940.                for (n = 0; n < LBUFL; n++) { /* accumulate response */
  941.                     lbuf[n] = (ttinc(0) & 0177);
  942.                     if ( lbuf[n] == '\r' || lbuf[n] == '\n' )
  943.                          break;
  944.                }
  945.                lbuf[n] = '\0';             /* terminate response from modem */
  946.                if (deblog)
  947.                     debug(F110, "dial modem response", lbuf,
  948.                          0);
  949.                if (n) {          /* if one or more characters present */
  950.                     switch (augmdmtyp) {
  951.                     case n_CERMETEK:
  952.                          if (didWeGet(lbuf, "\016A")) {
  953.                               status = CONNECTED;
  954.                               ttolSlow("\016U 1\r",
  955.                                    200);      /* make transparent*/
  956.                          }
  957.                          break;
  958.                     case n_DF100:      /* DF100 won't generate some of these */
  959.                     case n_DF200:
  960.                          if (didWeGet(lbuf, "Attached"))
  961.                               status = CONNECTED;
  962.                          /*
  963.                      * The DF100 will respond with "Attached" even if DTR
  964.                      * and/or carrier are not present.  Another reason to
  965.                      * (also) wait for carrier?
  966.                      */
  967.                          if (didWeGet(lbuf, "Busy"))
  968.                               status = FAILED;
  969.                          if (didWeGet(lbuf, "Disconnected"))
  970.                               status = FAILED;
  971.                          if (didWeGet(lbuf, "Error"))
  972.                               status = FAILED;
  973.                          if (didWeGet(lbuf, "No answer"))
  974.                               status = FAILED;
  975.                          if (didWeGet(lbuf, "No dial tone"))
  976.                               status = FAILED;
  977.                          if (didWeGet(lbuf, "Speed:"))
  978.                               status = FAILED;
  979.                          /*
  980.                      * It appears that the "Speed:..." response comes after an
  981.                      * "Attached" response, so this is never seen.  HOWEVER,
  982.                      * it would be very handy to detect this and temporarily
  983.                      * reset the speed, since it's a nuiscance otherwise.
  984.                      * If we wait for some more input from the modem, how do
  985.                      * we know if it's from the remote host or the modem?
  986.                      * Carrier reportedly doesn't get set until after the
  987.                      * "Speed:..." response (if any) is sent.  Another reason
  988.                      * to (also) wait for carrier.
  989.                      */
  990.                          break;
  991.                     case n_GDC:
  992.                          if (didWeGet(lbuf, "ON LINE"))
  993.                               status = CONNECTED;
  994.                          if (didWeGet(lbuf, "NO CONNECT"))
  995.                               status = FAILED;
  996.                          break;
  997.                     case n_HAYES:
  998.                     case n_USROBOT:
  999.                          if (didWeGet(lbuf, "CONNECT"))
  1000.                               status = CONNECTED;
  1001.                          if (didWeGet(lbuf, "NO CARRIER"))
  1002.                               status = FAILED;
  1003.                          break;
  1004.                     case n_PENRIL:
  1005.                          if (didWeGet(lbuf, "OK"))
  1006.                               status = CONNECTED;
  1007.                          if (didWeGet(lbuf, "BUSY"))
  1008.                               status = FAILED;
  1009.                          if (didWeGet(lbuf, "NO RING"))
  1010.                               status = FAILED;
  1011.                          break;
  1012.                     case n_RACAL:
  1013.                          if (didWeGet(lbuf, "ON LINE"))
  1014.                               status = CONNECTED;
  1015.                          if (didWeGet(lbuf, "FAILED CALL"))
  1016.                               status = FAILED;
  1017.                          break;
  1018.                     case n_ROLM:
  1019.                          if (didWeGet(lbuf, "CALLING"))
  1020.                               status = 0;
  1021.                          if (didWeGet(lbuf, "COMPLETE"))
  1022.                               status = CONNECTED;
  1023.                          if (didWeGet(lbuf, "FAILED"))
  1024.                               status = FAILED;
  1025.                          if (didWeGet(lbuf, "NOT AVAILABLE"))
  1026.                               status = FAILED;
  1027.                          if (didWeGet(lbuf, "LACKS PERMISSION"))
  1028.                               status = FAILED;
  1029.                          /*
  1030.                       The Rolm CBX does not give a CALL COMPLETE indication
  1031.                       when dialing an outpool number, but it does seem to
  1032.                       return a long string of DELs at that point.
  1033.                     */
  1034.                          if (didWeGet(lbuf, "\177\177\177"))
  1035.                               status = CONNECTED;
  1036.                          break;
  1037.                     case n_VENTEL:
  1038.                          if (didWeGet(lbuf, "ONLINE!"))
  1039.                               status = CONNECTED;
  1040.                          if (didWeGet(lbuf, "BUSY"))
  1041.                               status = FAILED;
  1042.                          if (didWeGet(lbuf, "DEAD PHONE"))
  1043.                               status = FAILED;
  1044.                          break;
  1045.                     case n_CONCORD:
  1046.                          if (didWeGet(lbuf, "INITIATING"))
  1047.                               status = CONNECTED;
  1048.                          if (didWeGet(lbuf, "BUSY"))
  1049.                               status = FAILED;
  1050.                          if (didWeGet(lbuf, "CALL FAILED"))
  1051.                               status = FAILED;
  1052.                          break;
  1053.                     }
  1054.                }
  1055.                break;
  1056.  
  1057.           case n_DF03:                    /* because response lacks CR or NL */
  1058.                c = ttinc(0) & 0177;
  1059.                if ( c == 'A' )
  1060.                     status = CONNECTED;
  1061.                if ( c == 'B' )
  1062.                     status = FAILED;
  1063.                break;
  1064.  
  1065.           case n_HAYESNV:
  1066.                c = ttinc(0) & 0177;
  1067.                if (mdmEcho) {              /* sponge up dialing string */
  1068.                     mdmEcho = c != '\r';      /* until return is echoed */
  1069.                     break;
  1070.                }
  1071.                if (c == '1')
  1072.                     status = CONNECTED;
  1073.                if (c == '3')
  1074.                     status = FAILED;
  1075.                if (c == '5')
  1076.                     status = CONNECTED;
  1077.                break;
  1078.  
  1079.           case n_UNKNOWN:
  1080.                /** SHOULD WAIT FOR CARRIER OR TIMEOUT -- DS **/
  1081.                break;
  1082.           }                               /* switch (augmdmtyp) */
  1083.      }                                   /* while status == 0 */
  1084.      ALARM(0);                           /* turn off alarm on connecting */
  1085.      if ( status != CONNECTED )          /* modem-detected failure */
  1086.           longjmp( sjbuf, F_modem );      /* exit (with reason in lbuf) */
  1087.      msleep(500);                        /* allow some time...  */
  1088.      ALARM(3);                           /* precaution in case of trouble */
  1089.      if (deblog)
  1090.           debug(F110, "dial", "succeeded", 0);
  1091.      if (augmdmtyp != n_ROLM)            /* Rolm has wierd modem signaling */
  1092.           ttpkt(speed, CONNECT, parity);      /* cancel dialing state ioctl */
  1093.      reset ();                           /* reset alarms, etc. */
  1094.      if ( !quiet )
  1095. #ifndef MCS_FLAG
  1096.           printf ( "Call completed.\07\r\n" );
  1097. #else
  1098.           mcs_printf ( "Call completed.\07\r\n" );
  1099. #endif
  1100.      return ( 0 );                       /* return, and presumably connect */
  1101. }
  1102.