ZMISC.C
上传用户:haiyue
上传日期:2007-01-05
资源大小:21k
文件大小:22k
源码类别:

通讯/手机编程

开发平台:

C/C++

  1. /*--------------------------------------------------------------------------*/
  2. /* FILE: zmisc.c    (Opus zmodem routines used by send and receive)         */
  3. /*                                                                          */
  4. /*                                                                          */
  5. /*               The Opus Computer-Based Conversation System                */
  6. /*       (c) Copyright 1986, Wynn Wagner III, All Rights Reserved           */
  7. /*                                                                          */
  8. /*      This implementation of Chuck Forsberg's ZMODEM protocol was         */
  9. /*              for Opus by Rick Huebner and Wynn Wagner III                */
  10. /*                                                                          */
  11. /* (MSC/4 with /Zp /Ox)                                                     */
  12. /*                                                                          */
  13. /*                                                                          */
  14. /*                                                                          */
  15. /*                                                                          */
  16. /*  This module is similar to a routine used by Opus-Cbcs (1.00).  It is    */
  17. /*  provided for your information only.  You will find routines that need   */
  18. /*  to be coded and identifiers to be resolved.                             */
  19. /*                                                                          */
  20. /*  There is absolutely no guarantee that anything here will work.  If you  */
  21. /*  break this routine, you own both pieces.                                */
  22. /*                                                                          */
  23. /*  USAGE:  You may use this material in any program with no obligation     */
  24. /*          as long as there is no charge for your program.  For more       */
  25. /*          information about commercial use, contact the "OPUSinfo HERE"   */
  26. /*          BBS (124/111).                                                  */
  27. /*                                                                          */
  28. /*  NOTE:   There are a couple of things the Opus implementation does that  */
  29. /*          aren't part of the original ZModem protocol.  They all deal     */
  30. /*          with WaZOO type ("ZedZap") netmail and should only show up when */
  31. /*          used under that condition.                                      */
  32. /*                                                                          */
  33. /*             * The maximum packet size can grow larger than 1k.  It is    */
  34. /*               sensitive to the baud rate.  (2400b=2048k; 9600b=8192k)    */
  35. /*             * The sender must be able to send nothing.  In other words,  */
  36. /*               the sending system must be able to initiate and terminate  */
  37. /*               a zmodem send session without having to actually send a    */
  38. /*               file.  Normally this kind of thing would never happen in   */
  39. /*               zmodem.                                                    */
  40. /*                                                                          */
  41. /*                                                                          */
  42. /*--------------------------------------------------------------------------*/
  43. #include "zmodem.h"
  44. static int Rxtype;               /* Type of header received                 */
  45. static int Rxframeind;           /* ZBIN ZBIN32,ZHEX type of frame received */
  46. static char hex[] = "0123456789abcdef";
  47. /* Send a byte as two hex digits */
  48. #define Z_PUTHEX(i,c) {i=(c);SENDBYTE(hex[((i)&0xF0)>>4]);SENDBYTE(hex[(i)&0xF]);}
  49. /*--------------------------------------------------------------------------*/
  50. /* Routines used by other ZModem modules...                                 */
  51. /*--------------------------------------------------------------------------*/
  52. int  pascal Z_GetByte(int);
  53. void pascal Z_PutString(unsigned char *);
  54. void pascal Z_SendHexHeader(unsigned short,unsigned char *);
  55. int  pascal Z_GetHeader(unsigned char *);
  56. int  pascal Z_GetZDL(void);
  57. void pascal Z_PutLongIntoHeader(long);
  58. unsigned short pascal Z_UpdateCRC(unsigned short,unsigned short);
  59. /*--------------------------------------------------------------------------*/
  60. /* Private routines                                                         */
  61. /*--------------------------------------------------------------------------*/
  62. static int  pascal _Z_qk_read(void);
  63. static int  pascal _Z_GetBinaryHeader(unsigned char *);
  64. static int  pascal _Z_GetHexHeader(unsigned char *);
  65. static int  pascal _Z_GetHex(void);
  66. static int  pascal _Z_TimedRead(void);
  67. static long pascal _Z_PullLongFromHeader(unsigned char *);
  68. extern byte *local_CEOL;
  69. extern char *KBD_msg;
  70. void pascal z_message( s )
  71.    byte *s;
  72.    begin
  73.     gotoxy( locate_x+20, locate_y );
  74.       if (s) cputs(s);
  75.       cputs( local_CEOL );
  76.    end
  77. void z_log(s)
  78.    byte *s;
  79.    begin
  80.       word x, y;
  81.       z_message(s);
  82.       x  = locate_x;
  83.       y  = locate_y;
  84.       status_line(s); /* also does disk file logging */
  85.       locate_x = x;
  86.       locate_y = y;
  87.    end
  88. void show_loc(l,w)
  89.    unsigned long  l;
  90.    unsigned int   w;
  91.    begin
  92.       gotoxy( locate_x+35, locate_y );
  93.       cprintf("Ofs=%ld Retries=%d%s",l,w,local_CEOL);
  94.    end
  95. byte * pascal zalloc()
  96.    begin
  97.       byte *sptr;
  98.       sptr  = malloc(WAZOOMAX);
  99.       if (!sptr)
  100.          begin
  101.           status_line("!Z-MEMOVFL");
  102.             adios(2);
  103.          end
  104.       return sptr;
  105.    end
  106. /*--------------------------------------------------------------------------*/
  107. /* Z GET BYTE                                                               */
  108. /* Get a byte from the modem;                                               */
  109. /* return TIMEOUT if no read within timeout tenths,                         */
  110. /* return RCDO if carrier lost                                              */
  111. /*--------------------------------------------------------------------------*/
  112. int pascal Z_GetByte(tenths)
  113.    register int tenths;
  114.    begin
  115.       register int i;
  116.       i^=i;
  117.       do
  118.        begin
  119.             if (CHAR_AVAIL()) return MODEM_IN();
  120.          end
  121.       while((i++)<2000);
  122.       i   = tenths/10;
  123.       if (i<1)   i =  1;
  124.       if (i>58)  i = 58;
  125.       i = set_timer(i);
  126.       while(!CHAR_AVAIL())
  127.          begin
  128.             if (!CARRIER)     return RCDO;
  129.             time_release();
  130.             if (time_gone(i)) return TIMEOUT;
  131.          end
  132.       return MODEM_IN();
  133.    end
  134. /*--------------------------------------------------------------------------*/
  135. /* QK_READ  (like Z_GetByte, but assumes the time to be Rxtimeout)          */
  136. /* Get a byte from the modem;                                               */
  137. /* return TIMEOUT if no read within timeout tenths,                         */
  138. /* return RCDO if carrier lost                                              */
  139. /*--------------------------------------------------------------------------*/
  140. static int pascal _Z_qk_read()
  141.    begin
  142.       register int i;
  143.       register int time_val;
  144.       time_val^=time_val;
  145.       do
  146.        begin
  147.             if ((i=MODEM_STATUS())&DATA_READY)  return MODEM_IN();
  148.             if (!(i&ctl.carrier_mask))          return RCDO;
  149.          end
  150.       while((time_val++)<2000);
  151.       time_val = set_timer(Rxtimeout);
  152.       do
  153.          begin
  154.             if ((i=MODEM_STATUS())&DATA_READY)  return MODEM_IN();
  155.             if (!(i&ctl.carrier_mask))          return RCDO;
  156.             time_release();
  157.          end
  158.       while(time_left(time_val));
  159.       return TIMEOUT;
  160.    end
  161. /*--------------------------------------------------------------------------*/
  162. /* Z PUT STRING                                                             */
  163. /* Send a string to the modem, processing for 336 (sleep 1 sec)            */
  164. /* and 335 (break signal, ignored)                                         */
  165. /*--------------------------------------------------------------------------*/
  166. void pascal Z_PutString(s)
  167.    register unsigned char *s;
  168.    begin
  169.       register int c;
  170.       while (*s)
  171.          begin
  172.             switch (c = *s++)
  173.                begin
  174.                   case '336':   big_pause(2);
  175.                   case '335':   break;
  176.                   default:       SENDBYTE(c);
  177.                end /* switch */
  178.          end /* while */
  179.    end /* Z_PutString */
  180. /*--------------------------------------------------------------------------*/
  181. /* Z UPDATE CRC                                                             */
  182. /* update CRC                                                               */
  183. /*--------------------------------------------------------------------------*/
  184. unsigned short pascal Z_UpdateCRC(c, crc)
  185.    unsigned short c;
  186.    unsigned short crc;
  187.    begin
  188.       register int    count;
  189.       register word   temp;
  190.       temp   = crc;
  191.       for (count=8; --count>=0; )
  192.          begin
  193.             if (temp & 0x8000)
  194.                begin
  195.                   temp <<= 1;
  196.                   temp += (((c<<=1) & 0400)  !=  0);
  197.                   temp ^= 0x1021;
  198.                end
  199.             else
  200.                begin
  201.                   temp <<= 1;
  202.                   temp += (((c<<=1) & 0400)  !=  0);
  203.                end
  204.          end /* for */
  205.       return temp;
  206.    end /* z_crc update */
  207. /*--------------------------------------------------------------------------*/
  208. /* Z SEND HEX HEADER                                                        */
  209. /* Send ZMODEM HEX header hdr of type type                                  */
  210. /*--------------------------------------------------------------------------*/
  211. void pascal Z_SendHexHeader(type, hdr)
  212.    unsigned short type;
  213.    unsigned char *hdr;
  214.    begin
  215.       register int   n;
  216.       register int   i;
  217.       unsigned short crc;
  218.       SENDBYTE(ZPAD);
  219.       SENDBYTE(ZPAD);
  220.       SENDBYTE(ZDLE);
  221.       SENDBYTE(ZHEX);
  222.       Z_PUTHEX(i,type);
  223.       crc = Z_UpdateCRC(type, 0);
  224.       for (n=4; --n >= 0;)
  225.          begin
  226.             Z_PUTHEX(i,(*hdr));
  227.             crc = Z_UpdateCRC(((unsigned short)(*hdr++)), crc);
  228.          end
  229.       crc = Z_UpdateCRC(0,crc);
  230.       crc = Z_UpdateCRC(0,crc);
  231.       Z_PUTHEX(i,(crc>>8));
  232.       Z_PUTHEX(i,crc);
  233.       /* Make it printable on remote machine */
  234.       SENDBYTE('r');
  235.       SENDBYTE('n');
  236.       /* Uncork the remote in case a fake XOFF has stopped data flow */
  237.       if (type != ZFIN) SENDBYTE(021);
  238.       wait_for_clear();
  239.    end /* Z_SendHexHeader */
  240. /*--------------------------------------------------------------------------*/
  241. /* Z GET HEADER                                                             */
  242. /* Read a ZMODEM header to hdr, either binary or hex.                       */
  243. /*   On success, set Zmodem to 1 and return type of header.                 */
  244. /*   Otherwise return negative on error                                     */
  245. /*--------------------------------------------------------------------------*/
  246. int pascal Z_GetHeader(hdr)
  247.    byte *hdr;
  248.    begin
  249.       register int   c;
  250.       register int   n;
  251.       int            cancount;
  252.       n        = cur_baud;   /* Max characters before start of frame */
  253.       cancount = 5;
  254. Again:
  255.       if (((KEYPRESS()) and (READKB()==27)))
  256.          begin
  257.             send_can();
  258.             z_log( KBD_msg );
  259.             return ZCAN;
  260.          end
  261.       Rxframeind = Rxtype = 0;
  262.       switch (c = _Z_TimedRead())
  263.          begin
  264.             case ZPAD:     /*-----------------------------------------------*/
  265.                            /* This is what we want.                         */
  266.                            /*-----------------------------------------------*/
  267.                            break;
  268.             case RCDO:
  269.             case TIMEOUT:  /*-----------------------------------------------*/
  270.                            /*                                               */
  271.                            /*-----------------------------------------------*/
  272.                            goto Done;
  273.             case CAN:      /*-----------------------------------------------*/
  274.                            /*                                               */
  275.                            /*-----------------------------------------------*/
  276.                            if (--cancount <= 0)
  277.                               begin
  278.                                  c = ZCAN;
  279.                                  goto Done;
  280.                               end
  281.                            /* fallthrough... */
  282.             default:       /*-----------------------------------------------*/
  283.                            /*                                               */
  284.                            /*-----------------------------------------------*/
  285. Agn2:
  286.                            if (--n <= 0)
  287.                               begin
  288.                                  z_log( FUBAR_msg );
  289.                                  send_can();
  290.                                  return ZCAN;
  291.                               end
  292.                            if (c != CAN) cancount = 5;
  293.                            goto Again;
  294.          end /* switch */
  295.       cancount = 5;
  296. Splat:
  297.       switch (c = _Z_TimedRead())
  298.          begin
  299.             case ZDLE:     /*-----------------------------------------------*/
  300.                            /* This is what we want.                         */
  301.                            /*-----------------------------------------------*/
  302.                            break;
  303.             case ZPAD:     /*-----------------------------------------------*/
  304.                            /*                                               */
  305.                            /*-----------------------------------------------*/
  306.                            goto Splat;
  307.             case RCDO:
  308.             case TIMEOUT:  /*-----------------------------------------------*/
  309.                            /*                                               */
  310.                            /*-----------------------------------------------*/
  311.                            goto Done;
  312.             default:       /*-----------------------------------------------*/
  313.                            /*                                               */
  314.                            /*-----------------------------------------------*/
  315.                            goto Agn2;
  316.          end /* switch */
  317.       switch (c = _Z_TimedRead())
  318.          begin
  319.             case ZBIN:     /*-----------------------------------------------*/
  320.                            /*                                               */
  321.                            /*-----------------------------------------------*/
  322.                            Rxframeind = ZBIN;
  323.                            c =  _Z_GetBinaryHeader(hdr);
  324.                            break;
  325.             case ZHEX:     /*-----------------------------------------------*/
  326.                            /*                                               */
  327.                            /*-----------------------------------------------*/
  328.                            Rxframeind = ZHEX;
  329.                            c =  _Z_GetHexHeader(hdr);
  330.                            break;
  331.             case CAN:      /*-----------------------------------------------*/
  332.                            /*                                               */
  333.                            /*-----------------------------------------------*/
  334.                            if (--cancount <= 0)
  335.                               begin
  336.                                  c = ZCAN;
  337.                                  goto Done;
  338.                               end
  339.                            goto Agn2;
  340.             case RCDO:
  341.             case TIMEOUT:  /*-----------------------------------------------*/
  342.                            /*                                               */
  343.                            /*-----------------------------------------------*/
  344.                            goto Done;
  345.             default:       /*-----------------------------------------------*/
  346.                            /*                                               */
  347.                            /*-----------------------------------------------*/
  348.                            goto Agn2;
  349.          end /* switch */
  350.       Rxpos = _Z_PullLongFromHeader(hdr);
  351. Done:
  352.       return c;
  353.    end /* Z_GetHeader */
  354. /*--------------------------------------------------------------------------*/
  355. /* Z GET BINARY HEADER                                                      */
  356. /* Receive a binary style header (type and position)                        */
  357. /*--------------------------------------------------------------------------*/
  358. static int pascal _Z_GetBinaryHeader(hdr)
  359.    byte *hdr;
  360.    begin
  361.       register int    c;
  362.       register word   crc;
  363.       int             n;
  364.       if ((c   = Z_GetZDL()) & ~0xFF)   return c;
  365.       Rxtype   = c;
  366.       crc      = Z_UpdateCRC(c, 0);
  367.       for (n=4; --n >= 0;)
  368.          begin
  369.             if ((c = Z_GetZDL()) & ~0xFF) return c;
  370.             crc = Z_UpdateCRC(c, crc);
  371.             *hdr++ = c;
  372.          end
  373.       if ((c   = Z_GetZDL()) & ~0xFF) return c;
  374.       crc      = Z_UpdateCRC(c, crc);
  375.       if ((c   = Z_GetZDL()) & ~0xFF) return c;
  376.       crc = Z_UpdateCRC(c, crc);
  377.       if (crc & 0xFFFF)
  378.          begin
  379.             z_message( CRC_msg );
  380.             return ERROR;
  381.          end
  382.       return Rxtype;
  383.    end /* _Z_GetBinaryHeader */
  384. /*--------------------------------------------------------------------------*/
  385. /* Z GET HEX HEADER                                                         */
  386. /* Receive a hex style header (type and position)                           */
  387. /*--------------------------------------------------------------------------*/
  388. static int pascal _Z_GetHexHeader(hdr)
  389.    unsigned char *hdr;
  390.    begin
  391.       register int   c;
  392.       register word  crc;
  393.       int            n;
  394.       if ((c   = _Z_GetHex()) < 0) return c;
  395.       Rxtype   = c;
  396.       crc      = Z_UpdateCRC(c, 0);
  397.       for (n=4; --n >= 0;)
  398.          begin
  399.             if ((c = _Z_GetHex()) < 0) return c;
  400.             crc      = Z_UpdateCRC(c, crc);
  401.             *hdr++   = c;
  402.          end
  403.       if ((c = _Z_GetHex()) < 0) return c;
  404.       crc = Z_UpdateCRC(c, crc);
  405.       if ((c = _Z_GetHex()) < 0) return c;
  406.       crc = Z_UpdateCRC(c, crc);
  407.       if (crc & 0xFFFF)
  408.          begin
  409.             z_message( CRC_msg );
  410.             return ERROR;
  411.          end
  412.       if (Z_GetByte(1) == 'r') Z_GetByte(1);  /* Throw away possible cr/lf */
  413.       return Rxtype;
  414.    end
  415. /*--------------------------------------------------------------------------*/
  416. /* Z GET HEX                                                                */
  417. /* Decode two lower case hex digits into an 8 bit byte value                */
  418. /*--------------------------------------------------------------------------*/
  419. static int pascal _Z_GetHex()
  420.    begin
  421.       register int c, n;
  422.       if ((n = _Z_TimedRead()) < 0) return n;
  423.       n -= '0';
  424.       if (n > 9) n -= ('a' - ':');
  425.       if (n & ~0xF) return ERROR;
  426.       if ((c = _Z_TimedRead()) < 0) return c;
  427.       c -= '0';
  428.       if (c > 9) c -= ('a' - ':');
  429.       if (c & ~0xF) return ERROR;
  430.       return (n<<4 | c);
  431.    end
  432. /*--------------------------------------------------------------------------*/
  433. /* Z GET ZDL                                                                */
  434. /* Read a byte, checking for ZMODEM escape encoding                         */
  435. /* including CAN*5 which represents a quick abort                           */
  436. /*--------------------------------------------------------------------------*/
  437. int pascal Z_GetZDL()
  438.    begin
  439.       register int c;
  440.       if ((c = _Z_qk_read()) != ZDLE)         return c;
  441.       switch (c=_Z_qk_read())
  442.          begin
  443.             case CAN:   return ((c=_Z_qk_read())<0)?               c :
  444.                                ((c==CAN) && ((c=_Z_qk_read())<0))? c :
  445.                                ((c==CAN) && ((c=_Z_qk_read())<0))? c : (GOTCAN);
  446.             case ZCRCE:
  447.             case ZCRCG:
  448.             case ZCRCQ:
  449.             case ZCRCW: return (c | GOTOR);
  450.             case ZRUB0: return 0x7F;
  451.             case ZRUB1: return 0xFF;
  452.             default:    return   (c<0)?            c :
  453.                                  ((c&0x60)==0x40)? (c ^ 0x40)  : ERROR;
  454.          end /* switch */
  455.    end /* Z_GetZDL */
  456. /*--------------------------------------------------------------------------*/
  457. /* Z TIMED READ                                                             */
  458. /* Read a character from the modem line with timeout.                       */
  459. /*  Eat parity, XON and XOFF characters.                                    */
  460. /*--------------------------------------------------------------------------*/
  461. static int pascal _Z_TimedRead()
  462.    begin
  463.       register int c;
  464.       for (;;)
  465.          begin
  466.             if ((c = _Z_qk_read()) < 0) return c;
  467.             switch (c &= 0x7F)
  468.                begin
  469.                   case XON:
  470.                   case XOFF:  continue;
  471.                   default:    return c;
  472.                end /* switch */
  473.          end /* for */
  474.    end /* _Z_TimedRead */
  475. /*--------------------------------------------------------------------------*/
  476. /* Z LONG TO HEADER                                                         */
  477. /* Store long integer pos in Txhdr                                          */
  478. /*--------------------------------------------------------------------------*/
  479. void pascal Z_PutLongIntoHeader(pos)
  480.    long pos;
  481.    begin
  482.       Txhdr[ZP0] = pos;
  483.       Txhdr[ZP1] = pos>>8;
  484.       Txhdr[ZP2] = pos>>16;
  485.       Txhdr[ZP3] = pos>>24;
  486.    end /* Z_PutLongIntoHeader */
  487. /*--------------------------------------------------------------------------*/
  488. /* Z PULL LONG FROM HEADER                                                  */
  489. /* Recover a long integer from a header                                     */
  490. /*--------------------------------------------------------------------------*/
  491. static long pascal _Z_PullLongFromHeader(hdr)
  492.    unsigned char *hdr;
  493.    begin
  494.       long l;
  495.       l = hdr[ZP3];
  496.       l = (l << 8) | hdr[ZP2];
  497.       l = (l << 8) | hdr[ZP1];
  498.       l = (l << 8) | hdr[ZP0];
  499.       return l;
  500.    end /* _Z_PullLongFromHeader */
  501. /* END OF FILE: n_zmodem.c */