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