Icon The Kermit Project   |   Now hosted by Panix.com
New York City USA   •   kermit@kermitproject.org
since 1981
Áëıøù        
C-Kermit To-Do List
    Notes for future developers
Frank da Cruz
fdc@columbia.edu
Created: 26 May 2022
Last update: Fri Mar 17 07:37:58 2023
WORK IN PROGRESS

Stability and portability

For every new release of C-Kermit a top priority has been backwards compatibility, meaning that (a) anything that worked in previous releases should still work in the new one, and (b) it could still be compiled, linked, and executed on every platform, no matter how old, where it was built before. Users who depend on C-Kermit should have confidence it won't break their established usage and procedures when they install a new version.

Futhermore, C-Kermit was designed from the beginning to be portable to any computer or operating system that had a C compiler and libraries. Not just GNU Linux (as is often the assumption in the 2020s), and indeed it has been adapted over the years to every known version and variation of Unix, and also to DEC VMS (which has changed names and hands many times but still exists), Apple's original Macintosh, IBM OS/2, Data General AOS/VS, Stratus VOS, Microware OS-9, Bell Labs Plan 9, the Atari ST, and the Commodore Amiga.

As a consequence, the source code is loaded with thousands of #ifdefs, the makefile is enormous, and C-Kermit has various seemingly redundant commands (e.g. the old OPEN READ / WRITE, and the newer and more flexible and powerful FOPEN / FREAD / FWRITE / FCLOSE command family), and others could have better names (e.g. TRANSLATE should be CONVERT). In cases like this I never "deprecate" or remove the old way, I leave it intact so existing procedures continue to work, release after release, and remedy any shortcomings by adding new replacements alongside the existing stuff.

Resources for developers

Title Medium Description
Kermit, A File Transfer Protocol Book[1] Part II has the Kermit protocol specification (1987)
Using C-Kermit, 2nd Ed. Book[1] Comprehensive documentation for C-Kermit 6.0 (1997)
Using C-Kermit clickable index Web page Index to all online C-Kermit information plus supplements
protocol/index.html File list Additions to Kermit protocol since 1987 (plain-text files)[2]
kpackets.html Web page Up-to-date description of Kermit packet types and their fields (2022)
ckermit70.html Web page Manual supplement for C-Kermit 7.0 (2000)
ckermit80.html Web page Manual supplement for C-Kermit 8.0 (2003)
ckermit90.html Web page Manual supplement for C-Kermit 9.0 (2011)
ckupdates.html Web page C-Kermit 10.0 Beta Test (2022)
ckw10beta.html Web page C-Kermit 10.0 for Windows Beta Test (2022)
ckuins.html Web page C-Kermit for Unix installation instructions[4]
ckvins.html Web page C-Kermit for VMS installation instructions[4]
Changelogs File list Edit history of older versions
Archive Web page Links to source code for every C-Kermit release[3]
ck10specs.html Web page C-Kermit 10.0 specifications
ckcplm.html[4] Web page Program Logic Manual as of C-Kermit 9.0
ckaaaa.txt Plain text Overview of C-Kermit filenames[4]
ckccfg.html[4] Web page C-Kermit configuration options
ckcbwr.html[4] Web page C-Kermit "beware" file (all platforms)
ckubwr.html[4] Web page C-Kermit "beware" file (Unix)
ckvbwr.html[4] Web page C-Kermit "beware" file (VMS) (dated)
ckcsets.html Web page Character encodings supported by C-Kermit[5]
ckvariables.html Web page C-Kermit built-in variables (2019)
ckfunctions.html Web page C-Kermit built-in functions (2022)
Notes:
  1. The books are also available as PDFs
  2. Clickable list of Kermit protocol working documents never published before
  3. See notes about downloading
  4. As of version 9.0 and mostly if not completely still valid
  5. For terminal connection and file transfer, not source code or command language
Kermit protocol features introduced after 1987 include streaming, character-set conversion, numerous client/server features, the Internet Kermit Service Daemon, various negations (whoami, whatami), resumption of interrupted file transfer, locking shifts, etc.

Makefile

