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