|
|
1.1 root 1: /* protf.c
2: The 'f' protocol.
3:
4: Copyright (C) 1991, 1992 Ian Lance Taylor
5:
6: This file is part of the Taylor UUCP package.
7:
8: This program is free software; you can redistribute it and/or
9: modify it under the terms of the GNU General Public License as
10: published by the Free Software Foundation; either version 2 of the
11: License, or (at your option) any later version.
12:
13: This program is distributed in the hope that it will be useful, but
14: WITHOUT ANY WARRANTY; without even the implied warranty of
15: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16: General Public License for more details.
17:
18: You should have received a copy of the GNU General Public License
19: along with this program; if not, write to the Free Software
20: Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21:
22: The author of the program may be contacted at [email protected] or
23: c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254.
24: */
25:
26: #include "uucp.h"
27:
28: #if USE_RCS_ID
29: const char protf_rcsid[] = "$Id: protf.c,v 1.1 93/07/30 07:53:18 bin Exp Locker: bin $";
30: #endif
31:
32: #include <ctype.h>
33: #include <errno.h>
34:
35: #include "uudefs.h"
36: #include "uuconf.h"
37: #include "conn.h"
38: #include "trans.h"
39: #include "system.h"
40: #include "prot.h"
41:
42: /* This implementation is based on code by Piet Beertema, CWI,
43: Amsterdam, Sep 1984.
44:
45: This code implements the 'f' protocol, which requires a
46: flow-controlled error-free seven-bit data path. It does check for
47: errors, but only at the end of each file transmission, so a noisy
48: line without error correcting modems will be unusable.
49:
50: The conversion to seven bit data is done as follows, where b
51: represents the character to convert:
52:
53: 0 <= b <= 037: 0172, b + 0100 (0100 to 0137)
54: 040 <= b <= 0171: b ( 040 to 0171)
55: 0172 <= b <= 0177: 0173, b - 0100 ( 072 to 077)
56: 0200 <= b <= 0237: 0174, b - 0100 (0100 to 0137)
57: 0240 <= b <= 0371: 0175, b - 0200 ( 040 to 0171)
58: 0372 <= b <= 0377: 0176, b - 0300 ( 072 to 077)
59:
60: This causes all output bytes to be in the range 040 to 0176; these
61: are the printable ASCII characters. */
62:
63: /* This structure is used to hold information when dealing with the
64: end of file acknowledgement. */
65:
66: struct sfinfo
67: {
68: /* The functions from the generic code. */
69: boolean (*psendfn) P((struct stransfer *qtrans, struct sdaemon *qdaemon));
70: boolean (*precfn) P((struct stransfer *qtrans, struct sdaemon *qdaemon,
71: const char *zdata, size_t cdata));
72: /* The info pointer from the generic code. */
73: pointer pinfo;
74: /* The character to send after receiving the checksum. */
75: char bsend;
76: };
77:
78: /* Internal functions. */
79: static boolean ffprocess_data P((struct sdaemon *qdaemon,
80: boolean *pfexit, size_t *pcneed));
81: static boolean ffawait_ack P((struct stransfer *qtrans,
82: struct sdaemon *qdaemon,
83: const char *zdata, size_t cdata));
84: static boolean ffawait_cksum P((struct stransfer *qtrans,
85: struct sdaemon *qdaemon,
86: const char *zdata, size_t cdata));
87: static boolean ffsend_ack P((struct stransfer *qtrans,
88: struct sdaemon *qdaemon));
89:
90: /* The size of the buffer we allocate to store outgoing data in. */
91: #define CFBUFSIZE (256)
92:
93: /* The timeout to wait for data to arrive before giving up. */
94: static int cFtimeout = 120;
95:
96: /* The maximum number of retries. */
97: static int cFmaxretries = 2;
98:
99: /* The buffer we allocate for outgoing data. */
100: static char *zFbuf;
101:
102: /* TRUE if we are receiving a file rather than a command. */
103: static boolean fFfile;
104:
105: /* The checksum so far. */
106: static unsigned int iFcheck;
107:
108: /* The last special byte (0172 to 0176) or 0 if none. */
109: static char bFspecial;
110:
111: /* The number of times we have retried this file. */
112: static int cFretries;
113:
114: /* Whether this file has been acknowledged. */
115: static boolean fFacked;
116:
117: struct uuconf_cmdtab asFproto_params[] =
118: {
119: { "timeout", UUCONF_CMDTABTYPE_INT, (pointer) &cFtimeout, NULL },
120: { "retries", UUCONF_CMDTABTYPE_INT, (pointer) &cFmaxretries, NULL },
121: { NULL, 0, NULL, NULL }
122: };
123:
124: /* Statistics. */
125:
126: /* The number of data bytes sent in files. */
127: static long cFsent_data;
128:
129: /* The number of actual bytes sent in files. */
130: static long cFsent_bytes;
131:
132: /* The number of data bytes received in files. */
133: static long cFrec_data;
134:
135: /* The number of actual bytes received in files. */
136: static long cFrec_bytes;
137:
138: /* The number of file retries when sending. */
139: static long cFsend_retries;
140:
141: /* The number of file retries when receiving. */
142: static long cFrec_retries;
143:
144: /* Start the protocol. */
145:
146: boolean
147: ffstart (qdaemon, pzlog)
148: struct sdaemon *qdaemon;
149: char **pzlog;
150: {
151: *pzlog = NULL;
152:
153: cFsent_data = 0;
154: cFsent_bytes = 0;
155: cFrec_data = 0;
156: cFrec_bytes = 0;
157: cFsend_retries = 0;
158: cFrec_retries = 0;
159:
160: /* Use XON/XOFF handshaking. */
161: if (! fconn_set (qdaemon->qconn, PARITYSETTING_DEFAULT,
162: STRIPSETTING_SEVENBITS, XONXOFF_ON))
163: return FALSE;
164:
165: /* We sleep to allow the other side to reset the terminal; this is
166: what Mr. Beertema's code does. */
167: usysdep_sleep (2);
168:
169: return TRUE;
170: }
171:
172: /* Shutdown the protocol. */
173:
174: /*ARGSIGNORED*/
175: boolean
176: ffshutdown (qdaemon)
177: struct sdaemon *qdaemon;
178: {
179: xfree ((pointer) zFbuf);
180: zFbuf = NULL;
181: ulog (LOG_NORMAL,
182: "Protocol 'f': sent %ld bytes for %ld, received %ld bytes for %ld",
183: cFsent_bytes, cFsent_data, cFrec_bytes, cFrec_data);
184: if (cFsend_retries != 0 || cFrec_retries != 0)
185: ulog (LOG_NORMAL, "Protocol 'f' file retries: %ld sending, %ld receiving",
186: cFsend_retries, cFrec_retries);
187: cFtimeout = 120;
188: cFmaxretries = 2;
189: return TRUE;
190: }
191:
192: /* Send a command string. We just send the string followed by a carriage
193: return. */
194:
195: /*ARGSUSED*/
196: boolean
197: ffsendcmd (qdaemon, z, ilocal, iremote)
198: struct sdaemon *qdaemon;
199: const char *z;
200: int ilocal;
201: int iremote;
202: {
203: size_t clen;
204: char *zalc;
205: boolean fret;
206:
207: DEBUG_MESSAGE1 (DEBUG_UUCP_PROTO, "ffsendcmd: Sending command \"%s\"", z);
208:
209: clen = strlen (z);
210: zalc = zbufalc (clen + 2);
211: memcpy (zalc, z, clen);
212: zalc[clen] = '\r';
213: zalc[clen + 1] = '\0';
214: fret = fsend_data (qdaemon->qconn, zalc, clen + 1, TRUE);
215: ubuffree (zalc);
216: return fret;
217: }
218:
219: /* Get space to be filled with data. We allocate the space from the
220: heap. */
221:
222: /*ARGSIGNORED*/
223: char *
224: zfgetspace (qdaemon, pclen)
225: struct sdaemon *qdaemon;
226: size_t *pclen;
227: {
228: *pclen = CFBUFSIZE;
229: if (zFbuf == NULL)
230: zFbuf = (char *) xmalloc (CFBUFSIZE);
231: return zFbuf;
232: }
233:
234: /* Send out a data packet. We have to encode the data into seven bits
235: and accumulate a checksum. */
236:
237: /*ARGSIGNORED*/
238: boolean
239: ffsenddata (qdaemon, zdata, cdata, ilocal, iremote, ipos)
240: struct sdaemon *qdaemon;
241: char *zdata;
242: size_t cdata;
243: int ilocal;
244: int iremote;
245: long ipos;
246: {
247: char ab[CFBUFSIZE * 2];
248: char *ze;
249: register unsigned int itmpchk;
250:
251: cFsent_data += cdata;
252:
253: ze = ab;
254: itmpchk = iFcheck;
255: while (cdata-- > 0)
256: {
257: register int b;
258:
259: /* Rotate the checksum left. */
260: if ((itmpchk & 0x8000) == 0)
261: itmpchk <<= 1;
262: else
263: {
264: itmpchk <<= 1;
265: ++itmpchk;
266: }
267:
268: /* Add the next byte into the checksum. */
269: b = *zdata++ & 0xff;
270: itmpchk += b;
271:
272: /* Encode the byte. */
273: if (b <= 0177)
274: {
275: if (b <= 037)
276: {
277: *ze++ = '\172';
278: *ze++ = (char) (b + 0100);
279: }
280: else if (b <= 0171)
281: *ze++ = (char) b;
282: else
283: {
284: *ze++ = '\173';
285: *ze++ = (char) (b - 0100);
286: }
287: }
288: else
289: {
290: if (b <= 0237)
291: {
292: *ze++ = '\174';
293: *ze++ = (char) (b - 0100);
294: }
295: else if (b <= 0371)
296: {
297: *ze++ = '\175';
298: *ze++ = (char) (b - 0200);
299: }
300: else
301: {
302: *ze++ = '\176';
303: *ze++ = (char) (b - 0300);
304: }
305: }
306: }
307:
308: iFcheck = itmpchk;
309:
310: cFsent_bytes += ze - ab;
311:
312: /* Passing FALSE tells fsend_data not to bother looking for incoming
313: information, since we really don't expect any. */
314: return fsend_data (qdaemon->qconn, ab, (size_t) (ze - ab), FALSE);
315: }
316:
317: /* Process data and return the amount of data we are looking for in
318: *pcneed. The 'f' protocol doesn't really reveal this, but when
319: transferring file we know that we need at least seven characters
320: for the checksum. */
321:
322: static boolean
323: ffprocess_data (qdaemon, pfexit, pcneed)
324: struct sdaemon *qdaemon;
325: boolean *pfexit;
326: size_t *pcneed;
327: {
328: int i;
329: register unsigned int itmpchk;
330:
331: *pfexit = FALSE;
332: if (pcneed != NULL)
333: *pcneed = 1;
334:
335: if (! fFfile)
336: {
337: /* A command continues until a '\r' character, which we turn
338: into '\0' before calling fgot_data. */
339: while (iPrecstart != iPrecend)
340: {
341: for (i = iPrecstart; i < CRECBUFLEN && i != iPrecend; i++)
342: {
343: if (abPrecbuf[i] == '\r')
344: {
345: int istart;
346:
347: DEBUG_MESSAGE1 (DEBUG_PROTO,
348: "ffprocess_data: Got %d command bytes",
349: i - iPrecstart + 1);
350:
351: abPrecbuf[i] = '\0';
352: istart = iPrecstart;
353: iPrecstart = (i + 1) % CRECBUFLEN;
354: if (pcneed != NULL)
355: *pcneed = 0;
356: return fgot_data (qdaemon, abPrecbuf + istart,
357: (size_t) (i - istart + 1),
358: (const char *) NULL, (size_t) 0,
359: -1, -1, (long) -1, TRUE, pfexit);
360: }
361: }
362:
363: DEBUG_MESSAGE1 (DEBUG_PROTO,
364: "ffprocess_data: Got %d command bytes",
365: i - iPrecstart);
366:
367: if (! fgot_data (qdaemon, abPrecbuf + iPrecstart,
368: (size_t) (i - iPrecstart),
369: (const char *) NULL, (size_t) 0,
370: -1, -1, (long) -1, TRUE, pfexit))
371: return FALSE;
372:
373: iPrecstart = i % CRECBUFLEN;
374: }
375:
376: return TRUE;
377: }
378:
379: /* Here the data is destined for a file, and we must decode it. */
380:
381: itmpchk = iFcheck;
382:
383: while (iPrecstart != iPrecend)
384: {
385: char *zstart, *zto, *zfrom;
386: int c;
387:
388: zto = zfrom = zstart = abPrecbuf + iPrecstart;
389:
390: c = iPrecend - iPrecstart;
391: if (c < 0)
392: c = CRECBUFLEN - iPrecstart;
393:
394: while (c-- != 0)
395: {
396: int b;
397:
398: b = *zfrom++ & 0xff;
399: if (b < 040 || b > 0176)
400: {
401: ulog (LOG_ERROR, "Illegal byte %d", b);
402: continue;
403: }
404:
405: /* Characters >= 0172 are always special characters. The
406: only legal pair of consecutive special characters
407: are 0176 0176 which immediately precede the four
408: digit checksum. */
409: if (b >= 0172)
410: {
411: if (bFspecial != 0)
412: {
413: if (bFspecial != 0176 || b != 0176)
414: {
415: ulog (LOG_ERROR, "Illegal bytes %d %d",
416: bFspecial, b);
417: bFspecial = 0;
418: continue;
419: }
420:
421: /* Pass any initial data. */
422: if (zto != zstart)
423: {
424: /* Don't count the checksum in the received bytes. */
425: cFrec_bytes += zfrom - zstart - 2;
426: cFrec_data += zto - zstart;
427: if (! fgot_data (qdaemon, zstart,
428: (size_t) (zto - zstart),
429: (const char *) NULL, (size_t) 0,
430: -1, -1, (long) -1, TRUE, pfexit))
431: return FALSE;
432: }
433:
434: /* The next characters we want to read are the
435: checksum, so skip the second 0176. */
436: iPrecstart = (iPrecstart + zfrom - zstart) % CRECBUFLEN;
437:
438: iFcheck = itmpchk;
439:
440: /* Tell fgot_data that we've read the entire file by
441: passing 0 length data. This will wind up calling
442: fffile to verify the checksum. We set *pcneed to
443: 0 because we don't want to read any more data
444: from the port, since we may have already read the
445: checksum. */
446: if (pcneed != NULL)
447: *pcneed = 0;
448: return fgot_data (qdaemon, (const char *) NULL,
449: (size_t) 0, (const char *) NULL,
450: (size_t) 0, -1, -1, (long) -1,
451: TRUE, pfexit);
452: }
453:
454: /* Here we have encountered a special character that
455: does not follow another special character. */
456: bFspecial = (char) b;
457: }
458: else
459: {
460: int bnext;
461:
462: /* Here we have encountered a nonspecial character. */
463:
464: switch (bFspecial)
465: {
466: default:
467: bnext = b;
468: break;
469: case 0172:
470: bnext = b - 0100;
471: break;
472: case 0173:
473: case 0174:
474: bnext = b + 0100;
475: break;
476: case 0175:
477: bnext = b + 0200;
478: break;
479: case 0176:
480: bnext = b + 0300;
481: break;
482: }
483:
484: *zto++ = (char) bnext;
485: bFspecial = 0;
486:
487: /* Rotate the checksum left. */
488: if ((itmpchk & 0x8000) == 0)
489: itmpchk <<= 1;
490: else
491: {
492: itmpchk <<= 1;
493: ++itmpchk;
494: }
495:
496: /* Add the next byte into the checksum. */
497: itmpchk += bnext;
498: }
499: }
500:
501: if (zto != zstart)
502: {
503: DEBUG_MESSAGE1 (DEBUG_PROTO,
504: "ffprocess_data: Got %d bytes",
505: zto - zstart);
506:
507: cFrec_data += zto - zstart;
508: if (! fgot_data (qdaemon, zstart, (size_t) (zto - zstart),
509: (const char *) NULL, (size_t) 0,
510: -1, -1, (long) -1, TRUE, pfexit))
511: return FALSE;
512: }
513:
514: cFrec_bytes += zfrom - zstart;
515:
516: iPrecstart = (iPrecstart + zfrom - zstart) % CRECBUFLEN;
517: }
518:
519: iFcheck = itmpchk;
520:
521: if (pcneed != NULL)
522: {
523: /* At this point we may have seen the first 0176 in the checksum
524: but not the second. The checksum is at least seven
525: characters long (0176 0176 a b c d \r). This won't help
526: much, but reading seven characters is a lot better than
527: reading two, which is what I saw in a 2400 baud log file. */
528: if (bFspecial == 0176)
529: *pcneed = 6;
530: else
531: *pcneed = 7;
532: }
533:
534: return TRUE;
535: }
536:
537: /* Wait for data to come in and process it until we've finished a
538: command or a file. */
539:
540: boolean
541: ffwait (qdaemon)
542: struct sdaemon *qdaemon;
543: {
544: while (TRUE)
545: {
546: boolean fexit;
547: size_t cneed, crec;
548:
549: if (! ffprocess_data (qdaemon, &fexit, &cneed))
550: return FALSE;
551: if (fexit)
552: return TRUE;
553:
554: if (cneed > 0)
555: {
556: /* We really want to do something like get all available
557: characters, then sleep for half a second and get all
558: available characters again, and keep this up until we
559: don't get anything after sleeping. */
560: if (! freceive_data (qdaemon->qconn, cneed, &crec, cFtimeout, TRUE))
561: return FALSE;
562: if (crec == 0)
563: {
564: ulog (LOG_ERROR, "Timed out waiting for data");
565: return FALSE;
566: }
567: }
568: }
569: }
570:
571: /* File level operations. Reset the checksums when starting to send
572: or receive a file, and output the checksum when we've finished
573: sending a file. */
574:
575: /*ARGSUSED*/
576: boolean
577: fffile (qdaemon, qtrans, fstart, fsend, cbytes, pfhandled)
578: struct sdaemon *qdaemon;
579: struct stransfer *qtrans;
580: boolean fstart;
581: boolean fsend;
582: long cbytes;
583: boolean *pfhandled;
584: {
585: DEBUG_MESSAGE3 (DEBUG_PROTO, "fffile: fstart %s; fsend %s; fFacked %s",
586: fstart ? "true" : "false", fsend ? "true" : "false",
587: fFacked ? "true" : "false");
588:
589: *pfhandled = FALSE;
590:
591: if (fstart)
592: {
593: iFcheck = 0xffff;
594: cFretries = 0;
595: fFacked = FALSE;
596: if (! fsend)
597: {
598: bFspecial = 0;
599: fFfile = TRUE;
600: }
601: return TRUE;
602: }
603: else
604: {
605: struct sfinfo *qinfo;
606:
607: /* We need to handle the checksum and the acknowledgement. If
608: we get a successful ACK, we set fFacked to TRUE and call the
609: send or receive function by hand. This will wind up calling
610: here again, so if fFacked is TRUE we just return out and let
611: the send or receive function do whatever it does. This is a
612: bit of a hack. */
613: if (fFacked)
614: {
615: fFacked = FALSE;
616: return TRUE;
617: }
618:
619: if (fsend)
620: {
621: char ab[sizeof "\176\176ABCD\r"];
622:
623: /* Send the final checksum. */
624: sprintf (ab, "\176\176%04x\r", iFcheck & 0xffff);
625: if (! fsend_data (qdaemon->qconn, ab, (size_t) 7, TRUE))
626: return FALSE;
627:
628: /* Now wait for the acknowledgement. */
629: fFfile = FALSE;
630: qinfo = (struct sfinfo *) xmalloc (sizeof (struct sfinfo));
631: qinfo->psendfn = qtrans->psendfn;
632: qinfo->precfn = qtrans->precfn;
633: qinfo->pinfo = qtrans->pinfo;
634: qtrans->psendfn = NULL;
635: qtrans->precfn = ffawait_ack;
636: qtrans->pinfo = (pointer) qinfo;
637: qtrans->fcmd = TRUE;
638:
639: *pfhandled = TRUE;
640:
641: return fqueue_receive (qdaemon, qtrans);
642: }
643: else
644: {
645: /* Wait for the checksum. */
646: fFfile = FALSE;
647: qinfo = (struct sfinfo *) xmalloc (sizeof (struct sfinfo));
648: qinfo->psendfn = qtrans->psendfn;
649: qinfo->precfn = qtrans->precfn;
650: qinfo->pinfo = qtrans->pinfo;
651: qtrans->psendfn = NULL;
652: qtrans->precfn = ffawait_cksum;
653: qtrans->pinfo = (pointer) qinfo;
654: qtrans->fcmd = TRUE;
655:
656: *pfhandled = TRUE;
657:
658: return fqueue_receive (qdaemon, qtrans);
659: }
660: }
661: }
662:
663: /* Wait for the ack after sending a file and the checksum. */
664:
665: static boolean
666: ffawait_ack (qtrans, qdaemon, zdata, cdata)
667: struct stransfer *qtrans;
668: struct sdaemon *qdaemon;
669: const char *zdata;
670: size_t cdata;
671: {
672: struct sfinfo *qinfo = (struct sfinfo *) qtrans->pinfo;
673:
674: qtrans->precfn = NULL;
675:
676: /* An R means to retry sending the file. */
677: if (*zdata == 'R')
678: {
679: if (! ffileisopen (qtrans->e))
680: {
681: ulog (LOG_ERROR, "Request to resent non-file");
682: return FALSE;
683: }
684:
685: ++cFretries;
686: if (cFretries > cFmaxretries)
687: {
688: ulog (LOG_ERROR, "Too many retries");
689: return FALSE;
690: }
691:
692: ulog (LOG_NORMAL, "Resending file");
693: if (! ffilerewind (qtrans->e))
694: {
695: ulog (LOG_ERROR, "rewind: %s", strerror (errno));
696: return FALSE;
697: }
698: qtrans->ipos = (long) 0;
699:
700: iFcheck = 0xffff;
701: ++cFsend_retries;
702:
703: qtrans->psendfn = qinfo->psendfn;
704: qtrans->precfn = qinfo->precfn;
705: qtrans->pinfo = qinfo->pinfo;
706: xfree ((pointer) qinfo);
707: qtrans->fsendfile = TRUE;
708:
709: return fqueue_send (qdaemon, qtrans);
710: }
711:
712: if (*zdata != 'G')
713: {
714: DEBUG_MESSAGE1 (DEBUG_PROTO, "fffile: Got \"%s\"", zdata);
715: ulog (LOG_ERROR, "File send failed");
716: return FALSE;
717: }
718:
719: qtrans->psendfn = qinfo->psendfn;
720: qtrans->precfn = qinfo->precfn;
721: qtrans->pinfo = qinfo->pinfo;
722: xfree ((pointer) qinfo);
723:
724: /* Now call the send function by hand after setting fFacked to TRUE.
725: Since fFacked is true fffile will simply return out, and the send
726: function can do whatever it what was going to do. */
727: fFacked = TRUE;
728: return (*qtrans->psendfn) (qtrans, qdaemon);
729: }
730:
731: /* This function is called when the checksum arrives. */
732:
733: /*ARGSUSED*/
734: static boolean
735: ffawait_cksum (qtrans, qdaemon, zdata, cdata)
736: struct stransfer *qtrans;
737: struct sdaemon *qdaemon;
738: const char *zdata;
739: size_t cdata;
740: {
741: struct sfinfo *qinfo = (struct sfinfo *) qtrans->pinfo;
742: unsigned int icheck;
743:
744: qtrans->precfn = NULL;
745:
746: if (! isxdigit (zdata[0])
747: || ! isxdigit (zdata[1])
748: || ! isxdigit (zdata[2])
749: || ! isxdigit (zdata[3])
750: || zdata[4] != '\0')
751: {
752: ulog (LOG_ERROR, "Bad checksum format");
753: xfree (qtrans->pinfo);
754: return FALSE;
755: }
756:
757: icheck = (unsigned int) strtol ((char *) zdata, (char **) NULL, 16);
758:
759: if (icheck != (iFcheck & 0xffff))
760: {
761: DEBUG_MESSAGE2 (DEBUG_PROTO | DEBUG_ABNORMAL,
762: "Checksum failed; calculated 0x%x, got 0x%x",
763: iFcheck & 0xffff, icheck);
764:
765: if (! ffileisopen (qtrans->e))
766: {
767: ulog (LOG_ERROR, "Failed to get non-file");
768: return FALSE;
769: }
770:
771: ++cFretries;
772: if (cFretries > cFmaxretries)
773: {
774: ulog (LOG_ERROR, "Too many retries");
775: qinfo->bsend = 'Q';
776: }
777: else
778: {
779: ulog (LOG_NORMAL, "File being resent");
780:
781: /* This bit of code relies on the receive code setting
782: qtrans->s.ztemp to the full name of the temporary file
783: being used. */
784: qtrans->e = esysdep_truncate (qtrans->e, qtrans->s.ztemp);
785: if (! ffileisopen (qtrans->e))
786: return FALSE;
787: qtrans->ipos = (long) 0;
788:
789: iFcheck = 0xffff;
790: bFspecial = 0;
791: fFfile = TRUE;
792: ++cFrec_retries;
793:
794: /* Send an R to tell the other side to resend the file. */
795: qinfo->bsend = 'R';
796: }
797: }
798: else
799: {
800: /* Send a G to tell the other side the file was received
801: correctly. */
802: qinfo->bsend = 'G';
803: }
804:
805: qtrans->psendfn = ffsend_ack;
806:
807: return fqueue_send (qdaemon, qtrans);
808: }
809:
810: /* Send the acknowledgement, and then possible wait for the resent
811: file. */
812:
813: static boolean
814: ffsend_ack (qtrans, qdaemon)
815: struct stransfer *qtrans;
816: struct sdaemon *qdaemon;
817: {
818: struct sfinfo *qinfo = (struct sfinfo *) qtrans->pinfo;
819: char ab[2];
820:
821: ab[0] = qinfo->bsend;
822: ab[1] = '\0';
823: if (! ffsendcmd (qdaemon, ab, 0, 0))
824: return FALSE;
825:
826: qtrans->psendfn = qinfo->psendfn;
827: qtrans->precfn = qinfo->precfn;
828: qtrans->pinfo = qinfo->pinfo;
829: xfree ((pointer) qinfo);
830:
831: if (ab[0] == 'Q')
832: return FALSE;
833: if (ab[0] == 'R')
834: {
835: qtrans->frecfile = TRUE;
836: return fqueue_receive (qdaemon, qtrans);
837: }
838:
839: fFacked = TRUE;
840: return (*qtrans->precfn) (qtrans, qdaemon, (const char *) NULL,
841: (size_t) 0);
842: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.