home *** CD-ROM | disk | FTP | other *** search
/ back2roots/padua / padua.7z / padua / uucp / duucp-1.17 / AU-117b4-src.lha / src / getty / getty.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-02-06  |  23.9 KB  |  1,216 lines

  1. /*
  2.  *  GETTY.C
  3.  *
  4.  *  (C)Copyright 1989, Matthew Dillon, All Rights Reserved
  5.  *
  6.  *  Uses:
  7.  *    GETTY:PASSWD
  8.  *    GETTY:LOGFILE
  9.  *    GETTY:Getty-Header
  10.  *
  11.  *  GETTY   <options>    <modem-commands>
  12.  *
  13.  *    -Sdevicenam Tells GETTY which serial.device to use, default
  14.  *            serial.device
  15.  *
  16.  *    -Uunitnum   Tells GETTY which unit number to use, default 0
  17.  *
  18.  *    -A        Always talk to the modem at the first baud
  19.  *            rate in the -B list and ignore the baud rate
  20.  *            in the CONNECT message.
  21.  *
  22.  *    -7        use SERF_7WIRE while online.
  23.  *
  24.  *    -Bn        Set baud rate.  If specified multiple times the
  25.  *            first one is the default and remaining ones
  26.  *            switched to when a BREAK is received after a
  27.  *            connect.  Also determines how CONNECT messages
  28.  *            are interpreted.  A CONNECT with no number uses
  29.  *            the first -B entry while CONNECTs with numbers
  30.  *            use those numbers regardless of any -B entries.
  31.  *
  32.  *    -Mc        Set modem type:
  33.  *            c = m    = multimodem
  34.  *                h    = hays
  35.  *                d    = dumb (no AT or +++ cmds are ever sent),
  36.  *                  normally used with only one specified
  37.  *                  baud rate.
  38.  *
  39.  *    -m1        Turn on the modem speaker during dialing/connect
  40.  *            (default is -m0)
  41.  *
  42.  *    -h0        Ignore CD (carrier detect), default is to use
  43.  *            carrier detect.
  44.  *
  45.  *    -c0        Ignore CONNECT message (i.e. you are not connected
  46.  *            to a modem, usually combined with -h0).  Default is
  47.  *            to expect a CONNECT message.
  48.  *
  49.  *    -d0        do not use DTR to drop connection.    Default is
  50.  *            to drop DTR to drop a connection.  If this option
  51.  *            is chosen the +++ and ATH0 sequence will be used
  52.  *            to drop a connection.
  53.  *
  54.  *    -xn        Set debug level.  Also causes log output to go
  55.  *            to stdout instead of GETTY:LOGFILE
  56.  *
  57.  *    -ln        n = 0:  Do not add -HLINK to command line
  58.  *            n = 1:  Add -HLINK to commands started by Getty
  59.  *
  60.  *    -bn        n = 0:  Do not add -BAUD to command line
  61.  *            n = 1:  Add -BAUD <baud> to commands started
  62.  *    Added by Christian Wolf (chris@wolfhh.hanse.de)
  63.  *
  64.  *    -un        n = 0:  Do not add -USER to command line
  65.  *            n = 1:  Add -USER <user> to commands started
  66.  *
  67.  *
  68.  *    -0        QUIT - Kills any running getty for the specified
  69.  *            port.
  70.  *
  71.  *    Any fields specified without a '-' are considered modem commands
  72.  *    used to initialize/reinitialize the modem.  Up to 16 fields may
  73.  *    be specified (each is sent to the modem in 1 second intervals)
  74.  */
  75.  
  76. /*
  77.  * FAX Modifications 1991 by David Varley
  78.  *
  79.  * Add entry in UULIB:passwd along the lines of
  80.  * fax,*,0,0,(Fax_Connection),ram:,AFAX:Faa
  81.  *
  82.  * (Faa is my Fax Auto-Answer program. Uses Getty, Device, Unit flags)
  83.  *
  84.  * It appears that we do not get CD when answering Fax, just +FCON
  85.  * So, have to wait on another event, being serial data received,
  86.  * and look for +FCON.
  87.  * This is a drag, as can wake on noise, etc. DAV
  88.  *
  89.  * 1.15 - 8Nov91 DAV
  90.  * As of TR-29.2/90-21R6 Fax responds +FCO
  91.  *  - Provide +FCO as subset of +FCON
  92.  *
  93.  */
  94.  
  95. /*
  96.  * Modifications to use OwnDevUnit.library for serial port locking
  97.  * done by Christopher A. Wichura (caw@miroc.chi.il.us)
  98.  */
  99.  
  100. #include "defs.h"
  101.  
  102. Prototype char    DeviceName[64];
  103. Prototype long    DeviceUnit;
  104. Prototype BPTR    NullFH;
  105. Prototype Iot      Iot0;
  106. Prototype Iot      Iot1;
  107. Prototype IOSer   Ios;
  108. Prototype IOSer   Iosr;
  109. Prototype IOSer   Iosw;
  110. Prototype IOSer   Ioss;
  111. Prototype long      MainTimeout;
  112.  
  113. Prototype char      Iot0IP;    /*  Iot0 in progress      */
  114. Prototype char      Iot1IP;    /*  Iot1 in progress      */
  115. Prototype char      IosrIP;    /*  serial read in prog   */
  116. Prototype char      IoswIP;    /*  serial write in prog  */
  117.  
  118. Prototype char    HardLink;
  119. Prototype char    BaudReport;
  120. Prototype long    BaudRate;
  121. Prototype char    UserReport;    /* Added by Christian Wolf (chris@wolfhh.hanse.de) */
  122.  
  123. Prototype struct MsgPort *IoSink;
  124. Prototype char    LoginBuf[32];
  125. /* Added by Christian Wolf (chris@wolfhh.hanse.de) */
  126. char    UserReport    = 0;
  127. Prototype char    PasswdBuf[32];
  128.  
  129. IDENT (".15");
  130.  
  131. char    *CopyRight = "(c)Copyright 1989, Matthew Dillon, All Rights Reserved\r\n";
  132. char    *ComPortName = NULL;
  133.  
  134. char    Fax        = 0;
  135. char    FIgnoreCD    = 0;
  136. char    DeviceName [64] = { "serial.device" };
  137. long    DeviceUnit    = 0;
  138. BPTR    NullFH        = 0;
  139. char    SpeakerLevel    = 0;
  140. char    AnswerRing    = 2;    /*  default, answer on second ring */
  141. char    SpeakerOpt    = 0;
  142. char    IgnoreCD    = 0;
  143. char    IgnoreConnect    = 0;
  144. char    IgnoreDTR    = 0;
  145. char    BaudAdjust    = 0;
  146. char    DropOnExit    = 1;
  147. char    ModemType    = 'h';
  148. char    ZeroOption    = 0;
  149. char    HardLink    = 0;
  150. char    BaudReport    = 0;
  151. char    Wire7        = 0;        /*  use 7 wire while online */
  152. long    Bauds [16]    = { 9600 };    /*  up 16 baud rates        */
  153. long    BaudRate;
  154. char    *AtFields [16];
  155.  
  156. struct MsgPort *ComPort = NULL;      /*  Background Getty    */
  157. struct MsgPort *IoSink    = NULL;      /*  Sink for IO reqs.   */
  158. long    IoSinkMask;
  159. long    ComPortMask;
  160.  
  161. Iot    Iot0;        /*  login timeout    */
  162. Iot    Iot1;        /*  check other things    */
  163. IOSer    Ios;        /*  parameters req    */
  164. IOSer    Iosr;        /*  serial read-req    */
  165. IOSer    Iosw;        /*  write req        */
  166. IOSer    Ioss;        /*  synchronous req    */
  167.  
  168. long    MainTimeout = 3;
  169.  
  170. char    Iot0IP;     /*  Iot0 in progress    */
  171. char    Iot1IP;     /*  Iot1 in progress    */
  172. char    IosrIP;     /*  serial read in prog */
  173. char    IoswIP;     /*  serial write in prog*/
  174. char    CarrierDetectEvent;
  175. char    TimeoutEvent;
  176. char    PortRequestedEvent;
  177. char    SerialEvent;
  178. char    OptionEvent;
  179.  
  180. struct Library *OwnDevUnitBase = NULL;
  181. char    NotifyBit = -1;
  182. long    NotifyMask;
  183.  
  184. char    LoginBuf[32];
  185. char    PasswdBuf[32];
  186. char    RxBuf[32];
  187. char    ScrBuf[256];
  188.  
  189. void myexit (void);
  190. void FLockSerialPort (void);
  191. void FUnLockSerialPort (void);
  192. void InitModem (void);
  193. void Disconnect (int);
  194. void WaitEvents (void);
  195. void Timeout (int);
  196. void OpenSerial (void);
  197. void CloseSerial (void);
  198. void SetParams (int);
  199. void RxStart (void);
  200. void RxStop (void);
  201. long GetStatus (void);
  202. void ClearRecv (void);
  203. void ResetSP (void);
  204. void DoOptions (int, char **);
  205. void DoLogin (void);
  206. void SerPuts (char *);
  207. char *GetLine (int);
  208.  
  209. Prototype void NiceAbortIO (void *);
  210. Prototype void RxStart (void);
  211. Prototype void RxStop (void);
  212. Prototype long GetStatus (void);
  213. Prototype void Timeout (int);
  214.  
  215. int
  216. main (int ac, char **av)
  217. {
  218.     puts (CopyRight);
  219.     fflush (stdout);
  220.     atexit (myexit);
  221.  
  222.     LogProgram = "Getty";
  223.     LogWho = LoginBuf;
  224.     LogFile = "Getty:LOGFILE";
  225.     PasswdFile = "Getty:Passwd";
  226.  
  227.     DoOptions (ac, av);
  228.  
  229.     IoSink = CreatePort (NULL, 0);
  230.     IoSinkMask = 1 << IoSink->mp_SigBit;
  231.  
  232.     ComPortName = malloc (strlen (DeviceName) + 20);
  233.     if (!ComPortName) {
  234.         fprintf (stderr, "No memory for portname!\n");
  235.         exit (30);
  236.     }
  237.     sprintf (ComPortName, "Getty.%s.%ld", DeviceName, DeviceUnit);
  238.  
  239.     Forbid();
  240.     if (ComPort = FindPort (ComPortName)) {
  241.         GMsg
  242.             msg;
  243.  
  244.         msg.Cmd = 'O';
  245.         msg.Data1 = ac;
  246.         msg.Data2 = (void *) av;
  247.         msg.Msg.mn_ReplyPort = IoSink;
  248.         PutMsg (ComPort, &msg.Msg);
  249.         ComPort = NULL;
  250.         WaitPort (IoSink);
  251.         Remove (&msg.Msg.mn_Node);
  252.         Permit ();
  253.         puts ("Options updated");
  254.         exit (0);
  255.     }
  256.     ComPort = CreatePort (ComPortName, 0L);
  257.     Permit ();
  258.  
  259.     ComPortMask = 1L << ComPort->mp_SigBit;
  260.  
  261.     NullFH = Open ("NULL:", 1006);
  262.     if (!NullFH) {
  263.         ulog (-1, "GETTY REQUIRES NULL: HANDLER!");
  264.         puts ("Requires NULL: handler!");
  265.         exit (30);
  266.     }
  267.     if (LogToStdout == 0) {
  268.         freopen ("NULL:", "r", stdin);
  269.         freopen ("NULL:", "w", stdout);
  270.         freopen ("NULL:", "w", stderr);
  271.     }
  272.  
  273.     /*
  274.      *  Grab OwnDevUnit.library stuff
  275.      */
  276.  
  277.     if (!(OwnDevUnitBase = OpenLibrary (ODU_NAME, 0))) {
  278.         fprintf (stderr, "Unable to open %s\n", ODU_NAME);
  279.         exit (20);
  280.     }
  281.  
  282.     if ((NotifyBit = AllocSignal (-1)) == -1) {
  283.         fprintf (stderr, "Couldn't allocate notify signal.\n");
  284.         exit (20);
  285.     }
  286.  
  287.     NotifyMask = 1L << NotifyBit;
  288.  
  289.     /*
  290.      *  Timer Device
  291.      */
  292.  
  293.     Iot0.tr_node.io_Message.mn_ReplyPort = IoSink;
  294.     if (OpenDevice ("timer.device", UNIT_VBLANK, (struct IORequest *) &Iot0, 0L)) {
  295.         Iot0.tr_node.io_Device = NULL;
  296.         exit (20);
  297.     }
  298.     Iot0.tr_node.io_Command = TR_ADDREQUEST;
  299.     Iot1 = Iot0;
  300.  
  301.     Iot1.tr_time.tv_secs = MainTimeout;
  302.     Iot1.tr_time.tv_micro= 0;
  303.     SendIO ((struct IORequest *) &Iot1);
  304.     Iot1IP = 1;
  305.  
  306.     /*
  307.      *  Main Loop
  308.      */
  309.  
  310.     FLockSerialPort ();
  311.     OpenSerial ();
  312.     InitModem ();
  313.  
  314.     for (;;) {
  315.         WaitEvents ();
  316.         if (OptionEvent) {
  317.             puts ("OE");
  318.             InitModem ();
  319.             OptionEvent = 0;
  320.         }
  321.         if (CarrierDetectEvent) {
  322.             ulog (2, "Carrier Detected");
  323.             DoLogin ();
  324.             ulog (2, "Getty Disconnecting");
  325.             Disconnect (1);
  326.             InitModem ();
  327.             OptionEvent = 0;
  328.         }
  329.         if (Fax && SerialEvent) {
  330.             IgnoreCD = 1;
  331.             CarrierDetectEvent = 1;
  332.             ulog (2, "Serial Data Detected");
  333.             DoLogin ();
  334.             IgnoreCD = FIgnoreCD;
  335.             ulog (2, "Getty Disconnecting");
  336.             Disconnect (1);
  337.             InitModem ();
  338.             OptionEvent = 0;
  339.         }
  340.         if (PortRequestedEvent) {
  341.             ulog (2, "External Port Request");
  342.             CloseSerial ();
  343.             FUnLockSerialPort ();
  344.  
  345.             PortRequestedEvent = 0;
  346.  
  347.             for (;;) {
  348.                 while (!AvailDevUnit (DeviceName, DeviceUnit))
  349.                     WaitEvents ();
  350.  
  351.                 /* if AttempDevUnit returns NULL then we got the lock back
  352.                  * and can break out of the loop and continue on.
  353.                  * Otherwise, someone swiped the device out from under our
  354.                  * feet in the time between our AvailDevUnit() call and our
  355.                  * AttemptDevUnit() call.
  356.                  */
  357.  
  358.                 if (AttemptDevUnit (DeviceName, DeviceUnit, "Getty", NotifyBit) == NULL)
  359.                     break;
  360.             }
  361.  
  362.             OpenSerial ();
  363.             ulog (2, "Getty Back on port");
  364.             Disconnect (1);
  365.             InitModem ();
  366.             OptionEvent = 0;
  367.         }
  368.     }
  369.  
  370.     exit (0);
  371. }
  372.  
  373. void
  374. DoOptions (int ac, char **av)
  375. {
  376.     int
  377.         i,
  378.         bi = 0,
  379.         fi = 0;
  380.     long
  381.         v;
  382.  
  383.     LogLevel = 1;
  384.  
  385.     for (i = 1; i < ac; ++i) {
  386.         char
  387.             *ptr = av [i];
  388.  
  389.         if (*ptr != '-') {
  390.             if (fi != arysize (AtFields))
  391.                 AtFields [fi++] = ptr;
  392.             else
  393.                 fprintf (stderr, "AT field overflow\n");
  394.             continue;
  395.         }
  396.         if (*++ptr)        /*  skip -    */
  397.             ++ptr;        /*  and option    */
  398.         v = atoi (ptr);
  399.         switch (ptr [-1]) {
  400.             case 'F':
  401.                 Fax = 1;
  402.                 break;
  403.             case '0':
  404.                 ZeroOption = 1;
  405.                 break;
  406.             case '7':
  407.                 Wire7 = 1;
  408.                 break;
  409.             case 'u':
  410.                 /* Added by Christian Wolf (chris@wolfhh.hanse.de) */
  411.                 UserReport = v;
  412.                 break;
  413.             case 'S':
  414.                 strcpy (DeviceName, ptr);
  415.                 break;
  416.             case 'U':
  417.                 DeviceUnit = v;
  418.                 break;
  419.             case 'M':
  420.                 ModemType = *ptr;
  421.                 break;
  422.             case 'A':
  423.                 BaudAdjust = 1;
  424.                 break;
  425.             case 'B':
  426.                 if (bi != arysize (Bauds))
  427.                     Bauds [bi++] = v;
  428.                 else
  429.                     fprintf (stderr, "-B field overflow\n");
  430.                 break;
  431.             case 'm':
  432.                 SpeakerOpt = 1;
  433.                 SpeakerLevel = v;
  434.                 break;
  435.             case 'r':
  436.                 AnswerRing = v;
  437.                 break;
  438.             case 'h':
  439.                 FIgnoreCD = !v;
  440.                 IgnoreCD = !v;
  441.                 break;
  442.             case 'c':
  443.                 IgnoreConnect = !v;
  444.                 break;
  445.             case 'd':
  446.                 IgnoreDTR = !v;
  447.                 break;
  448.             case 'x':
  449.                 LogLevel = v;
  450.                 LogToStdout = (v >= 9);
  451.                 break;
  452.             case 'n':
  453.                 /*NoBugs = 1;*/
  454.                 break;
  455.             case 'l':
  456.                 HardLink = v;
  457.                 break;
  458.             case 'b':
  459.                 BaudReport = v;
  460.                 break;
  461.             default:
  462.                 fprintf (stderr, "Warning, Bad option: -%s\n", ptr);
  463.                 break;
  464.         }
  465.     }
  466.  
  467.     if (fi && fi != arysize (AtFields))
  468.         AtFields [fi] = NULL;
  469.     if (bi && bi != arysize (Bauds))
  470.         Bauds [bi] = 0;
  471.  
  472.     return;
  473. }
  474.  
  475.  
  476. void
  477. myexit (void)
  478. {
  479.     if (IoSink) {
  480.         DeletePort (IoSink);
  481.         IoSink = NULL;
  482.     }
  483.     if (ComPort) {
  484.         DeletePort (ComPort);
  485.         ComPort = NULL;
  486.     }
  487.     if (Iot0IP) {
  488.         AbortIO ((struct IORequest *) &Iot0);
  489.         WaitIO ((struct IORequest *) &Iot0);
  490.     }
  491.     if (Iot1IP) {
  492.         AbortIO ((struct IORequest *) &Iot1);
  493.         WaitIO ((struct IORequest *) &Iot1);
  494.     }
  495.     if (Iot0.tr_node.io_Device) {
  496.         CloseDevice ((struct IORequest *) &Iot0);
  497.         Iot0.tr_node.io_Device = NULL;
  498.     }
  499.     CloseSerial ();
  500.     if (NullFH) {
  501.         Close (NullFH);
  502.         NullFH = 0;
  503.     }
  504.  
  505.     /* clean up stuff related to OwnDevUnit.library */
  506.  
  507.     if (OwnDevUnitBase) {
  508.         FreeDevUnit (DeviceName, DeviceUnit);     /* if we don't own it the */
  509.         CloseLibrary (OwnDevUnitBase);         /* lib will ignore the free */
  510.         OwnDevUnitBase = NULL;
  511.     }
  512.  
  513.     if (NotifyBit != -1) {
  514.         FreeSignal(NotifyBit);
  515.         NotifyBit = -1;
  516.     }
  517.  
  518.     return;
  519. }
  520.  
  521. void
  522. FLockSerialPort (void)
  523. {
  524.     char
  525.         *error;
  526.  
  527.     if (error = LockDevUnit (DeviceName, DeviceUnit, "Getty", NotifyBit)) {
  528.         fprintf (stderr, "Unable to lock serial port: %s\n", &error [1]);
  529.         exit (20);
  530.     }
  531.  
  532.     return;
  533. }
  534.  
  535. void
  536. FUnLockSerialPort (void)
  537. {
  538.     FreeDevUnit (DeviceName, DeviceUnit);
  539.  
  540.     return;
  541. }
  542.  
  543. void
  544. InitModem (void)
  545. {
  546.     char buf[64];
  547.     short i;
  548.  
  549.     RxStop();
  550.     ulog(2, "Init Modem");
  551.     Ios.io_Baud = BaudRate = Bauds[0];      /*  reset baud rate */
  552.     SetParams(0);
  553.  
  554.     switch(ModemType) {
  555.     case 'm':               /*  Multi Modem     */
  556.     SerPuts("\010\010\r");
  557.     Delay(10);
  558.     SerPuts("AT\r");
  559.     Delay(50);
  560.     sprintf(buf, "ATM%dS0=%dX4$BA%d&E%d\r",
  561.         SpeakerLevel,
  562.         AnswerRing,
  563.         !BaudAdjust,
  564.         (Wire7) ? 4 : 3
  565.     );
  566.     SerPuts(buf);
  567.     break;
  568.     case 'h':
  569.     SerPuts("\010\010\r");
  570.     Delay(10);
  571.     SerPuts("ATZ\r");
  572.     Delay(120);
  573.     strcpy(buf, "AT");
  574.     if (SpeakerOpt)
  575.         sprintf(buf + strlen(buf), "M%d", SpeakerLevel);
  576.     sprintf(buf + strlen(buf), "S0=%d", AnswerRing);
  577.     if (Fax)
  578.         sprintf (buf + strlen (buf), "+FCLASS=0+FCR=1+FAA=1");
  579.     strcat(buf, "\r");
  580.     SerPuts(buf);
  581.     break;
  582.     case 'd':
  583.     SerPuts("\010\010\r");
  584.     break;
  585.     }
  586.     for (i = 0; i < arysize(AtFields) && AtFields[i]; ++i) {
  587.     Delay(50);
  588.     SerPuts(AtFields[i]);
  589.     SerPuts("\r");
  590.     }
  591.     Delay(20);
  592.     ClearRecv ();
  593.     if (Fax)
  594.     RxStart ();
  595. }
  596.  
  597. #if 1
  598. void
  599. Disconnect (int dropdtr)
  600. {
  601.     short
  602.         retry = (IgnoreDTR) ? 2 : 10;
  603.  
  604.     ulog (2, "Disconnect drop = %ld", dropdtr);
  605.  
  606.     RxStop ();
  607.  
  608.     if (IgnoreCD) {
  609.         return;
  610.     }
  611.  
  612.     while (dropdtr) {
  613.         short
  614.             i;
  615.         long
  616.             status = GetStatus ();
  617.  
  618.         if (status & CIAF_COMCD)    /*  no carrier    */
  619.             break;
  620.  
  621.         SetParams (0);
  622.  
  623.         CloseDevice ((struct IORequest *) &Ios);
  624.         Ios.IOSer.io_Device = NULL;    /*  so exit doesn't reclose */
  625.         for (i = 0; i < 5; ++i) {      /*  5 seconds   */
  626.             Delay (50);
  627.             if (SetSignal (0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C)
  628.                 exit (23);
  629.         }
  630.  
  631.         /*
  632.          *  Use Iosr to re-open serial device so we don't loose
  633.          *  our config.
  634.          */
  635.  
  636.         if (Wire7)
  637.             Ios.io_SerFlags |= SERF_7WIRE;
  638.         else
  639.             Ios.io_SerFlags &= ~SERF_7WIRE;
  640.  
  641.         if (OpenDevice (DeviceName, DeviceUnit, (struct IORequest *) &Ios, 0)) {
  642.             Ios.IOSer.io_Device = NULL;
  643.             exit (22);
  644.         }
  645.         Iosr.IOSer.io_Device = Ios.IOSer.io_Device;
  646.         Iosw.IOSer.io_Device = Ios.IOSer.io_Device;
  647.         Ioss.IOSer.io_Device = Ios.IOSer.io_Device;
  648.         Iosr.IOSer.io_Unit = Ios.IOSer.io_Unit;
  649.         Iosw.IOSer.io_Unit = Ios.IOSer.io_Unit;
  650.         Ioss.IOSer.io_Unit = Ios.IOSer.io_Unit;
  651.         SetParams (1);
  652.  
  653.         status = GetStatus ();
  654.  
  655.         if (status & CIAF_COMCD)    /*  no carrier    */
  656.             break;
  657.  
  658.         if (IgnoreDTR) {
  659.             if (ModemType != 'd') {
  660.                 Delay (70);
  661.                 SerPuts ("+++");
  662.                 Delay (70);
  663.                 SerPuts ("\010\010\r");
  664.                 Delay (10);
  665.                 SerPuts ("ATZ\r");
  666.                 Delay (50*3);
  667.                 SerPuts ("ATH0\r");
  668.                 Delay (120);
  669.             }
  670.         }
  671.  
  672.         /*
  673.          *  Loop until carrier lost
  674.          */
  675.  
  676.         if (--retry == 0) {
  677.             if (IgnoreDTR == 0)
  678.                 fprintf (stderr, "Getty: unable to disconnect!\n");
  679.             break;
  680.         }
  681.     }
  682.  
  683.     return;
  684. }
  685. #else
  686. void
  687. Disconnect (int dropdtr)
  688. {
  689.     short retry = (IgnoreDTR) ? 2 : 10;
  690.  
  691.     ulog(2, "Disconnect drop=%d", dropdtr);
  692.  
  693.     RxStop();
  694.     if (IgnoreCD == 0) {
  695.     while (dropdtr) {
  696.         short i;
  697.         long status = GetStatus();
  698.  
  699.         if (status & CIAF_COMCD)        /*    no carrier  */
  700.         break;
  701.  
  702.         SetParams(0);
  703.  
  704.         if (IgnoreDTR) {
  705.         if (ModemType != 'd') {
  706.             Delay(70);
  707.             SerPuts("+++");
  708.             Delay(70);
  709.             SerPuts("\010\010\r");
  710.             Delay(10);
  711.             SerPuts("ATZ\r");
  712.             Delay(50*3);
  713.             SerPuts("ATH0\r");
  714.             Delay(120);
  715.         }
  716.         } else {
  717.         CloseDevice ((struct IORequest *) &Ios);
  718.         Ios.IOSer.io_Device = NULL;    /*  so exit doesn't reclose */
  719.         for (i = 0; i < 5; ++i) {      /*  5 seconds   */
  720.             Delay(50);
  721.             if (SetSignal (0, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C)
  722.             exit(23);
  723.         }
  724.  
  725.         /*
  726.          *  Use Iosr to re-open serial device so we don't loose
  727.          *  our config.
  728.          */
  729.  
  730.         if (Wire7)
  731.             Ios.io_SerFlags |= SERF_7WIRE;
  732.         else
  733.             Ios.io_SerFlags &= ~SERF_7WIRE;
  734.         if (OpenDevice(DeviceName, DeviceUnit, (struct IORequest *) &Ios, 0)) {
  735.             Ios.IOSer.io_Device = NULL;
  736.             exit(22);
  737.         }
  738.         Iosr.IOSer.io_Device = Ios.IOSer.io_Device;
  739.         Iosw.IOSer.io_Device = Ios.IOSer.io_Device;
  740.         Ioss.IOSer.io_Device = Ios.IOSer.io_Device;
  741.         Iosr.IOSer.io_Unit = Ios.IOSer.io_Unit;
  742.         Iosw.IOSer.io_Unit = Ios.IOSer.io_Unit;
  743.         Ioss.IOSer.io_Unit = Ios.IOSer.io_Unit;
  744.         SetParams(1);
  745.         }
  746.  
  747.         /*
  748.          *    Loop until carrier lost
  749.          */
  750.  
  751.         if (--retry == 0) {
  752.         if (IgnoreDTR == 0)
  753.             puts("Getty: unable to disconnect!");
  754.         break;
  755.         }
  756.     }
  757.     }
  758. }
  759. #endif
  760.  
  761. void
  762. WaitEvents (void)
  763. {
  764.     short event = 0;
  765.     unsigned long mask = 0;
  766.  
  767.     while (event == 0) {
  768.     {
  769.         GMsg *msg;
  770.         while (msg = (GMsg *)GetMsg(ComPort)) {
  771.         switch(msg->Cmd) {
  772.         case 'O':
  773.             DoOptions(msg->Data1, msg->Data2);
  774.             break;
  775.         }
  776.         ReplyMsg((Message *)msg);
  777.         if (ZeroOption)
  778.             exit(0);
  779.         OptionEvent = 1;
  780.         ++event;
  781.         }
  782.     }
  783.     {
  784.         IORequest *ior;
  785.         while (ior = (IORequest *)GetMsg(IoSink)) {
  786.         if (ior == (IORequest *)&Iot0) {
  787.             Iot0IP = 0;
  788.             TimeoutEvent = 1;
  789.             ++event;
  790.         }
  791.         if (ior == (IORequest *)&Iot1) {
  792.             Iot1.tr_time.tv_secs = MainTimeout;
  793.             Iot1.tr_time.tv_micro= 0;
  794.             SendIO ((struct IORequest *) &Iot1);
  795.             Iot1IP = 1;
  796.  
  797.             if (Ios.IOSer.io_Device) {
  798.             if ((GetStatus() & CIAF_COMCD) == 0)
  799.                 CarrierDetectEvent = 1;
  800.             else
  801.                 CarrierDetectEvent = 0;
  802.             }
  803.             ++event;
  804.         } else if (ior == (IORequest *)&Iosr) {
  805.             IosrIP = 0;
  806.             SerialEvent = 1;
  807.             ++event;
  808.         }
  809.         }
  810.     }
  811.  
  812.     if ((mask & NotifyMask) || SetSignal(0L, NotifyMask) == NotifyMask) {
  813.         PortRequestedEvent = 1;
  814.         ++event;
  815.     }
  816.  
  817.     if (event == 0) {
  818.         mask = Wait(SIGBREAKF_CTRL_C | IoSinkMask | ComPortMask | NotifyMask);
  819.         if (mask & SIGBREAKF_CTRL_C)
  820.         exit(0);
  821.     }
  822.     }
  823. }
  824.  
  825. void
  826. Timeout (int n)
  827. {
  828.     TimeoutEvent = 0;
  829.     if (Iot0IP) {
  830.         AbortIO ((struct IORequest *) &Iot0);
  831.         WaitIO ((struct IORequest *) &Iot0);
  832.         Iot0IP = 0;
  833.     }
  834.     if (n) {
  835.         Iot0.tr_time.tv_secs = n;
  836.         Iot0.tr_time.tv_micro= 0;
  837.         SendIO ((struct IORequest *) &Iot0);
  838.         Iot0IP = 1;
  839.     }
  840.  
  841.     return;
  842. }
  843.  
  844. void
  845. OpenSerial (void)
  846. {
  847.     Ios.IOSer.io_Message.mn_ReplyPort = IoSink;
  848.     Ios.io_SerFlags = SERF_XDISABLED | SERF_SHARED;
  849.     if (Wire7)
  850.         Ios.io_SerFlags |= SERF_7WIRE;
  851.  
  852.     if (OpenDevice (DeviceName, DeviceUnit, (struct IORequest *) &Ios, 0L)) {
  853.         Ios.IOSer.io_Device = NULL;
  854.         exit (21);
  855.     }
  856.  
  857.     Iosr = Ios;
  858.     Iosw = Ios;
  859.     Ioss = Ios;
  860.  
  861.     Iosr.IOSer.io_Command = CMD_READ;   /*    asynchronous read  */
  862.     Iosw.IOSer.io_Command = CMD_WRITE;  /*    asynchronous write */
  863.     Ios.IOSer.io_Command = SDCMD_QUERY;
  864.     DoIO ((struct IORequest *) &Ios);
  865.  
  866.     Ios.io_SerFlags = SERF_XDISABLED | SERF_RAD_BOOGIE | SERF_SHARED;
  867.     Ios.io_ExtFlags = 0;
  868.     Ios.io_Baud = Bauds [0];
  869.     Ios.io_ReadLen = 8;
  870.     Ios.io_WriteLen = 8;
  871.     Ios.io_StopBits = 1;
  872.  
  873.     SetParams (0);
  874.  
  875.     return;
  876. }
  877.  
  878. void
  879. CloseSerial (void)
  880. {
  881.     if (IosrIP) {
  882.         NiceAbortIO (&Iosr);
  883.         WaitIO ((struct IORequest *) &Iosr);
  884.         IosrIP = 0;
  885.     }
  886.     if (Ios.IOSer.io_Device) {
  887.         CloseDevice ((struct IORequest *) &Ios);
  888.         Ios.IOSer.io_Device = NULL;
  889.     }
  890.  
  891.     return;
  892. }
  893.  
  894. void
  895. SetParams (int wire7)
  896. {
  897.     int
  898.         error;
  899.  
  900.     wire7 = Wire7;
  901.  
  902.     RxStop ();
  903.  
  904.     if (wire7 && Wire7)
  905.         Ios.io_SerFlags |= SERF_7WIRE;
  906.     else
  907.         Ios.io_SerFlags &= ~SERF_7WIRE;
  908.     Ios.IOSer.io_Command = SDCMD_SETPARAMS;
  909.     Ios.IOSer.io_Message.mn_Node.ln_Type = NT_MESSAGE;
  910.     if (error = DoIO ((struct IORequest *) &Ios))
  911.         ulog (0, "SetParams Error %d", error);
  912.  
  913.     return;
  914. }
  915.  
  916. void
  917. RxStart (void)
  918. {
  919.     if (IosrIP) {
  920.         NiceAbortIO (&Iosr);
  921.         WaitIO ((struct IORequest *) &Iosr);
  922.     }
  923.     Iosr.IOSer.io_Data = (APTR) RxBuf;
  924.     Iosr.IOSer.io_Length = 1;
  925.     Iosr.IOSer.io_Message.mn_Node.ln_Type = NT_MESSAGE;
  926.     IosrIP = 1;
  927.     SendIO ((struct IORequest *) &Iosr);
  928.  
  929.     return;
  930. }
  931.  
  932. void
  933. RxStop (void)
  934. {
  935.     if (IosrIP) {
  936.         NiceAbortIO (&Iosr);
  937.         WaitIO ((struct IORequest *) &Iosr);
  938.         IosrIP = 0;
  939.     }
  940.  
  941.     return;
  942. }
  943.  
  944. void
  945. ClearRecv (void)
  946. {
  947.     int
  948.         error;
  949.  
  950.     Ioss.IOSer.io_Command = CMD_CLEAR;
  951.     Ioss.IOSer.io_Message.mn_Node.ln_Type = NT_MESSAGE;
  952.  
  953.     if (error = DoIO ((struct IORequest *) &Ioss))
  954.         ulog (0, "Clear Error %d", error);
  955.  
  956.     SerialEvent = 0;
  957.  
  958.     if (IosrIP) {
  959.         NiceAbortIO (&Iosr);
  960.         WaitIO ((struct IORequest *) &Iosr);
  961.         IosrIP = 0;
  962.         RxStart ();
  963.     }
  964.  
  965.     return;
  966. }
  967.  
  968. void
  969. ResetSP (void)
  970. {
  971.     int
  972.         error;
  973.  
  974.     Ioss.IOSer.io_Command = CMD_RESET;
  975.     Ioss.IOSer.io_Message.mn_Node.ln_Type = NT_MESSAGE;
  976.  
  977.     if (error = DoIO ((struct IORequest *) &Ioss))
  978.         ulog (0, "Reset Error %d", error);
  979.  
  980.     return;
  981. }
  982.  
  983. void
  984. SerPuts (char *str)
  985. {
  986.     int
  987.         error;
  988.  
  989.     Ioss.IOSer.io_Command = CMD_WRITE;
  990.     Ioss.IOSer.io_Data = (APTR) str;
  991.     Ioss.IOSer.io_Length = strlen (str);
  992.     Ioss.IOSer.io_Message.mn_Node.ln_Type = NT_MESSAGE;
  993.     if (error = DoIO ((struct IORequest *) &Ioss))
  994.         ulog (0, "Write Error %d", error);
  995.  
  996.     return;
  997. }
  998.  
  999. long
  1000. GetStatus (void)
  1001. {
  1002.     int
  1003.         error;
  1004.     long
  1005.         status = CIAF_COMCD;   /*  no carrier detect   */
  1006.  
  1007.     Ioss.IOSer.io_Command = SDCMD_QUERY;
  1008.     Ioss.IOSer.io_Message.mn_Node.ln_Type = NT_MESSAGE;
  1009.     if (error = DoIO ((struct IORequest *) &Ioss))
  1010.         ulog (0, "Query Error %d", error);
  1011.     status = Ioss.io_Status;
  1012.     if (IgnoreCD)
  1013.         status &= ~CIAF_COMCD;
  1014.  
  1015.     return status;
  1016. }
  1017.  
  1018. /*
  1019.  *  HANDLE LOGIN
  1020.  */
  1021.  
  1022. void
  1023. DoLogin (void)
  1024. {
  1025.     char *ptr;
  1026.     char *str;
  1027.     short retry = (IgnoreConnect) ? -1 : 5;
  1028.  
  1029.     Timeout(10);
  1030.     if (IgnoreConnect == 0) {
  1031.     while (ptr = GetLine(0)) {
  1032.         if (strnicmp(ptr, "CONNECT", 7) == 0)
  1033.         break;
  1034.         /*ulog(-1,"Received <%s>\n",ptr);*/
  1035.         if (Fax) {
  1036.         if (strnicmp(ptr, "RING", 4) == 0) {
  1037.             Timeout(20);    /* Extend timeout */
  1038.         } else if (strnicmp(ptr, "+FCO", 4) == 0) {
  1039.             BaudRate = 19200;
  1040.             Ios.io_Baud = BaudRate;
  1041.             SetParams(1);
  1042.             ClearRecv();
  1043.             RxStop();
  1044.             ulog(-1,"Fax Connection");
  1045.  
  1046.             strncpy(LoginBuf, "fax", sizeof(LoginBuf) - 1);
  1047.             PasswdBuf[0] = 0;
  1048.             if (CheckLoginAndPassword()) {
  1049.             ulog(-1, "login %s", LoginBuf);
  1050.             RunPasswdEntry();
  1051.             ulog(-1,"Fax Returned");
  1052.             } else {
  1053.             ulog(-1,"FaxConnect Disabled");
  1054.             }
  1055.             return;
  1056.         }
  1057.         }
  1058.     }
  1059.     if (ptr == NULL)
  1060.         return;
  1061.     }
  1062.  
  1063.     str = ptr + 7;
  1064.     while (*str && (*str == 9 || *str == ' '))
  1065.     ++str;
  1066.     if (*str >= '0' && *str <= '9')
  1067.     BaudRate = atoi(str);
  1068.     else
  1069.     BaudRate = Bauds[0];
  1070.  
  1071.     if (BaudAdjust) {
  1072.     ulog(9, "Connect Auto-Baud %d", BaudRate);
  1073.     } else {
  1074.     Ios.io_Baud = BaudRate;
  1075.     ulog(9, "Connect at %d baud", BaudRate);
  1076.     }
  1077.  
  1078.     SetParams(1);
  1079.  
  1080.     sleep(1);          /* GettyHeader mangled without sleep */
  1081.     IgnoreCD = FIgnoreCD; /* Not fax if get here */
  1082.  
  1083.     {
  1084.     FILE *fi;
  1085.     if (fi = fopen("Getty:Getty-Header", "r")) {
  1086.         while (fgets(ScrBuf, sizeof(ScrBuf), fi)) {
  1087.         SerPuts(ScrBuf);
  1088.         SerPuts("\r");
  1089.         };
  1090.         fclose(fi);
  1091.     }
  1092.     }
  1093.  
  1094.     if (retry < 0)
  1095.     Timeout(0);    /*  no timeout        */
  1096.     else
  1097.     Timeout(60);    /*  60 seconds        */
  1098.  
  1099.     while (retry--) {    /*  login retries   */
  1100.     char *ptr;
  1101.  
  1102.     if (retry < 0)    /*  no limit        */
  1103.         retry = -1;
  1104.     if (IgnoreConnect && PortRequestedEvent)
  1105.         break;
  1106.  
  1107.     ClearRecv();
  1108.     SerPuts("\r\nLogin: ");
  1109.     if (ptr = GetLine(1)) {
  1110.         if (ptr[0] == 0)
  1111.         continue;
  1112.         strncpy(LoginBuf, ptr, sizeof(LoginBuf) - 1);
  1113.         PasswdBuf[0] = 0;
  1114.         if (CheckLoginAndPassword() == 0) {
  1115.         SerPuts("Password: ");
  1116.         ptr = GetLine(0);
  1117.  
  1118.         if (ptr[0] == 0)
  1119.             continue;
  1120.         SerPuts("\r\n");
  1121.         strncpy(PasswdBuf, ptr, sizeof(PasswdBuf) - 1);
  1122.  
  1123.         if (CheckLoginAndPassword() == 0) {
  1124.             SerPuts("Login Failed.\r\n\n");
  1125.             ulog(0, "LoginFailed user=%s pass=%s", LoginBuf, PasswdBuf);
  1126.             Delay(50*4);
  1127.             continue;
  1128.         }
  1129.         }
  1130.         ulog(-1, "login %s", LoginBuf);
  1131.         RxStop();
  1132.         RunPasswdEntry();
  1133.     }
  1134.     break;
  1135.     }
  1136. }
  1137.  
  1138. /*
  1139.  *  Get a line, a timeout causes this call to return pronto NULL
  1140.  */
  1141.  
  1142. char *
  1143. GetLine (int echo)
  1144. {
  1145.     static char Buf[64];
  1146.     char buf[2];
  1147.     short i = 0;
  1148.     short nl = 0;
  1149.  
  1150.     RxStart();
  1151.     while (CarrierDetectEvent && TimeoutEvent == 0) {
  1152.     if (PortRequestedEvent && IgnoreConnect)
  1153.         return(NULL);
  1154.     if (SerialEvent && IosrIP == 0) {
  1155.         SerialEvent = 0;
  1156.         if (Iosr.IOSer.io_Actual) {
  1157.         unsigned char c;
  1158.         switch(c = (unsigned char )(RxBuf[0] & 0x7F)) {
  1159.         case 0x00:    /*  ignore NULs */
  1160.         case 0x7F:
  1161.         case 0xFF:
  1162.             break;
  1163.         case 13:
  1164.         case 10:
  1165.             if (nl == 0)
  1166.             nl = c;
  1167.             if (nl != c)
  1168.             break;
  1169.             if (echo)
  1170.             SerPuts("\r\n");
  1171.             Buf[i] = 0;
  1172.             return(Buf);
  1173.         case 8:
  1174.             if (i) {
  1175.             if (echo)
  1176.                 SerPuts("\010 \010");
  1177.             --i;
  1178.             }
  1179.             break;
  1180.         default:
  1181.             if (i == sizeof(Buf) - 1) {
  1182.             if (echo)
  1183.                 SerPuts("\007");
  1184.             } else {
  1185.             Buf[i++] = c;
  1186.             if (echo) {
  1187.                 buf[0] = c;
  1188.                 buf[1] = 0;
  1189.                 SerPuts(buf);
  1190.             }
  1191.             }
  1192.             break;
  1193.         }
  1194.         }
  1195.         RxStart();
  1196.     }
  1197.     WaitEvents();
  1198.     }
  1199.     return NULL;
  1200. }
  1201.  
  1202. /*
  1203.  *  bug fix for older A2232 serial.device's
  1204.  */
  1205.  
  1206. void
  1207. NiceAbortIO (void *ior)
  1208. {
  1209.     Disable ();
  1210.     if (((struct Message *) ior)->mn_Node.ln_Type != NT_REPLYMSG)
  1211.         AbortIO (ior);
  1212.     Enable ();
  1213.  
  1214.     return;
  1215. }
  1216.