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