ZMISC.C
资源名称:zmodem.zip [点击查看]
上传用户:haiyue
上传日期:2007-01-05
资源大小:21k
文件大小:22k
源码类别:
通讯/手机编程
开发平台:
C/C++
- /*--------------------------------------------------------------------------*/
- /* FILE: zmisc.c (Opus zmodem routines used by send and receive) */
- /* */
- /* */
- /* The Opus Computer-Based Conversation System */
- /* (c) Copyright 1986, Wynn Wagner III, All Rights Reserved */
- /* */
- /* This implementation of Chuck Forsberg's ZMODEM protocol was */
- /* for Opus by Rick Huebner and Wynn Wagner III */
- /* */
- /* (MSC/4 with /Zp /Ox) */
- /* */
- /* */
- /* */
- /* */
- /* This module is similar to a routine used by Opus-Cbcs (1.00). It is */
- /* provided for your information only. You will find routines that need */
- /* to be coded and identifiers to be resolved. */
- /* */
- /* There is absolutely no guarantee that anything here will work. If you */
- /* break this routine, you own both pieces. */
- /* */
- /* USAGE: You may use this material in any program with no obligation */
- /* as long as there is no charge for your program. For more */
- /* information about commercial use, contact the "OPUSinfo HERE" */
- /* BBS (124/111). */
- /* */
- /* NOTE: There are a couple of things the Opus implementation does that */
- /* aren't part of the original ZModem protocol. They all deal */
- /* with WaZOO type ("ZedZap") netmail and should only show up when */
- /* used under that condition. */
- /* */
- /* * The maximum packet size can grow larger than 1k. It is */
- /* sensitive to the baud rate. (2400b=2048k; 9600b=8192k) */
- /* * The sender must be able to send nothing. In other words, */
- /* the sending system must be able to initiate and terminate */
- /* a zmodem send session without having to actually send a */
- /* file. Normally this kind of thing would never happen in */
- /* zmodem. */
- /* */
- /* */
- /*--------------------------------------------------------------------------*/
- #include "zmodem.h"
- static int Rxtype; /* Type of header received */
- static int Rxframeind; /* ZBIN ZBIN32,ZHEX type of frame received */
- static char hex[] = "0123456789abcdef";
- /* Send a byte as two hex digits */
- #define Z_PUTHEX(i,c) {i=(c);SENDBYTE(hex[((i)&0xF0)>>4]);SENDBYTE(hex[(i)&0xF]);}
- /*--------------------------------------------------------------------------*/
- /* Routines used by other ZModem modules... */
- /*--------------------------------------------------------------------------*/
- int pascal Z_GetByte(int);
- void pascal Z_PutString(unsigned char *);
- void pascal Z_SendHexHeader(unsigned short,unsigned char *);
- int pascal Z_GetHeader(unsigned char *);
- int pascal Z_GetZDL(void);
- void pascal Z_PutLongIntoHeader(long);
- unsigned short pascal Z_UpdateCRC(unsigned short,unsigned short);
- /*--------------------------------------------------------------------------*/
- /* Private routines */
- /*--------------------------------------------------------------------------*/
- static int pascal _Z_qk_read(void);
- static int pascal _Z_GetBinaryHeader(unsigned char *);
- static int pascal _Z_GetHexHeader(unsigned char *);
- static int pascal _Z_GetHex(void);
- static int pascal _Z_TimedRead(void);
- static long pascal _Z_PullLongFromHeader(unsigned char *);
- extern byte *local_CEOL;
- extern char *KBD_msg;
- void pascal z_message( s )
- byte *s;
- begin
- gotoxy( locate_x+20, locate_y );
- if (s) cputs(s);
- cputs( local_CEOL );
- end
- void z_log(s)
- byte *s;
- begin
- word x, y;
- z_message(s);
- x = locate_x;
- y = locate_y;
- status_line(s); /* also does disk file logging */
- locate_x = x;
- locate_y = y;
- end
- void show_loc(l,w)
- unsigned long l;
- unsigned int w;
- begin
- gotoxy( locate_x+35, locate_y );
- cprintf("Ofs=%ld Retries=%d%s",l,w,local_CEOL);
- end
- byte * pascal zalloc()
- begin
- byte *sptr;
- sptr = malloc(WAZOOMAX);
- if (!sptr)
- begin
- status_line("!Z-MEMOVFL");
- adios(2);
- end
- return sptr;
- end
- /*--------------------------------------------------------------------------*/
- /* Z GET BYTE */
- /* Get a byte from the modem; */
- /* return TIMEOUT if no read within timeout tenths, */
- /* return RCDO if carrier lost */
- /*--------------------------------------------------------------------------*/
- int pascal Z_GetByte(tenths)
- register int tenths;
- begin
- register int i;
- i^=i;
- do
- begin
- if (CHAR_AVAIL()) return MODEM_IN();
- end
- while((i++)<2000);
- i = tenths/10;
- if (i<1) i = 1;
- if (i>58) i = 58;
- i = set_timer(i);
- while(!CHAR_AVAIL())
- begin
- if (!CARRIER) return RCDO;
- time_release();
- if (time_gone(i)) return TIMEOUT;
- end
- return MODEM_IN();
- end
- /*--------------------------------------------------------------------------*/
- /* QK_READ (like Z_GetByte, but assumes the time to be Rxtimeout) */
- /* Get a byte from the modem; */
- /* return TIMEOUT if no read within timeout tenths, */
- /* return RCDO if carrier lost */
- /*--------------------------------------------------------------------------*/
- static int pascal _Z_qk_read()
- begin
- register int i;
- register int time_val;
- time_val^=time_val;
- do
- begin
- if ((i=MODEM_STATUS())&DATA_READY) return MODEM_IN();
- if (!(i&ctl.carrier_mask)) return RCDO;
- end
- while((time_val++)<2000);
- time_val = set_timer(Rxtimeout);
- do
- begin
- if ((i=MODEM_STATUS())&DATA_READY) return MODEM_IN();
- if (!(i&ctl.carrier_mask)) return RCDO;
- time_release();
- end
- while(time_left(time_val));
- return TIMEOUT;
- end
- /*--------------------------------------------------------------------------*/
- /* Z PUT STRING */
- /* Send a string to the modem, processing for 336 (sleep 1 sec) */
- /* and 335 (break signal, ignored) */
- /*--------------------------------------------------------------------------*/
- void pascal Z_PutString(s)
- register unsigned char *s;
- begin
- register int c;
- while (*s)
- begin
- switch (c = *s++)
- begin
- case '336': big_pause(2);
- case '335': break;
- default: SENDBYTE(c);
- end /* switch */
- end /* while */
- end /* Z_PutString */
- /*--------------------------------------------------------------------------*/
- /* Z UPDATE CRC */
- /* update CRC */
- /*--------------------------------------------------------------------------*/
- unsigned short pascal Z_UpdateCRC(c, crc)
- unsigned short c;
- unsigned short crc;
- begin
- register int count;
- register word temp;
- temp = crc;
- for (count=8; --count>=0; )
- begin
- if (temp & 0x8000)
- begin
- temp <<= 1;
- temp += (((c<<=1) & 0400) != 0);
- temp ^= 0x1021;
- end
- else
- begin
- temp <<= 1;
- temp += (((c<<=1) & 0400) != 0);
- end
- end /* for */
- return temp;
- end /* z_crc update */
- /*--------------------------------------------------------------------------*/
- /* Z SEND HEX HEADER */
- /* Send ZMODEM HEX header hdr of type type */
- /*--------------------------------------------------------------------------*/
- void pascal Z_SendHexHeader(type, hdr)
- unsigned short type;
- unsigned char *hdr;
- begin
- register int n;
- register int i;
- unsigned short crc;
- SENDBYTE(ZPAD);
- SENDBYTE(ZPAD);
- SENDBYTE(ZDLE);
- SENDBYTE(ZHEX);
- Z_PUTHEX(i,type);
- crc = Z_UpdateCRC(type, 0);
- for (n=4; --n >= 0;)
- begin
- Z_PUTHEX(i,(*hdr));
- crc = Z_UpdateCRC(((unsigned short)(*hdr++)), crc);
- end
- crc = Z_UpdateCRC(0,crc);
- crc = Z_UpdateCRC(0,crc);
- Z_PUTHEX(i,(crc>>8));
- Z_PUTHEX(i,crc);
- /* Make it printable on remote machine */
- SENDBYTE('r');
- SENDBYTE('n');
- /* Uncork the remote in case a fake XOFF has stopped data flow */
- if (type != ZFIN) SENDBYTE(021);
- wait_for_clear();
- end /* Z_SendHexHeader */
- /*--------------------------------------------------------------------------*/
- /* Z GET HEADER */
- /* Read a ZMODEM header to hdr, either binary or hex. */
- /* On success, set Zmodem to 1 and return type of header. */
- /* Otherwise return negative on error */
- /*--------------------------------------------------------------------------*/
- int pascal Z_GetHeader(hdr)
- byte *hdr;
- begin
- register int c;
- register int n;
- int cancount;
- n = cur_baud; /* Max characters before start of frame */
- cancount = 5;
- Again:
- if (((KEYPRESS()) and (READKB()==27)))
- begin
- send_can();
- z_log( KBD_msg );
- return ZCAN;
- end
- Rxframeind = Rxtype = 0;
- switch (c = _Z_TimedRead())
- begin
- case ZPAD: /*-----------------------------------------------*/
- /* This is what we want. */
- /*-----------------------------------------------*/
- break;
- case RCDO:
- case TIMEOUT: /*-----------------------------------------------*/
- /* */
- /*-----------------------------------------------*/
- goto Done;
- case CAN: /*-----------------------------------------------*/
- /* */
- /*-----------------------------------------------*/
- if (--cancount <= 0)
- begin
- c = ZCAN;
- goto Done;
- end
- /* fallthrough... */
- default: /*-----------------------------------------------*/
- /* */
- /*-----------------------------------------------*/
- Agn2:
- if (--n <= 0)
- begin
- z_log( FUBAR_msg );
- send_can();
- return ZCAN;
- end
- if (c != CAN) cancount = 5;
- goto Again;
- end /* switch */
- cancount = 5;
- Splat:
- switch (c = _Z_TimedRead())
- begin
- case ZDLE: /*-----------------------------------------------*/
- /* This is what we want. */
- /*-----------------------------------------------*/
- break;
- case ZPAD: /*-----------------------------------------------*/
- /* */
- /*-----------------------------------------------*/
- goto Splat;
- case RCDO:
- case TIMEOUT: /*-----------------------------------------------*/
- /* */
- /*-----------------------------------------------*/
- goto Done;
- default: /*-----------------------------------------------*/
- /* */
- /*-----------------------------------------------*/
- goto Agn2;
- end /* switch */
- switch (c = _Z_TimedRead())
- begin
- case ZBIN: /*-----------------------------------------------*/
- /* */
- /*-----------------------------------------------*/
- Rxframeind = ZBIN;
- c = _Z_GetBinaryHeader(hdr);
- break;
- case ZHEX: /*-----------------------------------------------*/
- /* */
- /*-----------------------------------------------*/
- Rxframeind = ZHEX;
- c = _Z_GetHexHeader(hdr);
- break;
- case CAN: /*-----------------------------------------------*/
- /* */
- /*-----------------------------------------------*/
- if (--cancount <= 0)
- begin
- c = ZCAN;
- goto Done;
- end
- goto Agn2;
- case RCDO:
- case TIMEOUT: /*-----------------------------------------------*/
- /* */
- /*-----------------------------------------------*/
- goto Done;
- default: /*-----------------------------------------------*/
- /* */
- /*-----------------------------------------------*/
- goto Agn2;
- end /* switch */
- Rxpos = _Z_PullLongFromHeader(hdr);
- Done:
- return c;
- end /* Z_GetHeader */
- /*--------------------------------------------------------------------------*/
- /* Z GET BINARY HEADER */
- /* Receive a binary style header (type and position) */
- /*--------------------------------------------------------------------------*/
- static int pascal _Z_GetBinaryHeader(hdr)
- byte *hdr;
- begin
- register int c;
- register word crc;
- int n;
- if ((c = Z_GetZDL()) & ~0xFF) return c;
- Rxtype = c;
- crc = Z_UpdateCRC(c, 0);
- for (n=4; --n >= 0;)
- begin
- if ((c = Z_GetZDL()) & ~0xFF) return c;
- crc = Z_UpdateCRC(c, crc);
- *hdr++ = c;
- end
- if ((c = Z_GetZDL()) & ~0xFF) return c;
- crc = Z_UpdateCRC(c, crc);
- if ((c = Z_GetZDL()) & ~0xFF) return c;
- crc = Z_UpdateCRC(c, crc);
- if (crc & 0xFFFF)
- begin
- z_message( CRC_msg );
- return ERROR;
- end
- return Rxtype;
- end /* _Z_GetBinaryHeader */
- /*--------------------------------------------------------------------------*/
- /* Z GET HEX HEADER */
- /* Receive a hex style header (type and position) */
- /*--------------------------------------------------------------------------*/
- static int pascal _Z_GetHexHeader(hdr)
- unsigned char *hdr;
- begin
- register int c;
- register word crc;
- int n;
- if ((c = _Z_GetHex()) < 0) return c;
- Rxtype = c;
- crc = Z_UpdateCRC(c, 0);
- for (n=4; --n >= 0;)
- begin
- if ((c = _Z_GetHex()) < 0) return c;
- crc = Z_UpdateCRC(c, crc);
- *hdr++ = c;
- end
- if ((c = _Z_GetHex()) < 0) return c;
- crc = Z_UpdateCRC(c, crc);
- if ((c = _Z_GetHex()) < 0) return c;
- crc = Z_UpdateCRC(c, crc);
- if (crc & 0xFFFF)
- begin
- z_message( CRC_msg );
- return ERROR;
- end
- if (Z_GetByte(1) == 'r') Z_GetByte(1); /* Throw away possible cr/lf */
- return Rxtype;
- end
- /*--------------------------------------------------------------------------*/
- /* Z GET HEX */
- /* Decode two lower case hex digits into an 8 bit byte value */
- /*--------------------------------------------------------------------------*/
- static int pascal _Z_GetHex()
- begin
- register int c, n;
- if ((n = _Z_TimedRead()) < 0) return n;
- n -= '0';
- if (n > 9) n -= ('a' - ':');
- if (n & ~0xF) return ERROR;
- if ((c = _Z_TimedRead()) < 0) return c;
- c -= '0';
- if (c > 9) c -= ('a' - ':');
- if (c & ~0xF) return ERROR;
- return (n<<4 | c);
- end
- /*--------------------------------------------------------------------------*/
- /* Z GET ZDL */
- /* Read a byte, checking for ZMODEM escape encoding */
- /* including CAN*5 which represents a quick abort */
- /*--------------------------------------------------------------------------*/
- int pascal Z_GetZDL()
- begin
- register int c;
- if ((c = _Z_qk_read()) != ZDLE) return c;
- switch (c=_Z_qk_read())
- begin
- case CAN: return ((c=_Z_qk_read())<0)? c :
- ((c==CAN) && ((c=_Z_qk_read())<0))? c :
- ((c==CAN) && ((c=_Z_qk_read())<0))? c : (GOTCAN);
- case ZCRCE:
- case ZCRCG:
- case ZCRCQ:
- case ZCRCW: return (c | GOTOR);
- case ZRUB0: return 0x7F;
- case ZRUB1: return 0xFF;
- default: return (c<0)? c :
- ((c&0x60)==0x40)? (c ^ 0x40) : ERROR;
- end /* switch */
- end /* Z_GetZDL */
- /*--------------------------------------------------------------------------*/
- /* Z TIMED READ */
- /* Read a character from the modem line with timeout. */
- /* Eat parity, XON and XOFF characters. */
- /*--------------------------------------------------------------------------*/
- static int pascal _Z_TimedRead()
- begin
- register int c;
- for (;;)
- begin
- if ((c = _Z_qk_read()) < 0) return c;
- switch (c &= 0x7F)
- begin
- case XON:
- case XOFF: continue;
- default: return c;
- end /* switch */
- end /* for */
- end /* _Z_TimedRead */
- /*--------------------------------------------------------------------------*/
- /* Z LONG TO HEADER */
- /* Store long integer pos in Txhdr */
- /*--------------------------------------------------------------------------*/
- void pascal Z_PutLongIntoHeader(pos)
- long pos;
- begin
- Txhdr[ZP0] = pos;
- Txhdr[ZP1] = pos>>8;
- Txhdr[ZP2] = pos>>16;
- Txhdr[ZP3] = pos>>24;
- end /* Z_PutLongIntoHeader */
- /*--------------------------------------------------------------------------*/
- /* Z PULL LONG FROM HEADER */
- /* Recover a long integer from a header */
- /*--------------------------------------------------------------------------*/
- static long pascal _Z_PullLongFromHeader(hdr)
- unsigned char *hdr;
- begin
- long l;
- l = hdr[ZP3];
- l = (l << 8) | hdr[ZP2];
- l = (l << 8) | hdr[ZP1];
- l = (l << 8) | hdr[ZP0];
- return l;
- end /* _Z_PullLongFromHeader */
- /* END OF FILE: n_zmodem.c */