1*433d6423SLionel Sambuc /*
2*433d6423SLionel Sambuc * Z M . C
3*433d6423SLionel Sambuc * ZMODEM protocol primitives
4*433d6423SLionel Sambuc * 05-09-88 Chuck Forsberg Omen Technology Inc
5*433d6423SLionel Sambuc *
6*433d6423SLionel Sambuc * Entry point Functions:
7*433d6423SLionel Sambuc * zsbhdr(type, hdr) send binary header
8*433d6423SLionel Sambuc * zshhdr(type, hdr) send hex header
9*433d6423SLionel Sambuc * zgethdr(hdr, eflag) receive header - binary or hex
10*433d6423SLionel Sambuc * zsdata(buf, len, frameend) send data
11*433d6423SLionel Sambuc * zrdata(buf, len) receive data
12*433d6423SLionel Sambuc * stohdr(pos) store position data in Txhdr
13*433d6423SLionel Sambuc * long rclhdr(hdr) recover position offset from header
14*433d6423SLionel Sambuc */
15*433d6423SLionel Sambuc
16*433d6423SLionel Sambuc #ifndef CANFDX
17*433d6423SLionel Sambuc #include "zmodem.h"
18*433d6423SLionel Sambuc #endif
19*433d6423SLionel Sambuc int Rxtimeout = 100; /* Tenths of seconds to wait for something */
20*433d6423SLionel Sambuc
21*433d6423SLionel Sambuc #ifndef UNSL
22*433d6423SLionel Sambuc #define UNSL
23*433d6423SLionel Sambuc #endif
24*433d6423SLionel Sambuc
25*433d6423SLionel Sambuc
26*433d6423SLionel Sambuc /* Globals used by ZMODEM functions */
27*433d6423SLionel Sambuc int Rxframeind; /* ZBIN ZBIN32, or ZHEX type of frame received */
28*433d6423SLionel Sambuc int Rxtype; /* Type of header received */
29*433d6423SLionel Sambuc int Rxcount; /* Count of data bytes received */
30*433d6423SLionel Sambuc char Rxhdr[4]; /* Received header */
31*433d6423SLionel Sambuc char Txhdr[4]; /* Transmitted header */
32*433d6423SLionel Sambuc long Rxpos; /* Received file position */
33*433d6423SLionel Sambuc long Txpos; /* Transmitted file position */
34*433d6423SLionel Sambuc int Txfcs32; /* TURE means send binary frames with 32 bit FCS */
35*433d6423SLionel Sambuc int Crc32t; /* Display flag indicating 32 bit CRC being sent */
36*433d6423SLionel Sambuc int Crc32; /* Display flag indicating 32 bit CRC being received */
37*433d6423SLionel Sambuc int Znulls; /* Number of nulls to send at beginning of ZDATA hdr */
38*433d6423SLionel Sambuc char Attn[ZATTNLEN+1]; /* Attention string rx sends to tx on err */
39*433d6423SLionel Sambuc
40*433d6423SLionel Sambuc static int lastsent; /* Last char we sent */
41*433d6423SLionel Sambuc static int Not8bit; /* Seven bits seen on header */
42*433d6423SLionel Sambuc
43*433d6423SLionel Sambuc static char *frametypes[] = {
44*433d6423SLionel Sambuc "Carrier Lost", /* -3 */
45*433d6423SLionel Sambuc "TIMEOUT", /* -2 */
46*433d6423SLionel Sambuc "ERROR", /* -1 */
47*433d6423SLionel Sambuc #define FTOFFSET 3
48*433d6423SLionel Sambuc "ZRQINIT",
49*433d6423SLionel Sambuc "ZRINIT",
50*433d6423SLionel Sambuc "ZSINIT",
51*433d6423SLionel Sambuc "ZACK",
52*433d6423SLionel Sambuc "ZFILE",
53*433d6423SLionel Sambuc "ZSKIP",
54*433d6423SLionel Sambuc "ZNAK",
55*433d6423SLionel Sambuc "ZABORT",
56*433d6423SLionel Sambuc "ZFIN",
57*433d6423SLionel Sambuc "ZRPOS",
58*433d6423SLionel Sambuc "ZDATA",
59*433d6423SLionel Sambuc "ZEOF",
60*433d6423SLionel Sambuc "ZFERR",
61*433d6423SLionel Sambuc "ZCRC",
62*433d6423SLionel Sambuc "ZCHALLENGE",
63*433d6423SLionel Sambuc "ZCOMPL",
64*433d6423SLionel Sambuc "ZCAN",
65*433d6423SLionel Sambuc "ZFREECNT",
66*433d6423SLionel Sambuc "ZCOMMAND",
67*433d6423SLionel Sambuc "ZSTDERR",
68*433d6423SLionel Sambuc "xxxxx"
69*433d6423SLionel Sambuc #define FRTYPES 22 /* Total number of frame types in this array */
70*433d6423SLionel Sambuc /* not including psuedo negative entries */
71*433d6423SLionel Sambuc };
72*433d6423SLionel Sambuc
73*433d6423SLionel Sambuc static char badcrc[] = "Bad CRC";
74*433d6423SLionel Sambuc
75*433d6423SLionel Sambuc /* Send ZMODEM binary header hdr of type type */
zsbhdr(int type,char * hdr)76*433d6423SLionel Sambuc void zsbhdr(int type, char *hdr)
77*433d6423SLionel Sambuc {
78*433d6423SLionel Sambuc register int n;
79*433d6423SLionel Sambuc register unsigned short crc;
80*433d6423SLionel Sambuc
81*433d6423SLionel Sambuc vfile("zsbhdr: %s %lx", frametypes[type+FTOFFSET], rclhdr(hdr));
82*433d6423SLionel Sambuc if (type == ZDATA)
83*433d6423SLionel Sambuc for (n = Znulls; --n >=0; )
84*433d6423SLionel Sambuc xsendline(0);
85*433d6423SLionel Sambuc
86*433d6423SLionel Sambuc xsendline(ZPAD); xsendline(ZDLE);
87*433d6423SLionel Sambuc
88*433d6423SLionel Sambuc if ((Crc32t=Txfcs32))
89*433d6423SLionel Sambuc zsbh32(hdr, type);
90*433d6423SLionel Sambuc else {
91*433d6423SLionel Sambuc xsendline(ZBIN); zsendline(type); crc = updcrc(type, 0);
92*433d6423SLionel Sambuc
93*433d6423SLionel Sambuc for (n=4; --n >= 0; ++hdr) {
94*433d6423SLionel Sambuc zsendline(*hdr);
95*433d6423SLionel Sambuc crc = updcrc((0377& *hdr), crc);
96*433d6423SLionel Sambuc }
97*433d6423SLionel Sambuc crc = updcrc(0,updcrc(0,crc));
98*433d6423SLionel Sambuc zsendline(crc>>8);
99*433d6423SLionel Sambuc zsendline(crc);
100*433d6423SLionel Sambuc }
101*433d6423SLionel Sambuc if (type != ZDATA)
102*433d6423SLionel Sambuc flushmo();
103*433d6423SLionel Sambuc }
104*433d6423SLionel Sambuc
105*433d6423SLionel Sambuc
106*433d6423SLionel Sambuc /* Send ZMODEM binary header hdr of type type */
zsbh32(char * hdr,int type)107*433d6423SLionel Sambuc void zsbh32(char *hdr, int type)
108*433d6423SLionel Sambuc {
109*433d6423SLionel Sambuc register int n;
110*433d6423SLionel Sambuc register UNSL long crc;
111*433d6423SLionel Sambuc
112*433d6423SLionel Sambuc xsendline(ZBIN32); zsendline(type);
113*433d6423SLionel Sambuc crc = 0xFFFFFFFFL; crc = UPDC32(type, crc);
114*433d6423SLionel Sambuc
115*433d6423SLionel Sambuc for (n=4; --n >= 0; ++hdr) {
116*433d6423SLionel Sambuc crc = UPDC32((0377 & *hdr), crc);
117*433d6423SLionel Sambuc zsendline(*hdr);
118*433d6423SLionel Sambuc }
119*433d6423SLionel Sambuc crc = ~crc;
120*433d6423SLionel Sambuc for (n=4; --n >= 0;) {
121*433d6423SLionel Sambuc zsendline((int)crc);
122*433d6423SLionel Sambuc crc >>= 8;
123*433d6423SLionel Sambuc }
124*433d6423SLionel Sambuc }
125*433d6423SLionel Sambuc
126*433d6423SLionel Sambuc /* Send ZMODEM HEX header hdr of type type */
zshhdr(int type,char * hdr)127*433d6423SLionel Sambuc void zshhdr(int type, char *hdr)
128*433d6423SLionel Sambuc {
129*433d6423SLionel Sambuc register int n;
130*433d6423SLionel Sambuc register unsigned short crc;
131*433d6423SLionel Sambuc
132*433d6423SLionel Sambuc vfile("zshhdr: %s %lx", frametypes[type+FTOFFSET], rclhdr(hdr));
133*433d6423SLionel Sambuc sendline(ZPAD); sendline(ZPAD); sendline(ZDLE); sendline(ZHEX);
134*433d6423SLionel Sambuc zputhex(type);
135*433d6423SLionel Sambuc Crc32t = 0;
136*433d6423SLionel Sambuc
137*433d6423SLionel Sambuc crc = updcrc(type, 0);
138*433d6423SLionel Sambuc for (n=4; --n >= 0; ++hdr) {
139*433d6423SLionel Sambuc zputhex(*hdr); crc = updcrc((0377 & *hdr), crc);
140*433d6423SLionel Sambuc }
141*433d6423SLionel Sambuc crc = updcrc(0,updcrc(0,crc));
142*433d6423SLionel Sambuc zputhex(crc>>8); zputhex(crc);
143*433d6423SLionel Sambuc
144*433d6423SLionel Sambuc /* Make it printable on remote machine */
145*433d6423SLionel Sambuc sendline(015); sendline(0212);
146*433d6423SLionel Sambuc /*
147*433d6423SLionel Sambuc * Uncork the remote in case a fake XOFF has stopped data flow
148*433d6423SLionel Sambuc */
149*433d6423SLionel Sambuc if (type != ZFIN && type != ZACK)
150*433d6423SLionel Sambuc sendline(021);
151*433d6423SLionel Sambuc flushmo();
152*433d6423SLionel Sambuc }
153*433d6423SLionel Sambuc
154*433d6423SLionel Sambuc /*
155*433d6423SLionel Sambuc * Send binary array buf of length length, with ending ZDLE sequence frameend
156*433d6423SLionel Sambuc */
157*433d6423SLionel Sambuc static char *Zendnames[] = { "ZCRCE", "ZCRCG", "ZCRCQ", "ZCRCW"};
158*433d6423SLionel Sambuc
zsdata(char * buf,int length,int frameend)159*433d6423SLionel Sambuc void zsdata(char *buf, int length, int frameend)
160*433d6423SLionel Sambuc {
161*433d6423SLionel Sambuc register unsigned short crc;
162*433d6423SLionel Sambuc
163*433d6423SLionel Sambuc vfile("zsdata: %d %s", length, Zendnames[(frameend-ZCRCE)&3]);
164*433d6423SLionel Sambuc if (Crc32t)
165*433d6423SLionel Sambuc zsda32(buf, length, frameend);
166*433d6423SLionel Sambuc else {
167*433d6423SLionel Sambuc crc = 0;
168*433d6423SLionel Sambuc for (;--length >= 0; ++buf) {
169*433d6423SLionel Sambuc zsendline(*buf); crc = updcrc((0377 & *buf), crc);
170*433d6423SLionel Sambuc }
171*433d6423SLionel Sambuc xsendline(ZDLE); xsendline(frameend);
172*433d6423SLionel Sambuc crc = updcrc(frameend, crc);
173*433d6423SLionel Sambuc
174*433d6423SLionel Sambuc crc = updcrc(0,updcrc(0,crc));
175*433d6423SLionel Sambuc zsendline(crc>>8); zsendline(crc);
176*433d6423SLionel Sambuc }
177*433d6423SLionel Sambuc if (frameend == ZCRCW) {
178*433d6423SLionel Sambuc xsendline(XON); flushmo();
179*433d6423SLionel Sambuc }
180*433d6423SLionel Sambuc }
181*433d6423SLionel Sambuc
zsda32(char * buf,int length,int frameend)182*433d6423SLionel Sambuc void zsda32(char *buf, int length, int frameend)
183*433d6423SLionel Sambuc {
184*433d6423SLionel Sambuc register int c;
185*433d6423SLionel Sambuc register UNSL long crc;
186*433d6423SLionel Sambuc
187*433d6423SLionel Sambuc crc = 0xFFFFFFFFL;
188*433d6423SLionel Sambuc for (;--length >= 0; ++buf) {
189*433d6423SLionel Sambuc c = *buf & 0377;
190*433d6423SLionel Sambuc if (c & 0140)
191*433d6423SLionel Sambuc xsendline(lastsent = c);
192*433d6423SLionel Sambuc else
193*433d6423SLionel Sambuc zsendline(c);
194*433d6423SLionel Sambuc crc = UPDC32(c, crc);
195*433d6423SLionel Sambuc }
196*433d6423SLionel Sambuc xsendline(ZDLE); xsendline(frameend);
197*433d6423SLionel Sambuc crc = UPDC32(frameend, crc);
198*433d6423SLionel Sambuc
199*433d6423SLionel Sambuc crc = ~crc;
200*433d6423SLionel Sambuc for (length=4; --length >= 0;) {
201*433d6423SLionel Sambuc zsendline((int)crc); crc >>= 8;
202*433d6423SLionel Sambuc }
203*433d6423SLionel Sambuc }
204*433d6423SLionel Sambuc
205*433d6423SLionel Sambuc /*
206*433d6423SLionel Sambuc * Receive array buf of max length with ending ZDLE sequence
207*433d6423SLionel Sambuc * and CRC. Returns the ending character or error code.
208*433d6423SLionel Sambuc * NB: On errors may store length+1 bytes!
209*433d6423SLionel Sambuc */
zrdata(char * buf,int length)210*433d6423SLionel Sambuc int zrdata(char *buf, int length)
211*433d6423SLionel Sambuc {
212*433d6423SLionel Sambuc register int c;
213*433d6423SLionel Sambuc register unsigned short crc;
214*433d6423SLionel Sambuc register char *end;
215*433d6423SLionel Sambuc register int d;
216*433d6423SLionel Sambuc
217*433d6423SLionel Sambuc if (Rxframeind == ZBIN32)
218*433d6423SLionel Sambuc return zrdat32(buf, length);
219*433d6423SLionel Sambuc
220*433d6423SLionel Sambuc crc = Rxcount = 0; end = buf + length;
221*433d6423SLionel Sambuc while (buf <= end) {
222*433d6423SLionel Sambuc if ((c = zdlread()) & ~0377) {
223*433d6423SLionel Sambuc crcfoo:
224*433d6423SLionel Sambuc switch (c) {
225*433d6423SLionel Sambuc case GOTCRCE:
226*433d6423SLionel Sambuc case GOTCRCG:
227*433d6423SLionel Sambuc case GOTCRCQ:
228*433d6423SLionel Sambuc case GOTCRCW:
229*433d6423SLionel Sambuc crc = updcrc((((d=c))&0377), crc);
230*433d6423SLionel Sambuc if ((c = zdlread()) & ~0377)
231*433d6423SLionel Sambuc goto crcfoo;
232*433d6423SLionel Sambuc crc = updcrc(c, crc);
233*433d6423SLionel Sambuc if ((c = zdlread()) & ~0377)
234*433d6423SLionel Sambuc goto crcfoo;
235*433d6423SLionel Sambuc crc = updcrc(c, crc);
236*433d6423SLionel Sambuc if (crc & 0xFFFF) {
237*433d6423SLionel Sambuc zperr(badcrc);
238*433d6423SLionel Sambuc return ERROR;
239*433d6423SLionel Sambuc }
240*433d6423SLionel Sambuc Rxcount = length - (end - buf);
241*433d6423SLionel Sambuc vfile("zrdata: %d %s", Rxcount,
242*433d6423SLionel Sambuc Zendnames[(d-GOTCRCE)&3]);
243*433d6423SLionel Sambuc return d;
244*433d6423SLionel Sambuc case GOTCAN:
245*433d6423SLionel Sambuc zperr("Sender Canceled");
246*433d6423SLionel Sambuc return ZCAN;
247*433d6423SLionel Sambuc case TIMEOUT:
248*433d6423SLionel Sambuc zperr("TIMEOUT");
249*433d6423SLionel Sambuc return c;
250*433d6423SLionel Sambuc default:
251*433d6423SLionel Sambuc zperr("Bad data subpacket");
252*433d6423SLionel Sambuc return c;
253*433d6423SLionel Sambuc }
254*433d6423SLionel Sambuc }
255*433d6423SLionel Sambuc *buf++ = c;
256*433d6423SLionel Sambuc crc = updcrc(c, crc);
257*433d6423SLionel Sambuc }
258*433d6423SLionel Sambuc zperr("Data subpacket too long");
259*433d6423SLionel Sambuc return ERROR;
260*433d6423SLionel Sambuc }
261*433d6423SLionel Sambuc
zrdat32(char * buf,int length)262*433d6423SLionel Sambuc int zrdat32(char *buf, int length)
263*433d6423SLionel Sambuc {
264*433d6423SLionel Sambuc register int c;
265*433d6423SLionel Sambuc register UNSL long crc;
266*433d6423SLionel Sambuc register char *end;
267*433d6423SLionel Sambuc register int d;
268*433d6423SLionel Sambuc
269*433d6423SLionel Sambuc crc = 0xFFFFFFFFL; Rxcount = 0; end = buf + length;
270*433d6423SLionel Sambuc while (buf <= end) {
271*433d6423SLionel Sambuc if ((c = zdlread()) & ~0377) {
272*433d6423SLionel Sambuc crcfoo:
273*433d6423SLionel Sambuc switch (c) {
274*433d6423SLionel Sambuc case GOTCRCE:
275*433d6423SLionel Sambuc case GOTCRCG:
276*433d6423SLionel Sambuc case GOTCRCQ:
277*433d6423SLionel Sambuc case GOTCRCW:
278*433d6423SLionel Sambuc d = c; c &= 0377;
279*433d6423SLionel Sambuc crc = UPDC32(c, crc);
280*433d6423SLionel Sambuc if ((c = zdlread()) & ~0377)
281*433d6423SLionel Sambuc goto crcfoo;
282*433d6423SLionel Sambuc crc = UPDC32(c, crc);
283*433d6423SLionel Sambuc if ((c = zdlread()) & ~0377)
284*433d6423SLionel Sambuc goto crcfoo;
285*433d6423SLionel Sambuc crc = UPDC32(c, crc);
286*433d6423SLionel Sambuc if ((c = zdlread()) & ~0377)
287*433d6423SLionel Sambuc goto crcfoo;
288*433d6423SLionel Sambuc crc = UPDC32(c, crc);
289*433d6423SLionel Sambuc if ((c = zdlread()) & ~0377)
290*433d6423SLionel Sambuc goto crcfoo;
291*433d6423SLionel Sambuc crc = UPDC32(c, crc);
292*433d6423SLionel Sambuc if (crc != 0xDEBB20E3) {
293*433d6423SLionel Sambuc zperr(badcrc);
294*433d6423SLionel Sambuc return ERROR;
295*433d6423SLionel Sambuc }
296*433d6423SLionel Sambuc Rxcount = length - (end - buf);
297*433d6423SLionel Sambuc vfile("zrdat32: %d %s", Rxcount,
298*433d6423SLionel Sambuc Zendnames[(d-GOTCRCE)&3]);
299*433d6423SLionel Sambuc return d;
300*433d6423SLionel Sambuc case GOTCAN:
301*433d6423SLionel Sambuc zperr("Sender Canceled");
302*433d6423SLionel Sambuc return ZCAN;
303*433d6423SLionel Sambuc case TIMEOUT:
304*433d6423SLionel Sambuc zperr("TIMEOUT");
305*433d6423SLionel Sambuc return c;
306*433d6423SLionel Sambuc default:
307*433d6423SLionel Sambuc zperr("Bad data subpacket");
308*433d6423SLionel Sambuc return c;
309*433d6423SLionel Sambuc }
310*433d6423SLionel Sambuc }
311*433d6423SLionel Sambuc *buf++ = c;
312*433d6423SLionel Sambuc crc = UPDC32(c, crc);
313*433d6423SLionel Sambuc }
314*433d6423SLionel Sambuc zperr("Data subpacket too long");
315*433d6423SLionel Sambuc return ERROR;
316*433d6423SLionel Sambuc }
317*433d6423SLionel Sambuc
318*433d6423SLionel Sambuc
319*433d6423SLionel Sambuc /*
320*433d6423SLionel Sambuc * Read a ZMODEM header to hdr, either binary or hex.
321*433d6423SLionel Sambuc * eflag controls local display of non zmodem characters:
322*433d6423SLionel Sambuc * 0: no display
323*433d6423SLionel Sambuc * 1: display printing characters only
324*433d6423SLionel Sambuc * 2: display all non ZMODEM characters
325*433d6423SLionel Sambuc * On success, set Zmodem to 1, set Rxpos and return type of header.
326*433d6423SLionel Sambuc * Otherwise return negative on error.
327*433d6423SLionel Sambuc * Return ERROR instantly if ZCRCW sequence, for fast error recovery.
328*433d6423SLionel Sambuc */
zgethdr(char * hdr,int eflag)329*433d6423SLionel Sambuc int zgethdr(char *hdr, int eflag)
330*433d6423SLionel Sambuc {
331*433d6423SLionel Sambuc register int c, n, cancount;
332*433d6423SLionel Sambuc
333*433d6423SLionel Sambuc n = Zrwindow + Baudrate; /* Max bytes before start of frame */
334*433d6423SLionel Sambuc Rxframeind = Rxtype = 0;
335*433d6423SLionel Sambuc
336*433d6423SLionel Sambuc startover:
337*433d6423SLionel Sambuc cancount = 5;
338*433d6423SLionel Sambuc again:
339*433d6423SLionel Sambuc /* Return immediate ERROR if ZCRCW sequence seen */
340*433d6423SLionel Sambuc switch (c = readline(Rxtimeout)) {
341*433d6423SLionel Sambuc case RCDO:
342*433d6423SLionel Sambuc case TIMEOUT:
343*433d6423SLionel Sambuc goto fifi;
344*433d6423SLionel Sambuc case CAN:
345*433d6423SLionel Sambuc gotcan:
346*433d6423SLionel Sambuc if (--cancount <= 0) {
347*433d6423SLionel Sambuc c = ZCAN; goto fifi;
348*433d6423SLionel Sambuc }
349*433d6423SLionel Sambuc switch (c = readline(1)) {
350*433d6423SLionel Sambuc case TIMEOUT:
351*433d6423SLionel Sambuc goto again;
352*433d6423SLionel Sambuc case ZCRCW:
353*433d6423SLionel Sambuc c = ERROR;
354*433d6423SLionel Sambuc /* **** FALL THRU TO **** */
355*433d6423SLionel Sambuc case RCDO:
356*433d6423SLionel Sambuc goto fifi;
357*433d6423SLionel Sambuc default:
358*433d6423SLionel Sambuc break;
359*433d6423SLionel Sambuc case CAN:
360*433d6423SLionel Sambuc if (--cancount <= 0) {
361*433d6423SLionel Sambuc c = ZCAN; goto fifi;
362*433d6423SLionel Sambuc }
363*433d6423SLionel Sambuc goto again;
364*433d6423SLionel Sambuc }
365*433d6423SLionel Sambuc /* **** FALL THRU TO **** */
366*433d6423SLionel Sambuc default:
367*433d6423SLionel Sambuc agn2:
368*433d6423SLionel Sambuc if ( --n == 0) {
369*433d6423SLionel Sambuc zperr("Garbage count exceeded");
370*433d6423SLionel Sambuc return(ERROR);
371*433d6423SLionel Sambuc }
372*433d6423SLionel Sambuc if (eflag && ((c &= 0177) & 0140))
373*433d6423SLionel Sambuc bttyout(c);
374*433d6423SLionel Sambuc else if (eflag > 1)
375*433d6423SLionel Sambuc bttyout(c);
376*433d6423SLionel Sambuc #ifdef UNIX
377*433d6423SLionel Sambuc fflush(stderr);
378*433d6423SLionel Sambuc #endif
379*433d6423SLionel Sambuc goto startover;
380*433d6423SLionel Sambuc case ZPAD|0200: /* This is what we want. */
381*433d6423SLionel Sambuc Not8bit = c;
382*433d6423SLionel Sambuc case ZPAD: /* This is what we want. */
383*433d6423SLionel Sambuc break;
384*433d6423SLionel Sambuc }
385*433d6423SLionel Sambuc cancount = 5;
386*433d6423SLionel Sambuc splat:
387*433d6423SLionel Sambuc switch (c = noxrd7()) {
388*433d6423SLionel Sambuc case ZPAD:
389*433d6423SLionel Sambuc goto splat;
390*433d6423SLionel Sambuc case RCDO:
391*433d6423SLionel Sambuc case TIMEOUT:
392*433d6423SLionel Sambuc goto fifi;
393*433d6423SLionel Sambuc default:
394*433d6423SLionel Sambuc goto agn2;
395*433d6423SLionel Sambuc case ZDLE: /* This is what we want. */
396*433d6423SLionel Sambuc break;
397*433d6423SLionel Sambuc }
398*433d6423SLionel Sambuc
399*433d6423SLionel Sambuc switch (c = noxrd7()) {
400*433d6423SLionel Sambuc case RCDO:
401*433d6423SLionel Sambuc case TIMEOUT:
402*433d6423SLionel Sambuc goto fifi;
403*433d6423SLionel Sambuc case ZBIN:
404*433d6423SLionel Sambuc Rxframeind = ZBIN; Crc32 = FALSE;
405*433d6423SLionel Sambuc c = zrbhdr(hdr);
406*433d6423SLionel Sambuc break;
407*433d6423SLionel Sambuc case ZBIN32:
408*433d6423SLionel Sambuc Crc32 = Rxframeind = ZBIN32;
409*433d6423SLionel Sambuc c = zrbhdr32(hdr);
410*433d6423SLionel Sambuc break;
411*433d6423SLionel Sambuc case ZHEX:
412*433d6423SLionel Sambuc Rxframeind = ZHEX; Crc32 = FALSE;
413*433d6423SLionel Sambuc c = zrhhdr(hdr);
414*433d6423SLionel Sambuc break;
415*433d6423SLionel Sambuc case CAN:
416*433d6423SLionel Sambuc goto gotcan;
417*433d6423SLionel Sambuc default:
418*433d6423SLionel Sambuc goto agn2;
419*433d6423SLionel Sambuc }
420*433d6423SLionel Sambuc Rxpos = hdr[ZP3] & 0377;
421*433d6423SLionel Sambuc Rxpos = (Rxpos<<8) + (hdr[ZP2] & 0377);
422*433d6423SLionel Sambuc Rxpos = (Rxpos<<8) + (hdr[ZP1] & 0377);
423*433d6423SLionel Sambuc Rxpos = (Rxpos<<8) + (hdr[ZP0] & 0377);
424*433d6423SLionel Sambuc fifi:
425*433d6423SLionel Sambuc switch (c) {
426*433d6423SLionel Sambuc case GOTCAN:
427*433d6423SLionel Sambuc c = ZCAN;
428*433d6423SLionel Sambuc /* **** FALL THRU TO **** */
429*433d6423SLionel Sambuc case ZNAK:
430*433d6423SLionel Sambuc case ZCAN:
431*433d6423SLionel Sambuc case ERROR:
432*433d6423SLionel Sambuc case TIMEOUT:
433*433d6423SLionel Sambuc case RCDO:
434*433d6423SLionel Sambuc zperr("Got %s", frametypes[c+FTOFFSET]);
435*433d6423SLionel Sambuc /* **** FALL THRU TO **** */
436*433d6423SLionel Sambuc default:
437*433d6423SLionel Sambuc if (c >= -3 && c <= FRTYPES)
438*433d6423SLionel Sambuc vfile("zgethdr: %s %lx", frametypes[c+FTOFFSET], Rxpos);
439*433d6423SLionel Sambuc else
440*433d6423SLionel Sambuc vfile("zgethdr: %d %lx", c, Rxpos);
441*433d6423SLionel Sambuc }
442*433d6423SLionel Sambuc return c;
443*433d6423SLionel Sambuc }
444*433d6423SLionel Sambuc
445*433d6423SLionel Sambuc /* Receive a binary style header (type and position) */
zrbhdr(char * hdr)446*433d6423SLionel Sambuc int zrbhdr(char *hdr)
447*433d6423SLionel Sambuc {
448*433d6423SLionel Sambuc register int c, n;
449*433d6423SLionel Sambuc register unsigned short crc;
450*433d6423SLionel Sambuc
451*433d6423SLionel Sambuc if ((c = zdlread()) & ~0377)
452*433d6423SLionel Sambuc return c;
453*433d6423SLionel Sambuc Rxtype = c;
454*433d6423SLionel Sambuc crc = updcrc(c, 0);
455*433d6423SLionel Sambuc
456*433d6423SLionel Sambuc for (n=4; --n >= 0; ++hdr) {
457*433d6423SLionel Sambuc if ((c = zdlread()) & ~0377)
458*433d6423SLionel Sambuc return c;
459*433d6423SLionel Sambuc crc = updcrc(c, crc);
460*433d6423SLionel Sambuc *hdr = c;
461*433d6423SLionel Sambuc }
462*433d6423SLionel Sambuc if ((c = zdlread()) & ~0377)
463*433d6423SLionel Sambuc return c;
464*433d6423SLionel Sambuc crc = updcrc(c, crc);
465*433d6423SLionel Sambuc if ((c = zdlread()) & ~0377)
466*433d6423SLionel Sambuc return c;
467*433d6423SLionel Sambuc crc = updcrc(c, crc);
468*433d6423SLionel Sambuc if (crc & 0xFFFF) {
469*433d6423SLionel Sambuc zperr(badcrc);
470*433d6423SLionel Sambuc return ERROR;
471*433d6423SLionel Sambuc }
472*433d6423SLionel Sambuc #ifdef ZMODEM
473*433d6423SLionel Sambuc Protocol = ZMODEM;
474*433d6423SLionel Sambuc #endif
475*433d6423SLionel Sambuc Zmodem = 1;
476*433d6423SLionel Sambuc return Rxtype;
477*433d6423SLionel Sambuc }
478*433d6423SLionel Sambuc
479*433d6423SLionel Sambuc /* Receive a binary style header (type and position) with 32 bit FCS */
zrbhdr32(char * hdr)480*433d6423SLionel Sambuc int zrbhdr32(char *hdr)
481*433d6423SLionel Sambuc {
482*433d6423SLionel Sambuc register int c, n;
483*433d6423SLionel Sambuc register UNSL long crc;
484*433d6423SLionel Sambuc
485*433d6423SLionel Sambuc if ((c = zdlread()) & ~0377)
486*433d6423SLionel Sambuc return c;
487*433d6423SLionel Sambuc Rxtype = c;
488*433d6423SLionel Sambuc crc = 0xFFFFFFFFL; crc = UPDC32(c, crc);
489*433d6423SLionel Sambuc #ifdef DEBUGZ
490*433d6423SLionel Sambuc vfile("zrbhdr32 c=%X crc=%lX", c, crc);
491*433d6423SLionel Sambuc #endif
492*433d6423SLionel Sambuc
493*433d6423SLionel Sambuc for (n=4; --n >= 0; ++hdr) {
494*433d6423SLionel Sambuc if ((c = zdlread()) & ~0377)
495*433d6423SLionel Sambuc return c;
496*433d6423SLionel Sambuc crc = UPDC32(c, crc);
497*433d6423SLionel Sambuc *hdr = c;
498*433d6423SLionel Sambuc #ifdef DEBUGZ
499*433d6423SLionel Sambuc vfile("zrbhdr32 c=%X crc=%lX", c, crc);
500*433d6423SLionel Sambuc #endif
501*433d6423SLionel Sambuc }
502*433d6423SLionel Sambuc for (n=4; --n >= 0;) {
503*433d6423SLionel Sambuc if ((c = zdlread()) & ~0377)
504*433d6423SLionel Sambuc return c;
505*433d6423SLionel Sambuc crc = UPDC32(c, crc);
506*433d6423SLionel Sambuc #ifdef DEBUGZ
507*433d6423SLionel Sambuc vfile("zrbhdr32 c=%X crc=%lX", c, crc);
508*433d6423SLionel Sambuc #endif
509*433d6423SLionel Sambuc }
510*433d6423SLionel Sambuc if (crc != 0xDEBB20E3) {
511*433d6423SLionel Sambuc zperr(badcrc);
512*433d6423SLionel Sambuc return ERROR;
513*433d6423SLionel Sambuc }
514*433d6423SLionel Sambuc #ifdef ZMODEM
515*433d6423SLionel Sambuc Protocol = ZMODEM;
516*433d6423SLionel Sambuc #endif
517*433d6423SLionel Sambuc Zmodem = 1;
518*433d6423SLionel Sambuc return Rxtype;
519*433d6423SLionel Sambuc }
520*433d6423SLionel Sambuc
521*433d6423SLionel Sambuc
522*433d6423SLionel Sambuc /* Receive a hex style header (type and position) */
zrhhdr(char * hdr)523*433d6423SLionel Sambuc int zrhhdr(char *hdr)
524*433d6423SLionel Sambuc {
525*433d6423SLionel Sambuc register int c;
526*433d6423SLionel Sambuc register unsigned short crc;
527*433d6423SLionel Sambuc register int n;
528*433d6423SLionel Sambuc
529*433d6423SLionel Sambuc if ((c = zgethex()) < 0)
530*433d6423SLionel Sambuc return c;
531*433d6423SLionel Sambuc Rxtype = c;
532*433d6423SLionel Sambuc crc = updcrc(c, 0);
533*433d6423SLionel Sambuc
534*433d6423SLionel Sambuc for (n=4; --n >= 0; ++hdr) {
535*433d6423SLionel Sambuc if ((c = zgethex()) < 0)
536*433d6423SLionel Sambuc return c;
537*433d6423SLionel Sambuc crc = updcrc(c, crc);
538*433d6423SLionel Sambuc *hdr = c;
539*433d6423SLionel Sambuc }
540*433d6423SLionel Sambuc if ((c = zgethex()) < 0)
541*433d6423SLionel Sambuc return c;
542*433d6423SLionel Sambuc crc = updcrc(c, crc);
543*433d6423SLionel Sambuc if ((c = zgethex()) < 0)
544*433d6423SLionel Sambuc return c;
545*433d6423SLionel Sambuc crc = updcrc(c, crc);
546*433d6423SLionel Sambuc if (crc & 0xFFFF) {
547*433d6423SLionel Sambuc zperr(badcrc); return ERROR;
548*433d6423SLionel Sambuc }
549*433d6423SLionel Sambuc switch ( c = readline(1)) {
550*433d6423SLionel Sambuc case 0215:
551*433d6423SLionel Sambuc Not8bit = c;
552*433d6423SLionel Sambuc /* **** FALL THRU TO **** */
553*433d6423SLionel Sambuc case 015:
554*433d6423SLionel Sambuc /* Throw away possible cr/lf */
555*433d6423SLionel Sambuc switch (c = readline(1)) {
556*433d6423SLionel Sambuc case 012:
557*433d6423SLionel Sambuc Not8bit |= c;
558*433d6423SLionel Sambuc }
559*433d6423SLionel Sambuc }
560*433d6423SLionel Sambuc #ifdef ZMODEM
561*433d6423SLionel Sambuc Protocol = ZMODEM;
562*433d6423SLionel Sambuc #endif
563*433d6423SLionel Sambuc Zmodem = 1; return Rxtype;
564*433d6423SLionel Sambuc }
565*433d6423SLionel Sambuc
566*433d6423SLionel Sambuc /* Send a byte as two hex digits */
zputhex(int c)567*433d6423SLionel Sambuc void zputhex(int c)
568*433d6423SLionel Sambuc {
569*433d6423SLionel Sambuc static char digits[] = "0123456789abcdef";
570*433d6423SLionel Sambuc
571*433d6423SLionel Sambuc if (Verbose>8)
572*433d6423SLionel Sambuc vfile("zputhex: %02X", c);
573*433d6423SLionel Sambuc sendline(digits[(c&0xF0)>>4]);
574*433d6423SLionel Sambuc sendline(digits[(c)&0xF]);
575*433d6423SLionel Sambuc }
576*433d6423SLionel Sambuc
577*433d6423SLionel Sambuc /*
578*433d6423SLionel Sambuc * Send character c with ZMODEM escape sequence encoding.
579*433d6423SLionel Sambuc * Escape XON, XOFF. Escape CR following @ (Telenet net escape)
580*433d6423SLionel Sambuc */
zsendline(int c)581*433d6423SLionel Sambuc void zsendline(int c)
582*433d6423SLionel Sambuc {
583*433d6423SLionel Sambuc
584*433d6423SLionel Sambuc /* Quick check for non control characters */
585*433d6423SLionel Sambuc if (c & 0140)
586*433d6423SLionel Sambuc xsendline(lastsent = c);
587*433d6423SLionel Sambuc else {
588*433d6423SLionel Sambuc switch (c &= 0377) {
589*433d6423SLionel Sambuc case ZDLE:
590*433d6423SLionel Sambuc xsendline(ZDLE);
591*433d6423SLionel Sambuc xsendline (lastsent = (c ^= 0100));
592*433d6423SLionel Sambuc break;
593*433d6423SLionel Sambuc case 015:
594*433d6423SLionel Sambuc case 0215:
595*433d6423SLionel Sambuc if (!Zctlesc && (lastsent & 0177) != '@')
596*433d6423SLionel Sambuc goto sendit;
597*433d6423SLionel Sambuc /* **** FALL THRU TO **** */
598*433d6423SLionel Sambuc case 020:
599*433d6423SLionel Sambuc case 021:
600*433d6423SLionel Sambuc case 023:
601*433d6423SLionel Sambuc case 0220:
602*433d6423SLionel Sambuc case 0221:
603*433d6423SLionel Sambuc case 0223:
604*433d6423SLionel Sambuc xsendline(ZDLE);
605*433d6423SLionel Sambuc c ^= 0100;
606*433d6423SLionel Sambuc sendit:
607*433d6423SLionel Sambuc xsendline(lastsent = c);
608*433d6423SLionel Sambuc break;
609*433d6423SLionel Sambuc default:
610*433d6423SLionel Sambuc if (Zctlesc && ! (c & 0140)) {
611*433d6423SLionel Sambuc xsendline(ZDLE);
612*433d6423SLionel Sambuc c ^= 0100;
613*433d6423SLionel Sambuc }
614*433d6423SLionel Sambuc xsendline(lastsent = c);
615*433d6423SLionel Sambuc }
616*433d6423SLionel Sambuc }
617*433d6423SLionel Sambuc }
618*433d6423SLionel Sambuc
619*433d6423SLionel Sambuc /* Decode two lower case hex digits into an 8 bit byte value */
zgethex()620*433d6423SLionel Sambuc int zgethex()
621*433d6423SLionel Sambuc {
622*433d6423SLionel Sambuc register int c;
623*433d6423SLionel Sambuc
624*433d6423SLionel Sambuc c = zgeth1();
625*433d6423SLionel Sambuc if (Verbose>8)
626*433d6423SLionel Sambuc vfile("zgethex: %02X", c);
627*433d6423SLionel Sambuc return c;
628*433d6423SLionel Sambuc }
zgeth1()629*433d6423SLionel Sambuc int zgeth1()
630*433d6423SLionel Sambuc {
631*433d6423SLionel Sambuc register int c, n;
632*433d6423SLionel Sambuc
633*433d6423SLionel Sambuc if ((c = noxrd7()) < 0)
634*433d6423SLionel Sambuc return c;
635*433d6423SLionel Sambuc n = c - '0';
636*433d6423SLionel Sambuc if (n > 9)
637*433d6423SLionel Sambuc n -= ('a' - ':');
638*433d6423SLionel Sambuc if (n & ~0xF)
639*433d6423SLionel Sambuc return ERROR;
640*433d6423SLionel Sambuc if ((c = noxrd7()) < 0)
641*433d6423SLionel Sambuc return c;
642*433d6423SLionel Sambuc c -= '0';
643*433d6423SLionel Sambuc if (c > 9)
644*433d6423SLionel Sambuc c -= ('a' - ':');
645*433d6423SLionel Sambuc if (c & ~0xF)
646*433d6423SLionel Sambuc return ERROR;
647*433d6423SLionel Sambuc c += (n<<4);
648*433d6423SLionel Sambuc return c;
649*433d6423SLionel Sambuc }
650*433d6423SLionel Sambuc
651*433d6423SLionel Sambuc /*
652*433d6423SLionel Sambuc * Read a byte, checking for ZMODEM escape encoding
653*433d6423SLionel Sambuc * including CAN*5 which represents a quick abort
654*433d6423SLionel Sambuc */
zdlread()655*433d6423SLionel Sambuc int zdlread()
656*433d6423SLionel Sambuc {
657*433d6423SLionel Sambuc register int c;
658*433d6423SLionel Sambuc
659*433d6423SLionel Sambuc again:
660*433d6423SLionel Sambuc /* Quick check for non control characters */
661*433d6423SLionel Sambuc if ((c = readline(Rxtimeout)) & 0140)
662*433d6423SLionel Sambuc return c;
663*433d6423SLionel Sambuc switch (c) {
664*433d6423SLionel Sambuc case ZDLE:
665*433d6423SLionel Sambuc break;
666*433d6423SLionel Sambuc case 023:
667*433d6423SLionel Sambuc case 0223:
668*433d6423SLionel Sambuc case 021:
669*433d6423SLionel Sambuc case 0221:
670*433d6423SLionel Sambuc goto again;
671*433d6423SLionel Sambuc default:
672*433d6423SLionel Sambuc if (Zctlesc && !(c & 0140)) {
673*433d6423SLionel Sambuc goto again;
674*433d6423SLionel Sambuc }
675*433d6423SLionel Sambuc return c;
676*433d6423SLionel Sambuc }
677*433d6423SLionel Sambuc again2:
678*433d6423SLionel Sambuc if ((c = readline(Rxtimeout)) < 0)
679*433d6423SLionel Sambuc return c;
680*433d6423SLionel Sambuc if (c == CAN && (c = readline(Rxtimeout)) < 0)
681*433d6423SLionel Sambuc return c;
682*433d6423SLionel Sambuc if (c == CAN && (c = readline(Rxtimeout)) < 0)
683*433d6423SLionel Sambuc return c;
684*433d6423SLionel Sambuc if (c == CAN && (c = readline(Rxtimeout)) < 0)
685*433d6423SLionel Sambuc return c;
686*433d6423SLionel Sambuc switch (c) {
687*433d6423SLionel Sambuc case CAN:
688*433d6423SLionel Sambuc return GOTCAN;
689*433d6423SLionel Sambuc case ZCRCE:
690*433d6423SLionel Sambuc case ZCRCG:
691*433d6423SLionel Sambuc case ZCRCQ:
692*433d6423SLionel Sambuc case ZCRCW:
693*433d6423SLionel Sambuc return (c | GOTOR);
694*433d6423SLionel Sambuc case ZRUB0:
695*433d6423SLionel Sambuc return 0177;
696*433d6423SLionel Sambuc case ZRUB1:
697*433d6423SLionel Sambuc return 0377;
698*433d6423SLionel Sambuc case 023:
699*433d6423SLionel Sambuc case 0223:
700*433d6423SLionel Sambuc case 021:
701*433d6423SLionel Sambuc case 0221:
702*433d6423SLionel Sambuc goto again2;
703*433d6423SLionel Sambuc default:
704*433d6423SLionel Sambuc if (Zctlesc && ! (c & 0140)) {
705*433d6423SLionel Sambuc goto again2;
706*433d6423SLionel Sambuc }
707*433d6423SLionel Sambuc if ((c & 0140) == 0100)
708*433d6423SLionel Sambuc return (c ^ 0100);
709*433d6423SLionel Sambuc break;
710*433d6423SLionel Sambuc }
711*433d6423SLionel Sambuc if (Verbose>1)
712*433d6423SLionel Sambuc zperr("Bad escape sequence %x", c);
713*433d6423SLionel Sambuc return ERROR;
714*433d6423SLionel Sambuc }
715*433d6423SLionel Sambuc
716*433d6423SLionel Sambuc /*
717*433d6423SLionel Sambuc * Read a character from the modem line with timeout.
718*433d6423SLionel Sambuc * Eat parity, XON and XOFF characters.
719*433d6423SLionel Sambuc */
noxrd7()720*433d6423SLionel Sambuc int noxrd7()
721*433d6423SLionel Sambuc {
722*433d6423SLionel Sambuc register int c;
723*433d6423SLionel Sambuc
724*433d6423SLionel Sambuc for (;;) {
725*433d6423SLionel Sambuc if ((c = readline(Rxtimeout)) < 0)
726*433d6423SLionel Sambuc return c;
727*433d6423SLionel Sambuc switch (c &= 0177) {
728*433d6423SLionel Sambuc case XON:
729*433d6423SLionel Sambuc case XOFF:
730*433d6423SLionel Sambuc continue;
731*433d6423SLionel Sambuc default:
732*433d6423SLionel Sambuc if (Zctlesc && !(c & 0140))
733*433d6423SLionel Sambuc continue;
734*433d6423SLionel Sambuc case '\r':
735*433d6423SLionel Sambuc case '\n':
736*433d6423SLionel Sambuc case ZDLE:
737*433d6423SLionel Sambuc return c;
738*433d6423SLionel Sambuc }
739*433d6423SLionel Sambuc }
740*433d6423SLionel Sambuc }
741*433d6423SLionel Sambuc
742*433d6423SLionel Sambuc /* Store long integer pos in Txhdr */
stohdr(long pos)743*433d6423SLionel Sambuc void stohdr(long pos)
744*433d6423SLionel Sambuc {
745*433d6423SLionel Sambuc Txhdr[ZP0] = pos;
746*433d6423SLionel Sambuc Txhdr[ZP1] = pos>>8;
747*433d6423SLionel Sambuc Txhdr[ZP2] = pos>>16;
748*433d6423SLionel Sambuc Txhdr[ZP3] = pos>>24;
749*433d6423SLionel Sambuc }
750*433d6423SLionel Sambuc
751*433d6423SLionel Sambuc /* Recover a long integer from a header */
752*433d6423SLionel Sambuc long
rclhdr(char * hdr)753*433d6423SLionel Sambuc rclhdr(char *hdr)
754*433d6423SLionel Sambuc {
755*433d6423SLionel Sambuc register long l;
756*433d6423SLionel Sambuc
757*433d6423SLionel Sambuc l = (hdr[ZP3] & 0377);
758*433d6423SLionel Sambuc l = (l << 8) | (hdr[ZP2] & 0377);
759*433d6423SLionel Sambuc l = (l << 8) | (hdr[ZP1] & 0377);
760*433d6423SLionel Sambuc l = (l << 8) | (hdr[ZP0] & 0377);
761*433d6423SLionel Sambuc return l;
762*433d6423SLionel Sambuc }
763*433d6423SLionel Sambuc
764*433d6423SLionel Sambuc /* End of zm.c */
765