As of C-Kermit 10.0 Beta.03, the makefile has three main Linux targets for building on Linux (any version, any architecture) without optional security features:

  1. make linux (uses the computer's default C compiler)
  2. make linuxgcc (forces compilation with gcc) (new)
  3. make linux-clang (forces compilation with clang) (new)

These days, gcc *is* the default compiler on most or all Linux platforms, so the first two are, in effect, the same. But Clang is making inroads, and tends to want to "deprecate" constructions and idioms once perfectly legal, to the point of refusing to compile programs containing them at all. Behavior like this should not be rewarded.

Linux and many other targets often have other suffixes to include optional features; for example:

  1. make linux+ssl (include OpenSSL security)
  2. make linux+krb5 (includes Kerberos 5 security)
  3. make linux+krb5+ssl (includes both)
  4. make linux+srp (Secure Remote Password)

For many years the makefile has included 'install' and 'uninstall' targets. These are not for end users who download C-Kermit for their own use; they are more for administrators of multiuser computers, where applications and related files (such as the man page) are put in public directories that ordinary users do not have write access to. Prior to C-Kermit 10.0, these targets weren't documented properly and didn't issue the appropriate error messages when run by non-sysadmins, and also did not support relative paths or ~username notation. I don't think there is any way to fix them to work on every single platform and configuration that C-Kermit is available for, so use these at your own risk.

I had planned to write a much better and more flexible and intuitive installer myself, as a Kermit script, but more pressing issues keep coming up.

The Unix C-Kermit man page

The C-Kermit UNIX man page was thoroughly redone for C-Kermit 10.0 on 22 November 2022. There's also a pretty much up-to-date HTML equivalent on the Web, as a tutorial:
https://kermitproject.org/ckututor.html

Network protocols

C-Kermit has no support for IPV6. Nobody has complained.

This section was written before the OpenSSL code was fixed in September 2022. As of C-Kermit 10.0 Beta.05, secure HTTP (i.e. HTTPS) connections can be made after all, and C-Kermit can interoperate with Telnet and FTP servers secured by SSL/TLS, if you can find any! Meanwhile C-Kermit 10.0 for Unix still makes SSH connections through the external SSH client. C-Kermit 10.0 for Windows has its own built-in SSH client that (as of CKW Beta 4) works with all known SSH v2 servers.

Since nobody can predict what will become of SSH or what other security methods might come along in the future, as long as the text-mode terminal-to-host model of computer access survives, there will be Unix stdio clients similar to its SSH client for any future protocols, and C-Kermit should be able to use them.

File transfer protocol

The Kermit file transfer protocol is not documented in any one place, although at least as of 2 October 2022, Kermit packets are thoroughly documented in one place:

https://www.kermitproject.org/kpackets.html

The 1986 version of the protocol is documented in the first Kermit book, but there have been many additions since then (backwards compatible, of course). Protocol features added after the book and the Kermit Protocol Manual are documented in a long series of plain-text files that are collected here:

https://www.kermitproject.org/archivefiles/protocol.html

Kermit protocol areas of concern:

Packet block check
The Kermit packet block check can be one, two, or three bytes long, but there is no way to tell by looking at a packet where the data ends and block-check begins. It depends entirely on the state of protocol and the options negotiated. It would have been better to have the block-check clearly marked in each packet.
Length of filename
The file transfer protocol does not allow for extremely long filenames; the filename is transmitted in a single F-packet and if the maximum negotiated packet length won't accommodate the name, it'll be truncated. Ideally filename packets would be like data packets, where the filename would be transmitted in as many packets as necessary, and then the first data packet would signal that the entire filename had been received. This would require a new capability bit in the per-transfer negotiations and recoding of F-packet sending and reception to be like D packets. This is not an urgent problem however, because most platforms (e.g. Windows, Linux) have relatively modern limits on filename lengths, e.g. 256 characters. In Linux the maximum path name length is 4096 bytes. So any Kermit program that supports long packets (as do C-Kermit, K95, CKW, MS-DOS Kermit, IBM Mainframe Kermit) should be able to handle all existing filenames.
Recovery from packet-length misnegotiation
Occasionally there have been cases where Kermit transfers fail because the other Kermit, in the negotiation phase, declares that it can receive packets of a certain maximum length, but the declared maximum length is somewhat greater than the length it can actually accept, either because of its implemenation of Kermit, or the underlying operating system or hardware. In the case where (a) this is the first data packet, and (b) neither sliding windows nor streaming has been negotiated, it should be possible for the packet sender to "rewind" and send a smaller first packet, at least when the window size is 1, perhaps reducing the length each time a NAK is received in response, up to some limit. Worth a try if it ever becomes an issue. Of course users themselves can also work around such problems with SET SEND PACKET-LENGTH if they know about it.
Symbolic links (filename aliases)
Kermit protocol nas no way to handle file links. Both Unix and Windows use them. It should be possible to download a link as a link and have it converted to the platform-specific format on the receiver's file system. This could be done with a new Link flag in the A packet. The name of the linked-to file would have to be converted in exactly the same way as the file's name itself would be converted when it is downloaded so the link and filename match after transfer.

Character-set conversion in file transfer

Encoding of text files
Since the mid-to-late 1980s (i.e. before there was Unicode), Kermit protocol has included character-encoding conversion for text files, supporting more than 50 different encodings, a mixture of proprietary corporate, national standard, and international standard; click here to see the list. It would be nice to think that Unicode has made these obsolete and we don't need to bother with them any more, especially the quaint 7-bit and 8-bit single-byte sets for different languages and applications. But the massive installed base of of files in old encodings must be considered; the information they contain is not automatically worthless because they don't have the latest encoding. Kermit, of course, can convert them to Unicode, either in transfer, or in place. And for that matter, Kermit lets you view or work with the old files because its terminal emulator supports the old character sets.

But in the 21st Century shouldn't we at least make UTF-8 the default file transfer encoding for sending files??? This could simplify matters enormously, but it presupposes that all Kermit file-transfer partners support character-set conversion and UTF-8 (they don't). So this would work for C-Kermit (including the Windows version) but MS-DOS Kermit and all older Kermit programs would be left out, so C-Kermit would have to keep the previous methods available, and users who want to make UTF-8 their default transfer encoding can simply put SET TRANSFER CHARACTER-SET UTF-8 in the Kermit startup files (e.g. ~/.kermrc on Unix). Anyway, the default transfer character set has always been TRANSPARENT, and nobody has complained about it yet. So for now it seems best to leave it as is rather than risk breaking transfers that worked before.

