|
|
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.