home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / mmdf / mmdf-IIb.43 / lib / dial / d_port.c < prev    next >
Encoding:
C/C++ Source or Header  |  1986-05-21  |  9.2 KB  |  411 lines

  1. # include  "util.h"
  2. # include  "d_proto.h"
  3. # include  "d_returns.h"
  4. # include <signal.h>
  5. # include  "d_syscodes.h"
  6. # include  <stdio.h>
  7. # include  "d_structs.h"
  8.  
  9. /*  Jun 81    D. Crocker    Major reworking of alarm usage, trying to
  10.  *                          deal with fact that there may be multiple
  11.  *                          calls to d_rdport trying to get one good packet
  12.  *                          d_rdport fixed to handle 8th bit on
  13.  *                          Converted some d_dbglogs to d_log
  14.  *  Jul 81    D. Crocker    Skip initial non-hex text on line.
  15.  *
  16.  *  Sep 83    M. Laubach    added procedure d_waitprompt to interface
  17.  *                          to HP and IBM software prompting
  18.  *
  19.  *  Mar 84    D. Rockwell   Added select call to d_wrtport, removed alarm
  20.  */
  21.  
  22. extern int  d_errno, errno;
  23. extern  int     d_prompt;         /* prompt char from script            */
  24. LOCVAR  unsigned d_alrmtim;        /* time to wait for i/o to complete   */
  25.  
  26.  
  27. d_alarm (thetime)
  28.     unsigned thetime;
  29. {
  30.     d_alrmtim = thetime;
  31. }
  32.  
  33.  
  34. /*
  35.  *
  36.  *     D_RDPORT
  37.  *
  38.  *     this routine is called to read a packet from the port.  the packets
  39.  *     are checked for length errors, bad checksums, and to make sure that
  40.  *     we aren't receiving packets that we have sent ourselves.
  41.  *
  42.  *     packet -- place to load te incoming packet.  should be large enough to
  43.  *               contain a packet one character longer than the maximum.  the
  44.  *               newline is replaced by a null.
  45.  *
  46.  *     returns the length of the incoming packet, minus the newline.
  47.  *
  48.  *     D_FATAL -- fatal error from read call
  49.  *
  50.  *     D_NONFATAL -- eof from port
  51.  */
  52.  
  53. d_rdport (packet)
  54. char   *packet;
  55. {
  56.     extern  FILE * d_prtfp;
  57.     extern int  d_master,
  58.         d_rcvseq;
  59.     int     flags,
  60.         seqnum;
  61.     register char  *op;
  62.     register int    count;
  63.     register int   c;
  64.  
  65.     if (d_alrmtim == 0)
  66.     {
  67. #ifdef D_LOG
  68.     d_log("d_rdport", "*** no more alarm time left");
  69. #endif D_LOG
  70.     d_errno = D_TIMEOUT;
  71.     return(D_INTRPT);
  72.     }
  73.  
  74.     if (setjmp (timerest)) {
  75. #ifdef D_LOG
  76.     d_log("d_rdport", "read alarm");
  77. #endif D_LOG
  78.     d_errno = D_TIMEOUT;
  79.     return(D_INTRPT);
  80.     }
  81.     for (s_alarm (d_alrmtim); ; )
  82.     {                             /* get valid packet                   */
  83.     for (op = packet, count = 0; count <= MAXPACKET + 1; )
  84.     {                         /* get a line                         */
  85.         if ((c = d_getc (d_prtfp)) == EOF)
  86.         {                     /* truly an end of file?              */
  87.         if (ferror (d_prtfp))
  88.         {
  89.             d_alrmtim = s_alarm (0);
  90.             if (errno == EINTR)
  91.             {
  92. #ifdef D_LOG
  93.             d_log("d_rdport", "read alarm");
  94. #endif D_LOG
  95.             d_errno = D_TIMEOUT;
  96.             return(D_INTRPT);
  97.             }
  98. #ifdef V4_2BSD
  99.         /*
  100.          * This is a special for 4.2 systems -- a bug in
  101.          * the tty driver causes EWOULDBLOCK to be returned
  102.          * instead of an EOF on the tty.  So, we fake it.
  103.          * The messages are distinguishable.
  104.          */
  105.             else if (errno == EWOULDBLOCK)
  106.             {
  107. #ifdef D_LOG
  108.             d_log("d_rdport", "port read EOF");
  109. #endif D_LOG
  110.             d_errno = D_PORTEOF;
  111.             return(D_NONFATAL);
  112.             }
  113. #endif V4_2BSD
  114.             else
  115.             {
  116. #ifdef D_LOG
  117.             d_log("d_rdport",
  118.                 "port read errno %d", errno);
  119. #endif D_LOG
  120.             d_errno = D_PORTRD;
  121.             return(D_FATAL);
  122.             }
  123.         }
  124.         if (feof (d_prtfp))
  125.         {
  126.             d_alrmtim = s_alarm (0);
  127. #ifdef D_LOG
  128.             d_log("d_rdport", "port read eof");
  129. #endif D_LOG
  130.             d_errno = D_PORTEOF;
  131.             return(D_NONFATAL);
  132.         }
  133.         }
  134.  
  135.         c = toascii (c);      /* make sure high bit is off          */
  136.         switch (c)
  137.         {
  138.         case NULL:        /* nulls are simply skipped           */
  139.         case '\r':        /* carriage returns are skipped       */
  140.         case '\177':      /* DELs  are simply skipped           */
  141.             continue;
  142.  
  143.         case '\n':        /* end of line => end of packet       */
  144.             d_tscribe (packet, count);
  145.             d_tscribe ("\n", 1);
  146.             *op = '\0';
  147.             break;
  148.  
  149.         default:          /* add to packet buffer               */
  150.             if (op == packet && !isxdigit (c)) {
  151. #ifdef D_DBGLOG
  152.             d_dbglog ("d_rdport", "noise '%c'", c);
  153. #endif D_DBGLOG
  154.             } else {       /* packets begin with hex digits      */
  155.             *op++ = c;
  156.             count++;
  157.             }
  158.             continue;
  159.         }
  160.  
  161.         if (count <= MAXPACKET + 1)
  162.         break;            /*  so far, so good, now check form   */
  163.  
  164. #ifdef D_LOG
  165.         d_log ("d_rdport", "rcv too long (%dc) '%s'",
  166.             count, packet);
  167. #endif D_LOG
  168.         d_tscribe (packet, count);
  169.     }
  170.  
  171.  
  172. /*  make sure that the packet is at least as long as the shortest one.  */
  173. /*  this is done to make sure that when we use fixed offsets for the    */
  174. /*  fields that we're not reading junk.  check the checksum.            */
  175.  
  176.     if (count < MINPACKET)
  177.     {
  178. #ifdef D_LOG
  179.         if (count > 0)  /* ignore blank lines */
  180.             d_log ("d_rdport", "rcv len err (%d)", count);
  181. #endif D_LOG
  182.         continue;
  183.     }
  184.  
  185.     if (d_cscheck (packet, count) == D_NO)
  186.     {
  187. #ifdef D_LOG
  188.         d_log ("d_rdport", "rcv checksum err '%s'", packet);
  189. #endif D_LOG
  190.         continue;
  191.     }
  192.  
  193. /*  make sure that we didn't send it.  the other guy may not have echo off  */
  194.  
  195.     flags = d_fromhex (packet[FLAGOFF]);
  196.  
  197.     if ((((flags & MASTERBIT) && d_master) ||
  198.             ((flags & MASTERBIT) == 0) && (d_master == 0)))
  199.     {
  200. #ifdef D_LOG
  201.         d_log ("d_rdport", "rcv from self");
  202. #endif D_LOG
  203.         continue;
  204.     }
  205.  
  206. /*  acknowledge the packet  */
  207.  
  208.     d_alrmtim = s_alarm (0);  /* ackpack uses the alarm clock */
  209.  
  210.     seqnum = flags & 03;
  211.  
  212. #ifdef D_DBGLOG
  213.     d_dbglog ("d_rdport", "Received packet '%s'", packet);
  214. #endif D_DBGLOG
  215.  
  216.     switch (d_ackpack (packet[TYPEOFF], seqnum))
  217.     {
  218.         case D_FATAL:
  219.         return (D_FATAL);
  220.  
  221.         case D_NONFATAL:
  222.         s_alarm (d_alrmtim);
  223.         continue;
  224.  
  225.         default:
  226.         return (count);
  227.     }
  228.     }
  229. }
  230.  
  231.  
  232.  
  233.  
  234. /*
  235.  *
  236.  *     D_WAITPROMPT
  237.  *
  238.  *     this routine is called to wait for a prompt character from the 
  239.  *     port.  If prompt is not received within a receive timeout period 
  240.  *     then fall through.  Do not return an error. 
  241.  *
  242.  */
  243.  
  244. d_waitprompt ()
  245. {
  246.     extern  FILE * d_prtfp;
  247.     register int   c;
  248.     int promptalrm = 10;       /* timeout delay in seconds */
  249.     char  ch;
  250.  
  251.     if (d_prompt == 0) return(0); 
  252.  
  253.     for (alarm (promptalrm); ; )
  254.     { 
  255.         if ((c = d_getc (d_prtfp)) == EOF)
  256.         {                     /* truly an end of file?              */
  257.         if (ferror (d_prtfp))
  258.         {
  259.             d_alrmtim = alarm (0);
  260.             if (errno == EINTR)
  261.             {
  262.                     if (d_prompt == toascii(c)) return(0);
  263. #ifdef D_LOG
  264.                         d_log("d_waitprompt","prompt alarm for %d",d_prompt);
  265. #endif D_LOG
  266.                         d_errno = D_TIMEOUT;
  267.             return(D_INTRPT);
  268.             }
  269.             else
  270.             {
  271. #ifdef D_LOG
  272.             d_log("d_waitprompt","port read errno %d", errno);
  273. #endif D_LOG
  274.             d_errno = D_PORTRD;
  275.             return(D_FATAL);
  276.             }
  277.         }
  278.         if (feof (d_prtfp))
  279.         {
  280.             d_alrmtim = alarm (0);
  281. #ifdef D_LOG
  282.             d_log("d_waitprompt", "port read eof");
  283. #endif D_LOG
  284.             d_errno = D_PORTEOF;
  285.             return(D_NONFATAL);
  286.         }
  287.         }
  288.  
  289.             ch = toascii(c);
  290.             c  = toascii(c);
  291.             d_tscribe((char *) &ch, 1);   /* put chars into transcript log    */
  292.             if (d_prompt == c) {          /* hoo-rah, break out the champaign */
  293.               promptalrm = alarm(0);      /* cancel alarm                     */
  294.               return(D_OK);
  295.             }
  296.     }
  297. }
  298.  
  299.  
  300. /* */
  301.  
  302. /*
  303.  *     D_WRTPORT
  304.  *
  305.  *     this routine writes a packet on the port.
  306.  *
  307.  *     text -- pointer to packet to be sent.  must have line terminator
  308.  *             already attached.
  309.  *
  310.  *     length -- number of bytes in text
  311.  *
  312.  *     timeout -- number of seconds to wait for write to complete
  313.  *
  314.  *
  315.  *     return values:
  316.  *
  317.  *     OK -- no errors
  318.  *
  319.  *     D_FATAL -- fatal error writing on port
  320.  *
  321.  *     D_NONFATAL -- incomplete packet written on port.  usually means disconnect.
  322.  *
  323.  *     INTERRUPT -- write timer went off
  324.  */
  325.  
  326. d_wrtport (text, length)
  327. register char  *text;
  328. register int    length;
  329. {
  330.     extern  FILE * d_prtfp;
  331.     register int    result;
  332.  
  333.     d_tscribe (text, length);
  334.  
  335.     /*
  336.      *  Added for prompt wait.  Always wait before sending packet
  337.      *  9/28/83   laubach@udel-relay
  338.      */
  339.     if (d_prompt != 0) d_waitprompt();
  340.  
  341.     /*  Set up an alarm so we won't hang
  342.      *  indefintiely if something goes wrong
  343.      */
  344.     if (setjmp (timerest)) {
  345.     d_errno = D_TIMEOUT;
  346. #ifdef D_LOG
  347.     d_log ("d_wrtport", "write alarm");
  348. #endif D_LOG
  349.     return (D_INTRPT);
  350.     }
  351.     s_alarm (XMITWAIT);
  352.  
  353.     result = write (fileno (d_prtfp), text, length);
  354.     s_alarm (0);
  355.  
  356.     if (result == length)
  357.     return (D_OK);
  358.  
  359.     if (result >= 0)
  360.     {
  361.     d_errno = D_PORTEOF;
  362.     return (D_NONFATAL);
  363.     }
  364.  
  365.     if (errno == EINTR) {
  366.     d_errno = D_TIMEOUT;
  367. #ifdef D_LOG
  368.     d_log ("d_wrtport", "write alarm");
  369. #endif D_LOG
  370.     return (D_INTRPT);
  371.     }
  372.  
  373.     d_errno = D_PORTWRT;
  374.     return (D_FATAL);
  375. }
  376.  
  377. /*
  378.  *      D_BRKPORT
  379.  *
  380.  *      This routine does its best to cause a BREAK on the line.
  381.  *
  382.  */
  383.  
  384. d_brkport()
  385. {
  386. #ifdef V4_2BSD
  387. #include <sys/ioctl.h>
  388.     ioctl (fileno (d_prtfp), TIOCSBRK, 0);
  389.     sleep ((unsigned) 1);
  390.     ioctl (fileno (d_prtfp), TIOCCBRK, 0);
  391. #else
  392.  
  393. #ifdef SYS5
  394. #include <termio.h>
  395.     ioctl (fileno(d_prtfp), TCSBRK, 0);
  396. #else
  397. #include <sgtty.h>
  398.     struct sgttyb ttybuf;
  399.     int spdsave;
  400.  
  401.     ioctl (fileno (d_prtfp), TIOCGETP, &ttybuf);
  402.     spdsave = ttybuf.sg_ospeed;
  403.     ttybuf.sg_ospeed = B150;
  404.     ioctl (fileno (d_prtfp), TIOCSETP, &ttybuf);
  405.     d_wrtport("\0\0\0\0\0", 5);
  406.     ttybuf.sg_ospeed = spdsave;
  407.     ioctl (fileno (d_prtfp), TIOCSETP, &ttybuf);
  408. #endif SYS5
  409. #endif V4_2BSD
  410. }
  411.