Encoding of filenames
While the Kermit protocol can convert text files from the sender's encoding to the receiver's, it has no such mechanism for non-ASCII filenames. From the very beginning to the present day filenames are copied from sender to receiver byte-for-byte, although if the bytes are in the ASCII range some conversion (e.g. of upper and lower case, or converting space to underscore) might take place. But if the name contains non-ASCII characters and the receiver uses a different encoding from the sender, the filename on the receiver will be different from the sender's name; for example a file named "Grüße" on the sender might be stored on the receiver as "GrüÃ\237e".

Even if we assume that filename has the same encoding as the file contents (if it is a text file!), the filename packet arrives at the receiver before the Attribute packet(s) that specifies the transfer encoding. The file receiver could defer creating the file until after the Attribute packets (if any) have been received, i.e. when the first Data packet arrives, or in the case of empty files, the EOF packet. That's a lot of ifs! Anyway with that method all bets are still off with binary files, or (worse) with binary-mode transfer of text files, which is the rule for transfers between like platforms such as Unix-to-Unix, VMS-to-VMS, or Windows-to-Windows. Conceivably some new protocol could be added for the sender to convey the encoding of the filename being sent, but how would sender know what the encoding is? Filenames are too short for statistical analysis of their distribution of byte values. The user likely doesn't know the encoding either. At this writing (2022) the situation is chaotic. Any computer might have text files in a variety of encodings, and the encoding is not identified in the file information APIs of any OS I know about. A special case might be Windows XP and later, in which (supposedly) all filenames are UCS-2. But are they? And how is a file sender supposed to know that the receiver is Windows XP or later? The whole point of Kermit protocol is that no program needs to know the OS-specific quirks of the computer on the other end of the connection.

In short, dealing with different encodings of filenames is an ENORMOUS CAN OF WORMS, and the only solution (for Kermit and any other file-transfer method) is to use only ASCII printable characters in filenames until such time as the whole world uses only one character encoding like some form of Unicode. Even then, however, there will remain a vast legacy of non-ASCII files from the 20th Century. Kermit can handle them as long as their filenames are (a) ASCII and (b) not ridiculously long.

Interactive command parser

Kermit's command parser is modeled on the DECSYSTEM-20 Exec (that is, its interactive text-mode user interface, similar to the Unix shell, but much less cryptic). It's user-friendly, has features like abbreviation, completion, and context-sensitive per-field help when '?' is typed. But it does not allow in-line editing (e.g. nondestructive backspacing), which most people expect these days (Emacs or Vi style control characters). Even without that, Ctrl-T would be handy to swap the last two characters typed.

In-place line editing could be done in ckucmd.c: gtword(). If the user moves the cursor back into the buffer, stay in gtword() until they go to the end or type CR, then exit with reparse flag. The editing is not so difficult but showing it on the screen drags in a lot terminal features not used before. Presumably this would be handled via calls to the curses library (cursor back, insert character, etc) or in the case of C-Kermit for Windows since it *is* a terminal emaulator.

Maybe allow any command to have '|' and '>' suffixes like the Unix shell (most REMOTE commands already have them): to pipe the command's output to another process or redirect it to a file. Also || to test if the command failed and execute some action if it did (in place of having to write an IF FAILURE command on a separate line). This would be familiar to Unix shell programmers and (in spirit only) to SNOBOL programmers (where statements can have a "failure" clause).

C-Kermit's line continuation character is '-' (hyphen). Maybe '\' (backslash) should be accepted to, since is what Unix shell users would expect.

Allow commands in scripts (macro definitions) to end with ';' like in C? Of course scripts written in this way would not work in older C-Kermit versions, so the original syntax must also be recognized. Presently the comma is overloaded (command separator in the internal representation of macro definitions, field separator in function calls). But if each command was terminated by ';', there would be no need for line-continuation syntax, it would be just like C. But if ';' was to be used as command separator, it would have to appear at the end of every command.

Macros

The "Macro" concept is overloaded. At first it (on the DEC20 in the 1980s) was simply a way for the user to create a command that executed a series of commands. In C-Kermit this concept was extended to be like a subroutine or function call, with parameters passed by the caller and (optionally) returning a result for the caller's use. Such a macro is invoked by the DO command, and for convenience, the "do" can be omitted and the macro's name can be typed at the prompt (or included in a script) just as if it were a built-in command. So far so good.

Meanwhile, C-Kermit already had a small repertoire of variables: \%1, \%2, ..., \%9 intended for passing values to macros, and \%a, \%b, ... \%z for other uses. Since this set was so restrictive, it became evident that an unlimited number of variables could exist at once by defining them as macros; for example:

define alphabet abcdefghijklmnopqrstuvwxyz
But a notation was required to refer these macros that were really variables, and \m(name) was chosen: \m(macroname), e.g. \m(alphabet).

The problem (not a big one, to be sure) is that C-Kermit doesn't know if a particular macro is a variable or a procedure. So, for example, if you type "do ?" at the C-Kermit prompt you'll get a list of all defined quantities, both procedures and variables. But again, no big deal.

C-Kermit script language

