home *** CD-ROM | disk | FTP | other *** search
/ Fish 'n' More 2 / fishmore-publicdomainlibraryvol.ii1991xetec.iso / fish / telecom / uucp_442 / src / getty / getty.c < prev    next >
C/C++ Source or Header  |  1991-01-06  |  22KB  |  1,081 lines

  1.  
  2. /*
  3.  *  GETTY.C
  4.  *
  5.  *  $Header: Beta:src/uucp/src/getty/RCS/getty.c,v 1.1 90/02/02 12:13:30 dillon Exp Locker: dillon $
  6.  *
  7.  *  (C)Copyright 1989, Matthew Dillon, All Rights Reserved
  8.  *
  9.  *  Uses:
  10.  *    GETTY:PASSWD
  11.  *    GETTY:LOGFILE
  12.  *    GETTY:Getty-Header
  13.  *
  14.  *  GETTY   <options>    <modem-commands>
  15.  *
  16.  *    -Sdevicenam Tells GETTY which serial.device to use, default
  17.  *            serial.device
  18.  *
  19.  *    -Uunitnum   Tells GETTY which unit number to use, default 0
  20.  *
  21.  *    -A        Always talk to the modem at the first baud
  22.  *            rate in the -B list and ignore the baud rate
  23.  *            in the CONNECT message.
  24.  *
  25.  *    -7        use SERF_7WIRE while online.
  26.  *
  27.  *    -Bn        Set baud rate.  If specified multiple times the
  28.  *            first one is the default and remaining ones
  29.  *            switched to when a BREAK is received after a
  30.  *            connect.  Also determines how CONNECT messages
  31.  *            are interpreted.  A CONNECT with no number uses
  32.  *            the first -B entry while CONNECTs with numbers
  33.  *            use those numbers regardless of any -B entries.
  34.  *
  35.  *    -Mc        Set modem type:
  36.  *            c = m    = multimodem
  37.  *                h    = hays
  38.  *                d    = dumb (no AT or +++ cmds are ever sent),
  39.  *                  normally used with only one specified
  40.  *                  baud rate.
  41.  *
  42.  *    -m1        Turn on the modem speaker during dialing/connect
  43.  *            (default is -m0)
  44.  *
  45.  *    -h0        Ignore CD (carrier detect), default is to use
  46.  *            carrier detect.
  47.  *
  48.  *    -c0        Ignore CONNECT message (i.e. you are not connected
  49.  *            to a modem, usually combined with -h0).  Default is
  50.  *            to expect a CONNECT message.
  51.  *
  52.  *    -d0        do not use DTR to drop connection.    Default is
  53.  *            to drop DTR to drop a connection.  If this option
  54.  *            is chosen the +++ and ATH0 sequence will be used
  55.  *            to drop a connection.
  56.  *
  57.  *    -xn        Set debug level.  Also causes log output to go
  58.  *            to stdout instead of GETTY:LOGFILE
  59.  *
  60.  *    -0        QUIT - Kills any running getty for the specified
  61.  *            port.
  62.  *
  63.  *    Any fields specified without a '-' are considered modem commands
  64.  *    used to initialize/reinitialize the modem.  Up to 16 fields may
  65.  *    be specified (each is sent to the modem in 1 second intervals)
  66.  */
  67.  
  68. #include <exec/types.h>
  69. #include <exec/lists.h>
  70. #include <exec/devices.h>
  71. #include <exec/io.h>
  72. #include <devices/timer.h>
  73. #include <devices/serial.h>
  74. #include <libraries/dos.h>
  75. #include <libraries/dosextens.h>
  76. #include <hardware/cia.h>
  77. #include <stdio.h>
  78. #include <stdlib.h>
  79. #include "protos.h"
  80. #include <pwd.h>
  81. #include "version.h"
  82.  
  83. #include "log.h"
  84.  
  85. IDENT(".04");
  86.  
  87. #ifndef IO_STATF_READBREAK
  88. #define IO_STATF_READBREAK (IOSTF_READBREAK<<8)
  89. #endif
  90.  
  91. #define arysize(ary)    (sizeof(ary)/sizeof((ary)[0]))
  92.  
  93. #define ST_WAITCD    0
  94. #define ST_CONNECT    1
  95. #define ST_LOGIN    2
  96. #define ST_PASSWD    3
  97. #define ST_RUN        4
  98.  
  99. typedef struct IORequest    IOR;
  100. typedef struct timerequest  IOT;
  101. typedef struct IOExtSer     IOSER;
  102. typedef struct MsgPort        PORT;
  103. typedef struct List        LIST;
  104. typedef struct Node        NODE;
  105. typedef struct Message        MSG;
  106. typedef void (*FPTR)();
  107.  
  108. typedef struct GMsg {
  109.     struct Message  Msg;
  110.     short   Cmd;
  111.     long    Data1;
  112.     void    *Data2;
  113. } GMsg;
  114.  
  115. extern struct ProcID *RunPasswdEntry();
  116.  
  117. char    *CopyRight = "(c)Copyright 1989, Matthew Dillon, All Rights Reserved\r\n";
  118. char    *ComPortName;
  119.  
  120. char    *DeviceName = "serial.device";
  121. long    DeviceUnit  = 0;
  122. long    RefCnt        = 0;    /*  take into account ourselves    */
  123. long    NullFH;
  124. char    SpeakerLevel    = 0;
  125. char    AnswerRing    = 2;    /*  default, answer on second ring */
  126. char    SpeakerOpt    = 0;
  127. char    IgnoreCD    = 0;
  128. char    IgnoreConnect    = 0;
  129. char    IgnoreDTR    = 0;
  130. char    BaudAdjust    = 0;
  131. char    DropOnExit    = 1;
  132. char    ModemType    = 'h';
  133. char    ZeroOption    = 0;
  134. /*char      NoBugs      = 0;*/
  135. char    Wire7        = 0;        /*  use 7 wire while online */
  136. long    Bauds[16] = { 9600 };        /*  up 16 baud rates        */
  137. char    *AtFields[16];
  138.  
  139. APTR    UnitPtr;
  140.  
  141. PORT    *ComPort;
  142. PORT    *IoSink;    /*  Sink for IO reqs.    */
  143. long    IoSinkMask;
  144. long    ComPortMask;
  145.  
  146. IOT    Iot;        /*  check-carrier    */
  147. IOSER    Ios;        /*  parameters req    */
  148. IOSER    Iosr;        /*  serial read-req    */
  149. IOSER    Ioss;        /*  synchronous req    */
  150.  
  151. char    IotIP;        /*  Iot0 in progress    */
  152. char    IosrIP;
  153.  
  154. char    ScrBuf[256];
  155. char    ConnectBuf[64];
  156. char    LoginBuf[32];
  157. char    PasswdBuf[32];
  158. char    RxBuf[32];
  159. char    HaveConnectMsg;
  160. char    HaveLogin;
  161. char    HavePasswd;
  162.  
  163. short    State;
  164. short    Index;
  165. short    BIndex;
  166.  
  167. short CountDown;
  168. short GotOffPort;
  169.  
  170. long    GetStatus();
  171. void    SerPuts();
  172. void    RxStop();
  173. void    RxStart();
  174. void    xexit();
  175. void    Disconnect();
  176. void    ClearRecv();
  177. void    InitModem();
  178. void    SetParams();
  179. void    DoOptions();
  180. void    InterceptDeviceVector();
  181. void    RestoreDeviceVector();
  182.  
  183. brk()
  184. {
  185.     return(0);
  186. }
  187.  
  188. main(ac, av)
  189. char *av[];
  190. {
  191.     extern int IAmGetty;
  192.     char termCr = 1;
  193.     char termLf = 1;
  194.  
  195.     IAmGetty = 1;    /*  for LockSerialPort()/UnLockSerialPort()   */
  196.  
  197.     puts(CopyRight);
  198.     fflush(stdout);
  199.     onbreak(brk);
  200.  
  201.     LogProgram = "Getty";
  202.     LogWho = LoginBuf;
  203.     LogFile = "Getty:LOGFILE";
  204.     PasswdFile = "Getty:Passwd";
  205.  
  206.     DoOptions(ac, av);
  207.  
  208.     IoSink = CreatePort(NULL, 0);
  209.     IoSinkMask = 1 << IoSink->mp_SigBit;
  210.  
  211.     ComPortName = malloc(strlen(DeviceName) + 20);
  212.     sprintf(ComPortName, "Getty.%s.%ld", DeviceName, DeviceUnit);
  213.  
  214.     Forbid();
  215.     if (ComPort = FindPort(ComPortName)) {
  216.     GMsg msg;
  217.     msg.Cmd = 'O';
  218.     msg.Data1 = ac;
  219.     msg.Data2 = (void *)av;
  220.     msg.Msg.mn_ReplyPort = IoSink;
  221.     PutMsg(ComPort, &msg.Msg);
  222.     WaitPort(IoSink);
  223.     Remove(&msg.Msg.mn_Node);
  224.     Permit();
  225.     puts("Options updated");
  226.     xexit(0);
  227.     }
  228.     ComPort = CreatePort(ComPortName, 0L);
  229.     Permit();
  230.  
  231.     ComPortMask = 1L << ComPort->mp_SigBit;
  232.  
  233.     NullFH = Open("NULL:", 1006);
  234.     if (NullFH == NULL) {
  235.     ulog(-1, "GETTY REQUIRES NULL: HANDLER!");
  236.     puts("Requires NULL: handler!");
  237.     xexit(1);
  238.     }
  239.     if (LogToStdout == 0) {
  240.     freopen("NULL:", "r", stdin);
  241.     freopen("NULL:", "w", stdout);
  242.     freopen("NULL:", "w", stderr);
  243.     }
  244.  
  245.     /*
  246.      *    Timer Device
  247.      */
  248.  
  249.     Iot.tr_node.io_Message.mn_ReplyPort = IoSink;
  250.     if (OpenDevice("timer.device", UNIT_VBLANK, &Iot, 0L)) {
  251.     Iot.tr_node.io_Device = NULL;
  252.     xexit(20);
  253.     }
  254.     Iot.tr_node.io_Command = TR_ADDREQUEST;
  255.  
  256.     /*
  257.      *    SERIAL.DEVICE
  258.      */
  259.  
  260.     Ios.IOSer.io_Message.mn_ReplyPort = IoSink;
  261.     Ios.io_SerFlags = SERF_XDISABLED | SERF_SHARED;
  262.     if (Wire7)
  263.     Ios.io_SerFlags |= SERF_7WIRE;
  264.     if (OpenDevice(DeviceName, DeviceUnit, &Ios, 0L)) {
  265.     Ios.IOSer.io_Device = NULL;
  266.     xexit(21);
  267.     }
  268.  
  269.     InterceptDeviceVector(Ios.IOSer.io_Device);
  270.  
  271.     Iosr = Ios;
  272.     Ioss = Ios;
  273.  
  274.     Iosr.IOSer.io_Command = CMD_READ;
  275.     Ios.IOSer.io_Command = SDCMD_QUERY;
  276.     DoIO(&Ios);
  277.  
  278.     Ios.io_SerFlags = SERF_XDISABLED | SERF_RAD_BOOGIE | SERF_SHARED;
  279.     Ios.io_ExtFlags = 0;
  280.     Ios.io_Baud = Bauds[0];
  281.     Ios.io_ReadLen = 8;
  282.     Ios.io_WriteLen = 8;
  283.     Ios.io_StopBits = 1;
  284.  
  285.     SetParams(0);
  286.  
  287.     /*
  288.      *    Run Operation
  289.      */
  290.  
  291.     State = ST_WAITCD;
  292.     Iot.tr_time.tv_secs = 1;
  293.     Iot.tr_time.tv_micro= 0;
  294.     IotIP = 1;
  295.     SendIO(&Iot);
  296.  
  297.     InitModem();
  298.  
  299.     Signal(FindTask(NULL), IoSinkMask);
  300.  
  301.     for (;;) {
  302.     long mask;
  303.     IOR  *ior;
  304.     GMsg *msg;
  305.     mask = Wait(SIGBREAKF_CTRL_C | IoSinkMask | ComPortMask);
  306.  
  307.     ulog(9, "State = %d %d %08lx %08lx", State, RefCnt, UnitPtr, Ios.IOSer.io_Unit);
  308.  
  309.     if (mask & SIGBREAKF_CTRL_C)
  310.         break;
  311.  
  312.     if (msg = (GMsg *)GetMsg(ComPort)) {
  313.         do {
  314.         switch(msg->Cmd) {
  315.         case 'O':
  316.             DoOptions(msg->Data1, msg->Data2);
  317.             break;
  318.         }
  319.         ReplyMsg((MSG *)msg);
  320.         if (ZeroOption)
  321.             xexit(0);
  322.         } while (msg = (GMsg *)GetMsg(ComPort));
  323.         if (State == ST_WAITCD && !GotOffPort)
  324.         Disconnect(0);
  325.     }
  326.  
  327.     while (ior = (IOR *)GetMsg(IoSink)) {
  328.         if (ior == (IOR *)&Iot) {
  329.         short diu;
  330.         long status;
  331.  
  332.         IotIP = 0;
  333.         Iot.tr_time.tv_secs = 1;
  334.         Iot.tr_time.tv_micro= 0;
  335.  
  336.         /*
  337.          *  If # of references for unit is > 1 then device
  338.          *  is in use.    When refs fall <= 1 then reset the
  339.          *  serial port.
  340.          */
  341.  
  342.         diu = DeviceInUse();
  343.         if (diu) {
  344.             if (GotOffPort == 0) {
  345.             ulog(1, "Device in use");
  346.             RxStop();
  347.             GotOffPort = 1;
  348.             State = ST_WAITCD;
  349.             }
  350.             SendIO(&Iot);
  351.             IotIP = 1;
  352.             continue;
  353.         }
  354.         if (GotOffPort) {
  355.             GotOffPort = 0;
  356.             ulog(1, "Getty resetting");
  357.             SendIO(&Iot);
  358.             IotIP = 1;
  359.             Disconnect(1);
  360.             continue;
  361.         }
  362.         if (State == ST_WAITCD)
  363.             RxStop();
  364.  
  365.         if (State != ST_WAITCD && IosrIP == 0) {
  366.             RxStart();
  367.             ulog(2, "Carrier, Getty getting on port");
  368.         }
  369.  
  370.         status = GetStatus();
  371.  
  372.         /*
  373.          *  If state connected and we loose carrier, disconnect.
  374.          *
  375.          *  If state connected and timeout occurs disconnect.
  376.          */
  377.  
  378.         if (State != ST_WAITCD) {
  379.             if ((status & CIAF_COMCD) != 0) {
  380.             ulog(2, "Getty, Carrier lost");
  381.             Disconnect(1);
  382.             } else {
  383.             if (--CountDown == 0) {
  384.                 ulog(2, "Getty, Timeout, Disconnecting");
  385.                 Disconnect(1);
  386.                 status |= CIAF_COMCD;   /*    set lost carrier flag */
  387.             }
  388.             }
  389.         }
  390.  
  391.         switch(State) {
  392.         case ST_WAITCD:
  393.             if ((status & CIAF_COMCD) == 0) {
  394.             State = ST_CONNECT;
  395.             CountDown = 60;     /*    allow 60 seconds */
  396.             ulog(2, "Carrier Detect");
  397.             } else {
  398.             Iot.tr_time.tv_secs = 2;
  399.             }
  400.             break;
  401.         case ST_CONNECT:
  402.             /*
  403.              *    Wait for CONNECT message, then send Login:
  404.              */
  405.  
  406.             if (IgnoreConnect && HaveConnectMsg == 0) {
  407.             SetParams(1);
  408.             HaveConnectMsg = 1;
  409.             ulog(2, "Connect");
  410.             }
  411.  
  412.             if (HaveConnectMsg) {
  413.             FILE *fi;
  414.  
  415.             Delay(50);
  416.             ClearRecv();
  417.             if (fi = fopen("Getty:Getty-Header", "r")) {
  418.                 while (fgets(ScrBuf, sizeof(ScrBuf), fi)) {
  419.                 SerPuts(ScrBuf);
  420.                 SerPuts("\r");
  421.                 }
  422.                 fclose(fi);
  423.             }
  424.             termCr = termLf = 1;
  425.             SerPuts("Login: ");
  426.             ulog(1, "Getty, Connect, Login");
  427.             State = ST_LOGIN;
  428.             Index = 0;
  429.             HaveLogin = 0;
  430.             LoginBuf[0] = 0;
  431.             }
  432.             break;
  433.         case ST_LOGIN:        /*    wait Login: response    */
  434.             if (HaveLogin) {
  435.             if (LoginBuf[0] == 0) {
  436.                 State = ST_CONNECT;
  437.                 break;
  438.             }
  439.             ClearRecv();
  440.             PasswdBuf[0] = 0;
  441.  
  442.             /*
  443.              *  If no password required, else request
  444.              *  password.
  445.              */
  446.  
  447.             if (CheckLoginAndPassword()) {
  448.                 HavePasswd = 1;
  449.                 Index = 0;
  450.                 State = ST_PASSWD;
  451.             } else {
  452.                 SerPuts("Password: ");
  453.                 ulog(2, "Getty, Passwd");
  454.                 State = ST_PASSWD;
  455.                 HavePasswd = 0;
  456.                 Index = 0;
  457.             }
  458.             }
  459.             break;
  460.         case ST_PASSWD:     /*    wait Password: response */
  461.             if (HavePasswd) {
  462.             if (CheckLoginAndPassword()) {
  463.                 ulog(-1, "login %s", LoginBuf);
  464.  
  465.                 /*
  466.                  *    Disable read requests but leave serial
  467.                  *    port locked.
  468.                  */
  469.  
  470.                 RxStop();
  471.  
  472.                 /*
  473.                  *    If run successful, leave read req and
  474.                  *    timer disabled.
  475.                  */
  476.  
  477.                 RunPasswdEntry();
  478.  
  479.                 if (DropOnExit)
  480.                 Disconnect(1);
  481.                 else
  482.                 State = ST_CONNECT;
  483.                 ulog(-1, "disconnect");
  484.             } else {
  485.                 SerPuts("Login Failed.\r\n\n");
  486.                 State = ST_CONNECT;
  487.                 ulog(0, "LoginFailed user=%s pass=%s", LoginBuf, PasswdBuf);
  488.             }
  489.             HaveLogin = 0;
  490.             HavePasswd= 0;
  491.             LoginBuf[0] = 0;
  492.             }
  493.             break;
  494.         }
  495.  
  496.         /*
  497.          *  Make no read requests while running 3rd party
  498.          *  program, else resend read request.
  499.          */
  500.  
  501.         if (IotIP == 0) {
  502.             IotIP = 1;
  503.             SendIO(&Iot);
  504.         }
  505.         }
  506.  
  507.         /*
  508.          *    RECEIVED SERIAL READ DATA
  509.          */
  510.  
  511.         if (ior == (IOR *)&Iosr) {
  512.         long status;
  513.  
  514.         IosrIP = 0;
  515.  
  516.         status = GetStatus();
  517.  
  518.         /*
  519.          *  BREAK used to switch baud rates between allowed
  520.          *  values
  521.          */
  522.  
  523.         if (status & IO_STATF_READBREAK) {
  524.             if (BaudAdjust == 0 && (State == ST_LOGIN || State == ST_PASSWD)) {
  525.             if (++BIndex == arysize(Bauds))
  526.                 BIndex = 0;
  527.             if (Bauds[BIndex] == 0)
  528.                 BIndex = 0;
  529.             Ios.io_Baud = Bauds[BIndex];
  530.             SetParams(1);
  531.             ulog(1, "<BREAK> to %d baud", Ios.io_Baud);
  532.             Delay(50);
  533.             ClearRecv();
  534.             Index = 0;
  535.             State = ST_CONNECT;
  536.             }
  537.         } else if (Iosr.IOSer.io_Actual == 1) {
  538.             char *ptr;
  539.             UBYTE c = (UBYTE)RxBuf[0];
  540.  
  541.             ulog(9, "Rx %02x %c", c, (c < 32) ? ' ' : c);
  542.             c &= 0x7F;
  543.  
  544.             switch(State) {
  545.             case ST_WAITCD:    /*  looking for CONNECT msg */
  546.             case ST_CONNECT:    /*  looking for CONNECT msg */
  547.             ptr = ConnectBuf;
  548.             break;
  549.             case ST_LOGIN:    /*  looking for login name  */
  550.             ptr = LoginBuf;
  551.             break;
  552.             case ST_PASSWD:    /*  looking for password    */
  553.             ptr = PasswdBuf;
  554.             break;
  555.             }
  556.             if (State == ST_LOGIN && HaveLogin)
  557.             c = 0;
  558.             if (State == ST_PASSWD && HavePasswd)
  559.             c = 0;
  560.  
  561.             switch(c) {
  562.             case 0:
  563.             break;
  564.             case 8:
  565.             if (State == ST_LOGIN && HaveLogin)
  566.                 break;
  567.             if (Index) {
  568.                 if (State == ST_LOGIN)
  569.                 SerPuts("\010 \010");
  570.                 --Index;
  571.             }
  572.             break;
  573.             case 10:
  574.             if (termLf == 0)
  575.                 break;
  576.             termCr = 0;
  577.             case 13:
  578.             if (c == 13) {
  579.                 if (termCr == 0)
  580.                 break;
  581.                 else
  582.                 termLf = 0;
  583.             }
  584.             ptr[Index] = 0;
  585.             Index = 0;
  586.             switch(State) {
  587.             case ST_WAITCD:
  588.             case ST_CONNECT:
  589.                 if (strncmp(ptr, "CONNECT", 7)) {
  590.                 ulog(9, "Looking for CONNECT, got '%s'", ptr);
  591.                 break;
  592.                 }
  593.                 Delay(50);
  594.                 HaveConnectMsg = 1;
  595.                 if (BaudAdjust) {
  596.                 ulog(9, "Connect Auto-Baud %d", Ios.io_Baud);
  597.                 } else {
  598.                 char *str = ptr + 7;
  599.                 while (*str && (*str == 9 || *str == ' '))
  600.                     ++str;
  601.                 if (*str >= '0' && *str <= '9')
  602.                     Ios.io_Baud = atoi(str);
  603.                 else
  604.                     Ios.io_Baud = Bauds[0];
  605.                 ulog(9, "Connect at %d baud", Ios.io_Baud);
  606.                 }
  607.                 SetParams(1);
  608.                 break;
  609.             case ST_LOGIN:
  610.                 HaveLogin = 1;
  611.                 SerPuts("\r\n");
  612.                 ulog(1, "Login: %s", ptr);
  613.                 break;
  614.             case ST_PASSWD:
  615.                 HavePasswd = 1;
  616.                 SerPuts("\r\n");
  617.                 ulog(2, "Password: %s", ptr);
  618.                 break;
  619.             }
  620.             break;
  621.             default:
  622.             if (Index == 31)
  623.                 break;
  624.             if (State == ST_LOGIN) {
  625.                 char cc[2];
  626.                 cc[0] = c;
  627.                 cc[1] = 0;
  628.                 SerPuts(cc);
  629.             }
  630.             ptr[Index++] = c;
  631.             break;
  632.             }
  633.         }
  634.         if (IosrIP == 0)
  635.             RxStart();
  636.         }
  637.     }
  638.     }
  639.     xexit(0);
  640. }
  641.  
  642. void
  643. RxStart()
  644. {
  645.     Iosr.IOSer.io_Data = (APTR)RxBuf;
  646.     Iosr.IOSer.io_Length = 1;
  647.     Iosr.IOSer.io_Message.mn_Node.ln_Type = NT_MESSAGE;
  648.     IosrIP = 1;
  649.     SendIO(&Iosr);
  650. }
  651.  
  652. void
  653. RxStop()
  654. {
  655.     if (IosrIP) {
  656.     AbortIO(&Iosr);
  657.     WaitIO(&Iosr);
  658.     IosrIP = 0;
  659.     }
  660. }
  661.  
  662. long
  663. GetStatus()
  664. {
  665.     int error;
  666.     long status = CIAF_COMCD;    /*  no carrier detect    */
  667.  
  668.     if (!DeviceInUse()) {
  669.     Ioss.IOSer.io_Command = SDCMD_QUERY;
  670.     Ioss.IOSer.io_Message.mn_Node.ln_Type = NT_MESSAGE;
  671.     if (error = DoIO(&Ioss))
  672.         ulog(0, "Query Error %d", error);
  673.     status = Ioss.io_Status;
  674.     if (IgnoreCD)
  675.         status &= ~CIAF_COMCD;
  676.     }
  677.     return(status);
  678. }
  679.  
  680. void
  681. xexit(code)
  682. {
  683.     if (ComPortMask) {
  684.     GMsg *msg;
  685.     Forbid();
  686.     while (msg = (GMsg *)GetMsg(ComPort))
  687.         ReplyMsg((MSG *)msg);
  688.     DeletePort(ComPort);
  689.     Permit();
  690.     }
  691.     if (IotIP) {
  692.     AbortIO(&Iot);
  693.     WaitIO(&Iot);
  694.     }
  695.     if (Iot.tr_node.io_Device)
  696.     CloseDevice(&Iot);
  697.  
  698.     RxStop();
  699.  
  700.     if (Ios.IOSer.io_Device) {
  701.     RestoreDeviceVector(Ios.IOSer.io_Device);
  702.     CloseDevice(&Ios);
  703.     }
  704.  
  705.     if (IoSink)
  706.     DeletePort(IoSink);
  707.  
  708.     if (NullFH)
  709.     Close(NullFH);
  710.  
  711.     if (code)
  712.     ulog(-1, "Getty Exiting with code %d", code);
  713.  
  714.     exit(code);
  715. }
  716.  
  717. void
  718. SerPuts(str)
  719. char *str;
  720. {
  721.     int error;
  722.  
  723.     if (!DeviceInUse()) {
  724.     Ioss.IOSer.io_Command = CMD_WRITE;
  725.     Ioss.IOSer.io_Data = (APTR)str;
  726.     Ioss.IOSer.io_Length = strlen(str);
  727.     Ioss.IOSer.io_Message.mn_Node.ln_Type = NT_MESSAGE;
  728.     if (error = DoIO(&Ioss))
  729.         ulog(0, "Write Error %d", error);
  730.     }
  731. }
  732.  
  733. static short RxDisableIP;
  734.  
  735. void
  736. RxDisable()
  737. {
  738.     RxDisableIP = IosrIP;
  739.     RxStop();
  740. }
  741.  
  742. void
  743. RxEnable()
  744. {
  745.     if (RxDisableIP && IosrIP == 0)
  746.     RxStart();
  747. }
  748.  
  749. void
  750. ClearRecv()
  751. {
  752.     int error;
  753.  
  754.     if (!DeviceInUse()) {
  755.     Ioss.IOSer.io_Command = CMD_CLEAR;
  756.     Ioss.IOSer.io_Message.mn_Node.ln_Type = NT_MESSAGE;
  757.  
  758.     if (error = DoIO(&Ioss))
  759.         ulog(0, "Clear Error %d", error);
  760.     }
  761. }
  762.  
  763. void
  764. SetParams(wire7)
  765. {
  766.     int error;
  767.  
  768.     /*if (NoBugs == 0)
  769.     wire7 = Wire7;*/
  770.  
  771.     {
  772.  
  773.     RxStop();
  774.  
  775.     if (!DeviceInUse()) {
  776.         if (wire7 && Wire7)
  777.         Ios.io_SerFlags |= SERF_7WIRE;
  778.         else
  779.         Ios.io_SerFlags &= ~SERF_7WIRE;
  780.         Ios.IOSer.io_Command = SDCMD_SETPARAMS;
  781.         Ios.IOSer.io_Message.mn_Node.ln_Type = NT_MESSAGE;
  782.         if (error = DoIO(&Ios))
  783.         ulog(0, "SetParams Error %d", error);
  784.     }
  785.     }
  786. }
  787.  
  788. void
  789. Disconnect(dropdtr)
  790. {
  791.     short retry = (IgnoreDTR) ? 2 : 10;
  792.  
  793.     ulog(2, "Disconnect drop=%d", dropdtr);
  794.     HaveConnectMsg = 0;
  795.     HaveLogin    = 0;
  796.     HavePasswd    = 0;
  797.     LoginBuf[0] = 0;
  798.     PasswdBuf[0] = 0;
  799.     Index = 0;
  800.     State = ST_WAITCD;
  801.  
  802.     if (IgnoreCD == 0) {
  803.     while (dropdtr && DeviceInUse() == 0) {
  804.         short i;
  805.         long status = GetStatus();
  806.  
  807.         if (status & CIAF_COMCD)        /*  no carrier  */
  808.         break;
  809.  
  810.         RxDisable();
  811.         SetParams(0);
  812.  
  813.         if (IgnoreDTR) {
  814.         if (ModemType != 'd') {
  815.             Delay(70);
  816.             if (DeviceInUse())
  817.             break;
  818.             SerPuts("+++");
  819.             Delay(70);
  820.             if (DeviceInUse())
  821.             break;
  822.             SerPuts("\010\010\r");
  823.             Delay(10);
  824.             if (DeviceInUse())
  825.             break;
  826.             SerPuts("ATH0\r");
  827.             Delay(120);
  828.         }
  829.         } else {
  830.         RefCnt += 2;
  831.         CloseDevice(&Ios);
  832.         Ios.IOSer.io_Device = NULL;    /*  so xexit doesn't reclose */
  833.         for (i = 0; i < 5; ++i) {      /*  5 seconds   */
  834.             Delay(50);
  835.             if (SetSignal(SIGBREAKF_CTRL_C, 0) & SIGBREAKF_CTRL_C)
  836.             xexit(23);
  837.         }
  838.  
  839.         /*
  840.          *  Use Iosr to re-open serial device so we don't loose
  841.          *  our config.
  842.          */
  843.  
  844.         RefCnt -= 2;
  845.         if (Wire7)
  846.             Ios.io_SerFlags |= SERF_7WIRE;
  847.         else
  848.             Ios.io_SerFlags &= ~SERF_7WIRE;
  849.         if (OpenDevice(DeviceName, DeviceUnit, &Ios, 0)) {
  850.             Ios.IOSer.io_Device = NULL;
  851.             xexit(22);
  852.         }
  853.         Iosr.IOSer.io_Device = Ios.IOSer.io_Device;
  854.         Ioss.IOSer.io_Device = Ios.IOSer.io_Device;
  855.         Iosr.IOSer.io_Unit = Ios.IOSer.io_Unit;
  856.         Ioss.IOSer.io_Unit = Ios.IOSer.io_Unit;
  857.         SetParams(1);
  858.         }
  859.  
  860.         /*
  861.          *    Loop until carrier lost
  862.          */
  863.  
  864.         RxEnable();
  865.  
  866.         if (--retry == 0) {
  867.         if (IgnoreDTR == 0)
  868.             puts("Getty: unable to disconnect!");
  869.         break;
  870.         }
  871.     }
  872.     }
  873.     if (!DeviceInUse())
  874.     InitModem();
  875. }
  876.  
  877. void
  878. InitModem()
  879. {
  880.     char buf[64];
  881.     short i;
  882.  
  883.     RxDisable();
  884.     ulog(2, "Init Modem");
  885.     Ios.io_Baud = Bauds[0];    /*  reset baud rate */
  886.     BIndex = 0;
  887.     SetParams(0);
  888.     RxEnable();
  889.  
  890.     switch(ModemType) {
  891.     case 'm':               /*  Multi Modem     */
  892.     SerPuts("\010\010\r");
  893.     Delay(10);
  894.     if (DeviceInUse())
  895.         break;
  896.     SerPuts("AT\r");
  897.     Delay(50);
  898.     if (DeviceInUse())
  899.         break;
  900.     sprintf(buf, "ATM%dS0=%dX4$BA%d&E%d\r",
  901.         SpeakerLevel,
  902.         AnswerRing,
  903.         !BaudAdjust,
  904.         (Wire7) ? 4 : 3
  905.     );
  906.     SerPuts(buf);
  907.     break;
  908.     case 'h':
  909.     SerPuts("\010\010\r");
  910.     Delay(10);
  911.     if (DeviceInUse())
  912.         break;
  913.     SerPuts("ATZ\r");
  914.     Delay(120);
  915.     if (DeviceInUse())
  916.         break;
  917.     strcpy(buf, "AT");
  918.     if (SpeakerOpt)
  919.         sprintf(buf + strlen(buf), "M%d", SpeakerLevel);
  920.     sprintf(buf + strlen(buf), "S0=%d", AnswerRing);
  921.     strcat(buf, "\r");
  922.     SerPuts(buf);
  923.     break;
  924.     case 'd':
  925.     SerPuts("\010\010\r");
  926.     break;
  927.     }
  928.     for (i = 0; i < arysize(AtFields) && AtFields[i]; ++i) {
  929.     Delay(50);
  930.     if (DeviceInUse())
  931.         break;
  932.     SerPuts(AtFields[i]);
  933.     SerPuts("\r");
  934.     }
  935.     Delay(20);
  936.     ClearRecv();
  937.     Index = 0;
  938. }
  939.  
  940. void
  941. DoOptions(ac, av)
  942. char *av[];
  943. {
  944.     short i;
  945.     short bi = 0;
  946.     short fi = 0;
  947.     long v;
  948.  
  949.     for (i = 1; i < ac; ++i) {
  950.     char *ptr = av[i];
  951.     if (*ptr != '-') {
  952.         if (fi != arysize(AtFields))
  953.         AtFields[fi++] = ptr;
  954.         else
  955.         puts("AT field overflow");
  956.         continue;
  957.     }
  958.     if (*++ptr)             /*  skip -      */
  959.         ++ptr;        /*  and option    */
  960.     v = atoi(ptr);
  961.     switch(ptr[-1]) {
  962.     case '0':
  963.         ZeroOption = 1;
  964.         break;
  965.     case '7':
  966.         Wire7 = 1;
  967.         break;
  968.     case 'S':
  969.         DeviceName = ptr;
  970.         break;
  971.     case 'U':
  972.         DeviceUnit = v;
  973.         break;
  974.     case 'M':
  975.         ModemType = *ptr;
  976.         break;
  977.     case 'A':
  978.         BaudAdjust = 1;
  979.         break;
  980.     case 'B':
  981.         if (bi != arysize(Bauds))
  982.         Bauds[bi++] = v;
  983.         else
  984.         puts("-B field overflow");
  985.         break;
  986.     case 'm':
  987.         SpeakerOpt = 1;
  988.         SpeakerLevel = v;
  989.         break;
  990.     case 'r':
  991.         AnswerRing = v;
  992.         break;
  993.     case 'h':
  994.         IgnoreCD = !v;
  995.         break;
  996.     case 'c':
  997.         IgnoreConnect = !v;
  998.         break;
  999.     case 'd':
  1000.         IgnoreDTR = !v;
  1001.         break;
  1002.     case 'x':
  1003.         LogLevel = v;
  1004.         LogToStdout = (v >= 0);
  1005.         break;
  1006.     case 'n':
  1007.         /*NoBugs = 1;*/
  1008.         break;
  1009.     default:
  1010.         printf("Warning, Bad option: -%s\n", ptr);
  1011.         break;
  1012.     }
  1013.     }
  1014.     if (fi && fi != arysize(AtFields))
  1015.     AtFields[fi] = NULL;
  1016.     if (bi && bi != arysize(Bauds))
  1017.     Bauds[bi] = 0;
  1018. }
  1019.  
  1020. DeviceInUse()
  1021. {
  1022.     return(RefCnt > 0);
  1023. }
  1024.  
  1025. /*
  1026.  *  Device Vector Intercept, used to force SERF_SHARED on device open.
  1027.  */
  1028.  
  1029. extern void AsmOpenIntercept();
  1030. extern void AsmCloseIntercept();
  1031. /*extern void A2232BeginIOFix();*/
  1032.  
  1033. FPTR OldOpenVector;
  1034. FPTR OldCloseVector;
  1035. /*FPTR OldBeginIOVector;*/
  1036.  
  1037. void
  1038. InterceptDeviceVector(dev)
  1039. struct Library *dev;
  1040. {
  1041.     Forbid();
  1042.     OldOpenVector = SetFunction((struct Library *)dev, LIB_OPEN, AsmOpenIntercept);
  1043.     OldCloseVector = SetFunction((struct Library *)dev, LIB_CLOSE, AsmCloseIntercept);
  1044.     /*OldBeginIOVector = SetFunction((struct Library *)dev, DEV_BEGINIO, A2232BeginIOFix);*/
  1045.     Permit();
  1046. }
  1047.  
  1048. void
  1049. RestoreDeviceVector(dev)
  1050. struct Library *dev;
  1051. {
  1052.     FPTR oldFunc;
  1053.     int error = 0;
  1054.  
  1055.     /*
  1056.      *    must restore in same order as had openned
  1057.      */
  1058.  
  1059.     for (;;) {
  1060.     Forbid();
  1061.     oldFunc = (FPTR)SetFunction((struct Library *)dev, LIB_OPEN, OldOpenVector);
  1062.     if (oldFunc != (FPTR)AsmOpenIntercept) {
  1063.         SetFunction((struct Library *)dev, LIB_OPEN, oldFunc);
  1064.         Permit();
  1065.         if (error == 0) {
  1066.         error = 1;
  1067.         ulog(-1, "UNABLE TO REVERSE SETVECTOR, YOU MUST DEINSTALL");
  1068.         ulog(-1, "GETTYs ON THE SAME DEVICE IN REVERSE ORDER!");
  1069.         }
  1070.         Delay(50 * 5);
  1071.         continue;
  1072.     }
  1073.     break;
  1074.     }
  1075.     SetFunction((struct Library *)dev, LIB_CLOSE, OldCloseVector);
  1076.     /*SetFunction((struct Library *)dev, DEV_BEGINIO, OldBeginIOVector);*/
  1077.     Permit();
  1078. }
  1079.  
  1080.  
  1081.