SIMPLEMINDED RECOVERY FEATURE FOR KERMIT For public consumption, let's call this "Level-1" recovery. Level-2 recovery will be fullblown Checkpoint/Restart. This is just like Zmodem's method. It is compatible with (i.e. does not conflict with, can coexist with) the full-blown Kermit Checkpoint/Restart proposal. It can be implemented in about one day. It only works for binary-mode transfers, and only on systems that allow fseek() (sender) and append (receiver) operations. It does not work for text mode or labeled mode (e.g. in VMS or OS/2). It requires that SET FILE INCOMPLETE KEEP be in effect at the receiver during the original transfer, otherwise the partially received file is not saved. This is a "mere documentation issue" (or maybe it should become the new default). Syntax (just like SEND command): RESEND [ ] or: RESEND Semantics: 1. Fails immediately, with complaint, if transfer mode is not BINARY. 2. Fails immediately, with complaint, if ATTRIBUTES / DISPOSITION OFF. 3. Checks capability against other Kermit, fails if not there. 4. Other Kermit must also support A packets, fail if it doesn't. 5. Transfers the file or files in recover mode. Unlike the full-blown method, no records are kept, no checkpoints are taken, no new packet types are introduced. For each file, the receiver, after having obtained the name from the F packet and the Recover directive from the A packet, responds with the file size in the ACK to the A packet and switches into binary and append modes. The receiver starts sending at the given position (positions are 0-based). Thus the size reported by the receiver is exactly the starting position for the sender. Protocol changes: 1. A new capability bit in the Init String indicating recover capability. 2. A "recover" code, R, for the A-packet Disposition (+) field. 3. A new response to the A packet, to convey the size. 1. Initialization String Format: The full-blown checkpoint proposal already allocates the following fields, which we should leave alone (i.e. reserved). CAPAS+4, CHKPNT, 1 byte: WILL (1), WONT (0), DO (2) CAPAS+5, CHKINT, 3 bytes: Checkpoint interval It does not use any capabilities bits. Current capability bits definitions: Bit Number Value Meaning #1 32 Locking shifts #2 16 RESERVED #3 8 Attribute packets #4 4 Sliding windows #5 2 Long packets #6 1 Continuation marker So we can take Bit #2 for this. A Kermit that can handle "simpleminded recovery" always set this bit. 2. Attribute Packets When a RESEND command has been given, the sender's Disposition field (+) should be set to R (the uppercase letter R). Note that we only get this far if recovery capability has been negotiated. When receiver gets a recover indication in the A packet: 1. It makes sure the transfer mode is binary; if not, it refuses file, by sending an ACK to the A packet containing "N+" in its data field. (The transfer mode comes from the same A packet.) Otherwise: 2. It looks up the file and gets its size. If the file is not found, it sets the size to 0. There is some danger here of identifying the wrong file, especially when filename transformations or as-names are involved, but there's not much we can do about that. 3. It ACKs the A-packet. The data field of the ACK looks like this: 1 where L is the number of characters in the in excess-32 notation, and is the file's length in bytes, expressed as a decimal number, e.g. 1%12345 This notation is compatible with the notation used in the Checkpoint/Restart proposal. Program Changes: 1. We always set the new capability bit in the Init string. 2. The file sender adds the RESEND command. It uses exactly the same parsing and action code as the SEND command, but it sets a flag to remember we're resending rather than sending. At attribute-packet time, we set the disposition field to R if the flag is set. When the ACK to the A-packet comes, and it contains "1", we seek to the indicated place before commencing to send. If the length is the same as (or greater than) the source file's length, we just send a Z packet (since the destination file is open in append mode, we have effectively opened it, appended nothing to it, and closed it). 3. For the file receiver, the changes described above. Also, to aid in recovery after interrupted transfers to Kermit programs that don't support recovery or checkpointing: PSEND [ ] This is just like SEND, but fseeks to the given position first. The position is 0-based (first file byte is byte 0). Can be used for both text and binary transmission -- use at your own risk, etc. (This one was already part of the Checkpoint/Restart proposal -- it's so easy, might as well do it now). C-KERMIT IMPLEMENTATION: 1. Add symbols for RESEND and PSEND to ckuusr.h. 2. Add symbol to enable/disable this feature: CK_RESEND. 3. Add keywords to top-level table in ckuusr.c. 4. Add "sendmode" flag to parser and main, and define values for it. 5. Add parsing to ckuusr.c. 6. Add RS (ReSend) capability bit to main(), rpar(), spar(). 7. Sender fails (with E packet) if RS *and* AT capas not negotiated, ckcpro.w. 8. Sender's A-packet gets Disposition R, ckcfn3.c. 9. Create new zfseek(long pos) routine in ckufio.c. 10. Adjust "percent done" in file transfer display to account for fseeking. zfseek(pos) in the UNIX version is very simple: return(fseek(fp[ZIFILE], pos, 0)); It's OK if the pointer is beyond the end of file; in that case the next read will return EOF. Probably there will need to be extra complication in the VMS version. Receiver: If receiver gets A packet with R disposition: . If file type is not binary, it rejects the file. . It looks up the file with zchki(), gets length, responds with length. . If length > 0, it must save current file collision action, temporarily switch to SET FILE COLLISION APPEND. . Upon end of file reception, receiver restores saved file collision action. Sender: . Gets response to A packet, sees length, saves it. rsattr(). . After A-packet arrives, zfseek() if sendmode is RESEND and starting pos != 0. FILE COLLISION OPTIONS AT THE RECEIVER APPEND This works with no changes. OVERWRITE Works with no changes. DISCARD The discard flag is set in rcvfil. Later, it is tested in ckcpro.w, D, and if set, the file is discarded. Fix: at attribute time, if disposition=R, unset the discard flag. UPDATE The discard flag is set based on date comparison at A-packet time. Fix: after all the attributes have been processed, check to see if the disposition is R. If so, then: if the transfer mode is binary, we unset the discard flag and accept the file in recovery mode; if not binary, then we reject the file on the grounds of disposition (and/or file type). BACKUP This does not work because the old file is renamed before the A packet arrives. Looking up the old file fails because its name has changed. Cure: Postpone renaming until after A-packet comes. RENAME This should be OK, because it's the incoming file that will be renamed, and not the existing file. By the time the file starts to arrive, we know it's a RESENt file.