Suppose you want to TAKE a script file in a loop. The loop variables can easily be clobbered by the script. How can the script know this? The TAKE command should be able to isolate itself from side effects of the script. Workaround: Instead of TAKE, use RUN. Workaround 2: Declare all veriables in the inferior script to be LOCAL.

There's no good way to assign a complicated list of files to an array. Syntax limitations of function calls prevent the use of {foo*,*.txt} notation in \ffiles(). ADD SEND-LIST is the perfect thing for this but there's no way at command level to convert the the send-list to an array. (This could be fixed without too much effort.)

Add SET COMMAND ERROR-HANDLER applying to any command that fails, no matter whether it's in a TAKE file or a MACRO, with a default value of something like: exit 1 Fatal: \v(lastcommand): \v(errstring), but it could be the name of a macro to invoke or anything else C-Kermit can execute.

C-Kermit has no ability to do hex or octal calculations except by using \fradix(). Regular arithmetic should allow the hex and octal notation that C-Kermit already supports:

.sum ::= \x20 + \o33
increment sum \xFF

It might be desirable to read the lines of a file into an array; this would require a new ARRAY LOAD command. Currently this requires FOPEN /READ, an FREAD LINE loop, and FCLOSE.

It's annoying to have to put dashes in array initializations. Example, an array of URLs:

dcl \&u[] -
    ftp://kermit.columbia.edu/kermit/ -
    ftp://ftp.columbia.edu/kermit/ -
    ftp://www.columbia.edu/kermit/ -
    ftp://kermit.columbia.edu/pcfonts/ -
    ftp://kermit.columbia.edu/packet-drivers/ -
    ftp://kermit.columbia.edu/mm/ -
    ftp://kermit.columbia.edu/utils/

Here's a nonobvious trick that works: define the list as a multiline macro (which is itself represented internally as a comma-separated list):

define ftplist {
    ftp://kermit.columbia.edu/kermit/
    ftp://ftp.columbia.edu/kermit/
    ftp://www.columbia.edu/kermit/
    ftp://kermit.columbia.edu/pcfonts/
    ftp://kermit.columbia.edu/packet-drivers/
    ftp://kermit.columbia.edu/mm/
    ftp://kermit.columbia.edu/utils/
}
# Then turn the list into an array -
# break characters are comma and space:
#
void \fsplit(\m(ftplist),&a,\44\32)

But this doesn't solve the general problem of how to define a macro whose value is a formatted block of text, e.g.:

define formletter {
Dear \%1,

   This is to inform you that...
blah blah blah blah blah blah...
}

The same trick won't here because leading spaces and blank lines are squeezed out. A whole new data object would need to be created, and a new command to define it, and new notation to refer to it.

Error messages in scripts

WE REALLY NEED a better way to report errors in scripts. Fixing this would require a massive rewrite of the parser along these lines: Each command file or macro is an array of lines, so "get next command" just toodles through the array, much easier and safer than parsing commas. When the last command is reached (or STOP, or END), we pop the stack. TAKE or DO commands create and enter a new stack level (local array). Command files and macros can be handled the same way. A separate global array is indexed by stack level, each element tells what occupies that level, its name, its current status (or exit status), and the "program counter". When there's an error, we can get the specific command that caused it and its line number in the source file.

The GET command should recognize a URL (http(s):, ftp:, or kermit:) (there is already code for this in the "ftp command-line personality")

Possible problems

Mac OS (macOS) filenames are case-folded. Kermit doesn't know about this, e.g. for detecting filename collisions.

Built-in functions

\ffiles() only lists regular files, not directories; ditto \frfiles(). Need another bitmap argument to specify which kinds of files to list:
  • regular files
  • executable files
  • directories
  • links
plus maybe another new argument after that: an exclude pattern (e.g. ~.\fspan([09]~$, i.e. EMACS backup files)

\findex() doesn't have a case argument, ditto for many other string functions that could use them.

There is no SHOW CASE command.

The DIRECTORY command

To add... DIRECTORY /RECORD-FORMAT show whether file is text or binary, and if text, LF or CRLF, and perhaps also the encoding. Lots more info in VMS.

Make DIR /PUBLIC - only show what is publicly readable. By the same token DIR /PRIVATE.

DIRECTORY /ARRAY includes both files and directories but lacks an EXCEPT: switch, e.g. for filtering out backup files.

DIR /ARRAY:&a /SORT:DATE *.jpg creates array in lexical order, not date order.

Also... DIRECTORY /FOLLOWLINKS doesn't follow links, it shows them symbolically, e.g. "foo -> bar". Exactly the same as when /FOLLOWINLINKS is not included.

Bug:

[C:\Users\fdc\Desktop\] CKW> dir ckuath.c (which does not exist)
?No files match - "/*" <-- ???

(it should say '?File not found - "ckuath.c"' or if wild '?No files match - "ckuath.c"'). This bug did not exist in C-Kermit 9.0 I tried to pin it down by adding a code to all "No files match" and "File not found" messages, but code the never appears.

ckucmd.c: printf("?XX1 File not found - %s\n",*xp);
ckuus3.c: printf("?XX6 No files match - \"%s\"\n",line);
ckuus6.c: printf("?XX4 No files match: %s\n",brstrip(atmbuf));
ckuus6.c: printf("?XX2 File not found: %s\n",brstrip(atmbuf));
ckuus6.c: printf("?XX5 No files match: %s\n",brstrip(atmbuf));
ckuus6.c: printf("?XX3 File not found: %s\n",brstrip(atmbuf));
ckuusr.c: printf("?XX7 %s - \"%s\"\n",
ckuusr.c: "XX7 No files match" : "File not found",

I took the codes back out. Also looked at a debug log and at dodir() and domydir() code; can't find where the message is coming from. I didn't have time for another rabbit hole so I gave up.

Additional commands or features

COPY and RENAME needs switches for FILES only, DIRECTORIES only, or both. Maybe also LINKS.

COPY needs an /EXCEPT switch.

Add a way to declare an FREAD file to be card images and to define the fields. Each FREAD fills an array. FREAD /CARD:xxx \%c &a[], where xxx defines the fields (like a Hollerith string, for old time's sake).

A way to fix files that contain a mixture of ISO-8859 or UTF-8 and Windows "smart quotes", like when you copy a Web page or email message and paste it into EMACS. This could be a C-Kermit command or a script.

Add Iridium modem type; they still use 'em for satellite communication.

GET and RECEIVE command improvements: GET /PERMISSIONS:xxxx; RECEIVE /PERMISSIONS:xxxx; and maybe SET RECEIVE PERMISSIONS xxxx; GET /UPDATE (only accept newer versions); GET /COLLISION:xxx (ditto receive).

SEND /UPDATE, which would tell the receiver to SET FILE COLLISION UPDATE for this transaction only. But this would require both sender and receiver to have a new protocol feature to handle this.

REMOTE SET FILE COLLISION OVERWRITE from C-Kermit client to K95 server gets an error "Unknown REMOTE SET parameter". Ditto UPDATE, and probably ditto anything else. REMOTE SET FILE COLLISION OVERWRITE with no option does not get an error but it doesn't change anything either. Does this have anything to do with ENABLE/DISABLE? There's no associated command.

Add a command that searches for \v(variables) whose *values* match a given pattern (SHOW VARIABLE xxx shows variables whose names match xxx).

Add ARRAY SORT /DATE (for an array of dates).

Image processing

For the Photogallery script some facilities were added for "parsing" JPG files to get dimensions, orientation, date taken, etc. These are pretty jerry-rigged, the right way to do it is to actually navigate and parse the Exif structure. Later, support for GIF and PNG images was added, but with no way to get their data except (in most cases) to ask the external ImageMagick 'convert' utility. Libraries exist for this purpose — libjpeg, libgif, libpng and makefile targets like 'linux' could test for them ("if ld -ljpeg ...") and add the appropriate definitions to KFLAGS (HAVE_LIBJPEG, HAVE_LIBGIF, HAVE_LIBPNG) to govern any code added to make use of them.

STILL UNSORTED....

Bug: GETOK (which prompts the user to enter Yes, No, or the equivalent to a question) no longer gives help when '?' is typed. It used to!

IF MATCH doesn't always work. IF MATCH could detect whether it's a floating or anchored pattern, no? Right now anchored patterns don't work. Just check for ^ at front or $ at end... Or make a function that can specify floating or anchored as a parameter.

Add MATCH /switches pattern string - succeed or fail switches can be for case, etc.

C-Kermit's IF MATCH string pattern is less than perfect.

C-Kermit's patterns (wildcards) are not regular expressions. They are based on the file matching features of Unix ("man 3 glob", "man 7 glob") -- particularly C-Shell and Bash -- and various DEC operating systems from the 1970s-90s: TOPS-10, TOPS-20, VMS, etc. There is no support for Gnu-style regexps anywhere in C-Kermit. C-Kermit's wildcard notation is described by the HELP WILDCARDS command.

So maybe replace the homegrown handmade pattern matcher with glob library calls? Of course this would only work only in Unixes that had glob libraries. No, bad idea. Glob is only for matching filenames, not text in general.

A new \fmakeurl() function that does what Javascript encode() does: hexifies non-printable-ascii bytes (and space), leaves printable ASCII nonspace characters as-is.

SET HOST /TIMEOUT was never implemented, some people have need of it.

Add PNG to getpictureinfo(). Maybe add animated GIF test to getpictureinfo(). If there were libjpg, libping, libgif, etc, packages Kermit could just use those; they do exist but they are usually not installed.

Is there any reason why there can't be named arrays? we know the name starts with & and ends with [..]. Actually, no, it doesn't always end with [..], array names (like &a are valid in certain contexts.

Redo the HELP command to to do its own formatting, instead of having fixed-length strings in the code, to make it scale automatically to screens of different widths, and add an APROPOS command that could search through all the help text.

Or... Move all HELP text to an external database that allows searching, localization, and includes escapes for substitutions, selections, etc. Use \v(xxx) constructions in the text itself, and pass the text thru zzstring. (This is not a good idea because it's too easy for the executable and the help database to get separated or out of sync)

"type d*.log" works even if more than one file matches.

Make HELP look in alternative keyword tables: SET, FUNCTION, ...

Make SHOW HIST display the buffer size.

The zfnqfp() struct should include some info fields -- at least an isdir() bit, since it calls isdir() it might as well pass along the result to avoid additional isdir() calls. But this would require changing Unix, K95, VMS, VOS, and DG.

SET TERM TRIGGER is always case-sensitive. There should be a way to make it case independent, e.g. for "charset=US-ASCII", "CHARSET=us-ascii", ...

cmfld() should be able to parse \fsexp(+ 1 1) as a single field without needing quotes around it??? ← This works in C-Kermit 10.

Use \v(exedir) to find init file? No, \v(exedir) is not secure, because argv[0] is unpredictable and can probably be spoofed. In which case, a malignant .kermrc could be executed.

When sending a UCS-2 file between like systems, is it OK to use binary mode? (Because of peer recognition?) Or should we switch to Text mode and send as UCS2-BE, swapping bytes if necessary? This would only be an issue for (e.g.) Linux/PC (LE) to Solaris/Sparc (BE), both Unix. Probably a moot question at this point; UTF-8 is always used on the wire as far as I know.

When built with Unicode support (as it is by default), the Unix version inherits all the K95 terminal emulation translation tables and functions, which take up a lot of space, but it has no way to use them. Since the stuff is all there anyway, why not use it, at least in the TRANSLATE, COPY, and CONNECT commands? This would mean (at least) changing the keyword tables to use the one from ckcuni.c instead of the file or terminal charset table from ckuxla.c, and then changing x[gp]nbyte() to use ckcuni.[ch] charset indices, rather than ck[cu]xla.[ch] ones. But then what about file transfer?

In \freplace(a,b,c,n), allow n to be a range, like 3:7, to replace occurrences 3-7 of b in a with c.

Did You Know: writing into successfully malloc'd memory can cause SIGSEGV (seg fault) if the OS uses deferred allocation (create page on first write) and swap space is full.

File-transfer display... If terminal height is greater than 24, put more stuff on file transfer display. In particular: if it is a multifile transfer, add a second thermometer line so there is one for the current file and another for the entire file group. But this would also require a change to the Kermit protocol, in which the sender informs the receiver of the number of files that will be sent and their total length. The sender could do this without any protocol changes.

Make SET TAKE (and MACRO) ERROR ON automatically do the equivalent of: exit 1 FATAL ERROR: [\v(lastcommand)]

In Unix, SEND /NOBACKUPFILES should also skip #blah# files

C-Kermit can't TAKE a command file that contains UTF-8 text, even as comments: "?Error in TAKE command file: Line too long or contains NUL characters". But I can make it work if I do some combination of: set file character set utf-8; set terminal character set utf-8; set locale utf-8. Still, C-Kermit shouldn't freak out when executing a TAKE command and it finds UTF-8 in a comment. NOTE: FOPEN /READ has no problem with the same file, and neither does TYPE.

Note in docs and help text that FREAD /TRIM trims from the right only. Maybe add FREAD /TRIM:{LEFT,RIGHT,BOTH}, with RIGHT being the default. Maybe also add FREAD /SQUEEZE.

Handle failure something like shell; in addition to:

cd ~/public_html/postal/
if fail exit 1

allow:

cd ~/public_html/postal/ || exit 1

add this to "remcmd()" which already supports some Unix pipeline-like syntax for REMOTE commands.

Allow a Unix-like redirector (> or >> or 2> or |) at the end of each command; do it in cmcfm(). Didn't I already do this for REMOTE commands? Yeah, see (for example) REMOTE PWD. The code is in remcfm() in ckuus7.c; it should be moved to cmcfm() to be available for all commands.

Actually it's different, right? remcfm() is redirecting the decoded contents of incoming Data packets, whereas in the general we want to redirect stdout for the duration of the command.

Check this: If FSEEK /FIND doesn't find its target it winds up at EOF but returns SUCCESS? If true, fix it to fail.

Change GREP /NOMATCH to accept an argument, which, if given, causes the target string to be matched only if the line also does not contain the NOMATCH string.

\fcvtdate() format for date with month spelled all the way out in the language and charset of the current locale.

\fcvtdate() needs a new argument saying what to return: 0 (date-time), 1 (date-only), 2 (time-only), to make it easier to write IF commands that test the date *or* time.

\fcvtdate() a new argument which is the yyyy-mm-dd separator.

SET LOCALE doesn't affect non-numeric date-related \v() variables like \v(date), \v(day); they are hardwired to English. However the functions \fmonthname() and \fdayname() return the Locale-appropriate names.

Add \fcenter(s1,n1,c) to center string s1 in a field n1 chars wide.

Add \fdateinfo(date,&a), which populates the array with: Numeric day of month, Numeric day of week, Numeric day of year, Numeric week of year, Numeric month of year, Numeric year, Abbreviated day of week name, Full day of week name, Abbreviated month name, Full month name, 12-hour hour, 24-hour hour, Minutes of hour, Seconds of minute, Seconds since midnight, AM or PM, in which names are in the current locale.

Kermit DIR /ENGLISHDATE doesn't use locale. Should add /LOCALEDATE.

C-Kermit's commands (and source code) are composed exclusively of 7-bit ASCII for maximum portability in both space and time. However, non-ASCII characters can be used in macro definitions and even in macro names:

(~/) C-Kermit>define Grüße echo Hi
(~/) C-Kermit> Grüße
Hi
(~/) C-Kermit>

But then (obviosly) the macro invocation must be in the same coding system that the macro was defined with.

Kermit's explicit support for many character sets, including UTF-8, covers only terminal emulation and file transfer. But not (e.g.) scripting: for example, what do \fcode() and \fchar() do with UTF-8? Probably nothing good!

If you write a script that contains non-ASCII text in ISO-8859-1, don't expect it to work in an environment where other encodings are used.

FSEEK command: Shouldn't FSEEK /FIND default to "from current position"? Make it clear in HELP text that the first FREAD after a successful FSEEK reads the line that was found.

Transferring files with non-ASCII characters in their name: C-Kermit already does the right thing; it treats the file name just like the file contents, converting them both to the receiver's file character-set.

SEXPs - function that writes big number in human notation like 1,000,000 and maybe also a regular \function() to do the same.

SEXPs need (_INCREMENT ) to be like _INCREMENT, ditto _DECREMENT maybe also _SETQ and _LET

And there's no looping in S-Expressions.

S-expressions: (echo '(1st-year rent) oneyear (round (* 12 oneyear) 2)) (echo '(some other string)) The second echo causes a parse error.

\v(month) has a trailing space: K>echo [\v(month)] [Aug ]

RENAME needs a /TOUCH switch to update the modification date (for photogallery).

Add TOUCH /FROM:filename to copy the modtime from that of a given file. And maybe if filename is a directory name, take date from the corresponding files (if any) in that directory. This is really just:

TOUCH /MODTIME:\fdate(file1) file2

Make TOUCH /MODTIME: recognize all the date-time formats CK knows about, not just the all-numeric ones.

STATISTICS /VERBOSE doesn't show files refused / skipped

grep /array:&a puts the filenames into the array instead of the matching lines that are shown without the /array switch. To fix, allow two arguments: /array:{{&a}{%b}} - the first for filenames, the second for lines; this would be backwards compatible. Alternatively (too much magic) make it put lines if grepping one file and count if grepping > 1.

Non-obvious shortcoming of \fsplit() and \fword(): They put their results in an array but array elements are evaluated recursively and if a result has a backslash... This is now handled by SET VARIABLE-EVALUATION SIMPLE (which is the default in C-Kermit 10.0 and later).

send /except{{subdir/}{anothersubdir/}} doesn't work. But /except{{subdir/*}{anothersubdir/*}} does work.

query directories(name) doesn't seem to work, e.g. when server's current directory has a subdirectory called 20190409 and the command is query kermit directories(20190409). but query kermit directories(*) seems to work ok.

\fcvtdate() needs another argument to specify whether the result is date-and-time, date-only, time-only, and maybe others like day-of-week.

ALSO... \findex() really needs an argument for case sensitivity But then this raises issues with non-ASCII strings.

A big drawback of backing up from Unix to Windows is that symlinks are lost, maybe there should be a filename transformation rule. Ideally, there would be a new file type besides text and binary.

When receiving files why is K95 saying it's converting them to UCS2??? (this is a hornet's nest, best not to poke it)

File transfer commands should skip messages like this if a /quiet switch is included: Return to your local Kermit and give a RECEIVE command. KERMIT READY TO SEND...

It is impossible to define or assign a value to a variable if the definition contains literal tabs. This is because at the very lowest level, the command reader converts tabs to spaces. Example: .line = a b c # (the wide spaces are tabs) void \fsplit(\m(line),&a,,TSV) show array a Result has only one element, not 3. Have to use \9.

NOTES.TXT says "Discovered that the result returned by \fsearch() is totally unreliable. This is probably too hard to fix." (26 Jan 2010) Maybe it's worth another try.

FOR loops truncate floating point loop variables to int; it should be pretty easy to make FOR loops with with floating point numbers.

INCREMENT and DECREMENT don't work with floating-point numbers

File-transfer: Maybe show transfer rate as Kbps, Mbps, or Gbps

Make a function to format large numbers with commas, periods, or with KB, MB, GB, TB etc. Or as x.yyM, B, etc. For this use locale?
426426936 -> 4.26M; 426,426,936; 406.67MB; 4.264E8

SET HOST * should print IP address of '*'

ARRAY SORT: could allow any number of secondary arrays to be sorted.

C-Kermit 4.x (the original mid-1980s version) sent a very short S-packet, like: ^A, Sz* @-#Y1~^^M. Does a C-Kermit 10.0 receiver accept it? Yes. This was tested by using "set send negotiation-string-max-length 8" at the C-Kermit sender.

In in file transfer display for SEND /DELETE, put "Local copy deleted OK" Or "Transfer OK - original deleted", something like that.

Make new function: \fdecodeqp() for decode quoted printable.

.blah = 3 IF NUMERIC blah doesn't work Have to do IF NUMERIC \m(blah) <-- is this reasonable? Yes, because non-\() macro invocations only work in numeric fields, but the IF NUMERIC argument can be anything, and then the command tells whether it's a number.

There is no way to refer to top-level \&_[] from inside a macro because it becomes the macro argument vector. So macros can't refer directly to top-level script arguments (this could be fixed by adding a notation to refer the the top of the call stack). Also, it seems that writing into this array can cause core dumps. Best to treat it as read-only and use ARRAY COPY at top level if the command-line args need to be accessed from inside macros.

LOCAL scope is not exactly right. It should be possible to declare ALL variables local. It should be possible to initialize variables in LOCAL statement, e.g. LOCAL foo=bar baz=zzz It should be possible to prevent export of local variables to to subordinate macros or TAKE files. Actually this could be done by having the subordinate macros or TAKE files declare LOCAL ALL. The problem is that if A executes B in a loop, and A uses a variable V, even if it is declared LOCAL, then if B also uses a variable V, it will be the same one, and it can change it out from under A.

Similarly... FCLOSE ALL in a subordinate TAKE file will close any files opened by the superior one. BAD! This should close only those files opened at cmdlevel or below. (Hmmmm, think about this.) At least put some kind of warning in the docs.

\ffiles(/tmp) returns the number of files *in* /tmp, not 1 or 0. BUT CHANGING THIS COULD BREAK SCRIPTS. <--

We have REMOTE ASSIGN, what about REMOTE DEFINE???

SET FILE COLLISION doesn't take RECEIVE MOVE-TO or RENAME-TO into account.

Add SET TRANSMIT PACING (intercharacter pacing) and TRANSMIT /PACING:.

How do you force a kerbang file to NOT execute the init file?

C-Kermit does not have a way to delete files recursively without also deleting directories.

Make a BASIC-like ON_ERROR (macro to invoke if any command fails that does not have an IF FAIL/SUCCESS after).

Make SHOW MAC use getncm() to show lines of macro.

The makefile has an 'install' target that I have never used nor paid much attention to. I have no idea how useful it is (or isn't). I think most Kermit installations are either done by Linux package distribution mechanisms, or else by hand.

The makefile doesn't work well for cross compilation. The rule: "./wart ckcpro.w ckcpro.c" tries to run the wart binary it just built, which of course won't work because it is for some other platform. If there was a wart in the PATH we should use that instead, but how to test for it? Alternatively, don't make ckcpro.c depend on wart and ckwart.c?

Problem: some kind of drill press or something has an embedded Kermit program that sends filenames that contain slashes. These are part of the filename and are not supposed to be directory separators. If you tell the receiver to SET RECEIVE PATHNAMES OFF, you lose the information that was in the filename and possibly create conflicts (e.g. one/bit, two/bit), but if you leave them on, Kermit creates directories. I thought there might be a way to use SET FILE NAMES CONVERTED to get around this but no, Kermit would have to be a mind reader. The only way around this one is with templates, e.g. "receive /as-name:\freplace(\v(filename),/,-)", except this doesn't help when in server mode.

COPY /REMOVE-CR's or somesuch. Everybody wants to be able to convert CRLF to LF (or v.v.) but only Kermit will know how to do this for only text files and skip binary files. COPY /CONVERT:{LF/CR/CRLF}...

Make command recall work for commands that have become invalid since they were last executed (e.g. "delete foo.bar"). I tried this once, it's very difficult. Tabled for a future release.

Add (Main)SAIL-like methods of loop exit: exit multiple loops / blocks at once, and possibly also set an exit code at the same time, so an IF statement at the end of the loop can test success/failure.

:label { FOR, WHILE, SWITCH } { }

A FOR, WHILE, or SWITCH command remembers if it was immediately preceded by a label, and what the label was. This is done by creating a "loop-stack" of:

,

Then:

BREAK [ value [ label ] ]

searches the loop-stack for the variable and, if found, pops back to the associated cmdlevel, setting "success" according to the given value.

Default value is 0, default label is "this loop".

CONTINUE label

CONTINUES the FOR or WHILE (but not SWITCH) statement having the given label. In this case, it peels back to cmdlevel - 2 and executes the GOTO .._BOT command (???)

Finally, loops should should have a default exit status: 1 (FAIL) if exit was because was no longer true, 0 (SUCCESS) if BREAK given with no argument.

The problem with all this is that BREAK and CONTINUE are presently implemented as macros that translate to GOTOs. BREAK blah could be translated to GOTO blah+1 (but offsets in GOTO labels would need to be implemented). CONTINUE, however, would need to be redone.

Get rid of wart(). Replace with a bunch of case statements like if (state == blah || state == blah) { x = input(); switch (x) { } } Why? To eliminate a lot of redundant code when the action for a given state is (almost) the same for different inputs, etc, and also to make it clearer to a C programmer.

TAKE /NOSHARE to prevent a new command level from stomping over higher levels definitions.

Kermit is good at sending big files. What if somebody needs to send thousands of tiny files? Performance takes a nosedive.

Add a SHOW command for each SET command?

Let user SET the command-editing characters: SET COMMAND { CHARACTER-DELETE, WORD-DELETE, LINE-DELETE, REDISPLAY } ...

. Internationalize: . Segregate all message strings into a separate module, to allow translation into other languages - a "resource file"? Use xstr. Complicated because many different character sets can be used for each language. . Make string comparisons and "tolower"/"toupper" work with int'l character sets (inlcuding in INPUT/REINPUT). . Fix \v(date) to report date in different languages, formats. . Fix \v(ndate) to handle non-English month names. . GETOK command answers: Yes, Ja, Si, ... . etc etc.

+++++++++++++++++++++++++++++++++++++++