FILE CKU178.UPD

Author:  Frank da Cruz
Address: Watson Laboratory, Columbia University Center for Computing Activities
         612 West 115th Street, New York, NY 10025, USA, Earth
Phone:   (212) 854-5126
Fax:     (212) 662-6442
E-Mail:  fdc@watsun.cc.columbia.edu (Internet), FDCCU@CUVMA (BITNET/EARN)

  Copyright (C) 1985, 1992, Trustees of Columbia University in the City of New
  York.  Permission is granted to any individual or institution to use this
  software as long as it is not sold for profit.  This copyright notice must be
  retained.  This software may not be included in commercial products without
  written permission of Columbia University.

Last update: Wed Jan 29 23:22:14 1992

This file contains the update history of C-Kermit 5A from its beginning
to the end of the pre-beta test period.  History of pre-5A versions can be
found in CKUV4E.UPD and CKUV4F.UPD.  Edit history of the 5A beta release
is in CKUKER.UPD.

UPDATE HISTORY:
==============

------------------------------
5A(178) Wed Jan 29 23:22:14 1992

Test for TELNET <host> <service> was backwards in setlin().  ckuus7.c.

Extraneous "#include <sys/types.h>" in ckufio.c moved to within #ifdef OS2
conditional.

Sent the above two fixes to the list in e-mail.

Changed name of KOI-8 from "koi-cyrillic" to "koi8-cyrillic".  ckuxla.c.

Fixes to zmail() and zprint() for Olivetti OXOS, which uses mailx and lp
rather than Mail and lpr.  Fulvio Marino.  ckufio.c

Fixed error in TRANSMIT command help message reported by Christian Hemsing.
ckuus2.c.

Fixed erroneous declaration of "c" in SHOW KEY -- should be int, not KEY.

Many SCO Xenix changes from Warren Tucker and William Bader.  ckuver.h,
ckufio.c, ckutio.c, makefile.

Added OS/2 changes to support "set speed 57600", adapted from code furnished
by Kai Uwe Rommel.  ckuus3.c, ckotio.c, ckocon.c.

Fixed two places where some SCRIPT-command-related code was added without
putting it in #ifndef NOSCRIPT..#endif, reported by Jay Rouman.  ckuus5.c.

Moved several unguarded references to character-set related variables to
within #ifndef NOCSETS..#endif, or removed them where not needed.  Many
ckc*.c and cku*.c modules.

Changed ckcxla.h to skip itself if NOCSETS is defined, and to make sure
that CYRILL and KANJI are not defined, in case of conflicts on the cc
command line, like -DNOCSETS -DKANJI.

Added -DDYNAMIC to hpuxs5r3 makefile entry.

In response to persistent complaints about slow screen updating on the NeXT,
added a -DNOSETBUF compiler option to remove the setbuf() call that makes
console output be unbuffered.  This definitely clears up the slow-writing
problem, but there may be other risks -- the setbuf() call has been there
forever, and who knows what might break by removing it.  Local testing on NeXT
and SUN found no ill effects, so it was added to the sunos41 and next make
entries.  So if you want to improve performance a bit, try adding this option
but then test the results thoroughly.  ckutio.c, makefile.

Saved and restored duplex setting around telnet sessions.  ckuus7.c.

Finally solved Joe Doupnik's strange problem: if you "set host" from C-Kermit
on his PC SV/386 R4 system, giving a hostname, you get an apparent successful
connection, but then a blank screen.  Diagnosis: When a service is not
specified by the user, Kermit supplies "telnet".  The TCP/IP implementation
on Joe's machine, of Wollongong lineage, returns an incorrect value for
getservbyname("telnet"): 111 (which is SUN RPC) rather than 23 (which is
TELNET).  So Kermit, sensing that it has not reached a TELNET socket, sets
a flag saying "no negotiations".  Solution: make the default service be
"23" rather than "telnet" so the call to getservbyname() is skipped.

Big change: added ANSI escape sequence recognition to the CONNECT command.
This was necessary to prevent character translation within escape sequences.
The code is compiled by default (include -DNOESCSEQ to remove it) (it is also
excluded automatically by -DNOCSETS).  It is activated only when the local or
remote terminal character set is a 7-bit set other than US or UK ASCII, for
example the Swedish ISO 646 NRC.  ckucon.c, therefore UNIX only.  Note: ONLY
ANSI sequences are supported: not H-P, Televideo, etc etc etc, for reasons of
space, complexity, performance, and standardization.

Added some HP symbols for SHOW VER and \v(cpu).

Updated VMS C-Kermit CONNECT command to current level: ANSI escape sequence
recognition, character-set translation bugs fixed, etc.  ckvcon.c

Tried to make C-Kermit telnet work successfully to an HP-UX telnet server
(also Wollongong based).  Each change I made that fixed this problem broke
telnet for everyone else (especially the NeXT telnet server).  Finally, I
totally rewrote TELNET negotiation code (again) to accommodate the situation
where a telnet server (like the one on HP-UX) does not send any negotiations
until after login.  This amounted to: (1) Starting out with duplex set to
remote but sending DO ECHO to the server right away (this is different from
UNIX telnet, see next paragraph); (2) not sending any gratuitous DO or DONT
commands; (3) simplifying the treatment of received DO ECHO, DONT ECHO, WILL
SGA, and WONT SGA commands; (4) Never sending unnecessary replies.  ckcnet.c.

A big cause of problems in Kermit's telnet code was the way the lower CONNECT
fork would be killed and restarted every time echoing had to change.  This
could cause data (including negotiations) to be lost.  CONNECT was changed
to have the lower fork simply signal the upper one, to coordinate echoing
changes.  Now, if need be (i.e. if new telnet problems are reported), we can
start off in local-echo mode, knowing that the immediate change to remote echo
won't cause us to lose the other negotiations and the login banner.  The 
SUNlink X.25 code still restarts the lower fork, probably unnecessarily, but
I don't want to change this without being able to test it.  ckucon.c.

Found that C-Kermit doesn't transfer files with Honeywell GCOS-8 Kermit,
because the latter does not put a terminator on outgoing packets.  It has a
"set sendeol" command, which apparently does not work.  So (in the UNIX
version only, and only if the PARSENSE (automatic parity sensing) feature is
selected), I added code to ttinl to read the packet length and use it if a
line turnaround handshake character is not defined.  I had to add a sixth
argument to ttinl (again, only for UNIX): a flag to tell whether the
"end-of-line" (eol) character is a turnaround character or a regular eol.  If
it is a turnaround character, behavior is as before.  If it is an eol, ttinl
reads the number of characters specified in the length field and returns
immediately, without waiting for the eol.  If an eol comes, it is skipped over
when ttinl reads the next incoming packet.  This has the added benefit that
packets are no longer ignored if the eol is garbaged in transmission.  Tested
with MS-Kermit, Honeywell GCOS-8 Kermit, IBM mainframe Kermit in linemode, etc
-- seems to work fine.  ckutio.c, ckcfns.c, ckcdeb.h.

Also built without PARSENSE defined.  Works fine (i.e. as it did before).  The
PARSENSE feature is available for the UNIX, VMS, Mac, OS-9, and Amiga
versions, but not the OS/2, version -- this code needs to be added to
ckotio.c.  Also, the new length-reading code needs to be added to all but the
UNIX version of ck?tio.c.  After that, the #ifdef UNIX around the call to
ttinl() in rpack() in ckcfn2.c can be adjusted or removed.

MACINTOSH CHANGES

Fixed RENAME command in Mac Kermit.  zrenam() in ckmfio.c.
Fixed DELETE command in Mac Kermit.  ckuusr.c + zdelet() in ckmfio.c.
Fixed znewn() in Mac Kermit, it was writing new name over old name.  ckmfio.c.

As a result of these three fixes, five out of the six SET FILE COLLISION
options work: BACKUP, OVERWITE, RENAME, DISCARD, and UPDATE.  APPEND
overwrites instead of appending.

Fixed TRANSMIT command in Mac Kermit.  It works, but it doesn't echo.
ckuus4.c, ckmker.mak.

Fixed TRANSLATE command on the Mac to write translated text into the
Response window if no output filename is given.  ckcdeb.h, ckuus4.c.

Fixed Mac Kermit zstrip() to really strip the pathname, and zltor() to
produce somewhat nicer results.  ckmfio.c.

Removed the SET CARRIER command from Mac Kermit -- The Mac doesn't "do"
carrier.  ckuusr.c, ckuus3.c.

Tried to fix CD command in Mac Kermit.  ckuus5.c.  No go -- when zchdir()
is called, it puts up a bunch of error boxes on the screen: "Warning - Writing
to the console in applications is not supported".  Commented out the screen
calls.  Now it works, except when you leave off the directory name or enter
a bad one.

Disabled SET TERMINAL command for Macintosh, since it has no effect.  This
code needs to be hooked into the Mac's terminal emulator.  ckuus7.c.

------------------------------
5A(177) Mon Jan 20 12:25:35 1992

Relaxed the restriction on sliding windows that required the user to SET
WINDOW n on both Kermits.  Now the receiver can determine the window size,
just like with packet length.  ckcmai.c, ckcfns.c.

Added -Y command-line switch (note uppercase): system-independent way to
skip init file.  ckuus5.c, ckuusy.c.

Added \v(fsize) and \v(tfsize) variables, containing the size of the last
file transferred, and the total size of all the files in the last group
transferred, respectively.  Suggested by Bob Larson.  ckuusr.h, ckuus4.c.

Added \v(cpu) to show the CPU type.  ckuver.h, ckuus4.c.

Restored buffered output to CONNECT mode, but only for non-TELNET,
non-session-debugging, non-SO/SI sessions.  The nonbuffered output in edit 176
was noticeably slower on small, slow machines.  Thanks to Tom Kloos at Sequent
and Peter Mauzey at AT&T for pointing out the problem, and to Tom for
suggesting some output buffering code.  ckucon.c.  NOTE: a general solution to
this problem (e.g. covering the TELNET and SO/SI cases) requires massive
reorganization of the code -- e.g. moving the TELNET negotiations from the
high-level code (CONNECT, INPUT, SCRIPT, etc) to the lowest level (ttinc,
ttinl, ttxin, etc, in ck*tio.c).  This could be done easily enough, but it
would have to be done for all C-Kermit variants.

Added -DTCPSOCKET to Apollo sr10-bsd entry.

Rearranged overlays for 2.10/2.11 BSD version because root segment became
a tad too large.  ckubs2.c, makefile.

Supplied many missing "\" continuation marks to makefile that were lost
in edit 176.

Updated the Apollo sr10-bsd makefile entry to allow for an apparently new
ANSI-compliant C compiler, plus a couple of minor changes to ckcdeb.h and
ckutio.c.  Thanks to: Michael Pins <amigapd@icaen.uiowa.edu>, Iowa Computer
Aided Engineering Network, University of Iowa.

Fix for SunLink X.25 PAD parameters-setting from Chris Green in England.
The construction *(++p) is apparently not evaluated consistently by different
compilers...  (this can't really be true, can it?)  ckcnet.c.

Removed *(++p) constructions from elsewhere too: ckucmd.c, ckuscr.c.

Stupid Compiler Tricks: changed all occurrences (169 of them) of "strlen(...)"
to "(int)strlen(...)" to make compilations with the new and improved string
library, in which strlen() is size_t rather than int, happy.  The previous
trick of "#define strlen (int)strlen" caused recursion in certain C
preprocessors (such as DG, DIAB).  I wonder what havoc will now be wrought by
casting a function to its own type...

Fix for Kanji file transfer: Kanji translations were being applied even if
the file type was binary.  Fix supplied by Dr. Hirofumi Fujii, KEK, Tokyo.
ckcfns.c.

Fixed duplicate case in switch in ckuusx.c for compilers where \n is carriage
return.  Christian Hemsing.

Fixed prototypes for xkanj[fzi]() routines in ckcker.h.

Made sure that atol() was declared as 'long' in all modules by adding it to
ckcdeb.h.  Maybe this will fix the problems with speeds and file lengths
once and for all.  Thanks to Steven Schultz for this one.

Improved version of warray() for ckwart.c.  Bob Larson.

Made some variables in ckwart.c static to avoid conflicts when built with VMS 
shared libraries.  Piet W. Plomp.

Added OS-9 to \v(platform).  Bob Larson.  Also Macintosh, Amiga, etc.
ckuus4.c.

Added check for "NO DIAL TONE" (note spaces) in Telebit dialing.  Tom Kloos.

Replaced translation tables between CP437 and Latin-1, and CP850 and Latin-1,
with the official IBM invertible translations, recently published in IBM's
Character Data Representation Architecture (CDRA) manuals.  Watch out, there
are a few surprises in the C0 control-character area!  We also need official
corporate translations like these from Apple, NeXT, DG, etc.  ckuxla.c.

Replaced translation tables between Apple Quickdraw and Latin-1 with new,
invertible "Extended Macintosh Latin" encoding, in preparation for the
production of the new Extended Mac Latin font (which, unfortunately, nobody
has started to work on yet...).

Noticed that ttoc() can core dump on the SUN when trying to output a character
and the load is VERY high.  A timer goes off, and ttoc() tries to call a
special ioctl() to unstick a possibly stuck XOFF condition.  Apparently this
ioctl (TCXONC), which I now cannot find documented anywhere, was being called
incorrectly (like maybe TCXONC is really supposed to be for termio rather than
ioctl?  Or 3rd arg is by reference rather than value?).  Replaced this code
with a call to the POSIX function tcflow(ttyfd,TCOON).  ckutio.c.

Added Telnet protocol negotiation support to the SCRIPT command.  Until now,
SCRIPT commands would not work at the beginning of a SET HOST connection
(noticed by Bert Laverman). ckuscr.c, ckcnet.c.

Made sure that telnet echo negotiations were handled correctly by the SCRIPT
and INPUT commands (previously, they were handled, but the global "duplex"
setting was never changed).  ckuus4.c, ckuscr.c.

Added SET SCRIPT ECHO {ON, OFF} and made SCRIPT echoing obey it.  Also, got
rid of the message that echoes the SCRIPT command, since it usually tends to
contain a password.  Suggested by Augustine Cano.  Added SCRIPT ECHO state to
SHOW SCRIPTS.  ckuscr.c, ckuus3.c, ckuus5.c.

Changed the SCRIPT command to take the character following "~" literally if it
is not one of the special "~"-arguments.  This takes care of (in particular),
"-" (dash), which there was previously no easy way to send (pointed out by
Augustine Cano).

Added an #ifdef to ckcpro.w for the benefit of the Coherent C compiler,
which blew up at the switch() statement that was added in the <rdata>Z case,
suggested by Manfred Prange.

Added confirming message "Hanging up" when user types <esc-char>H during
CONNECT mode.  Suggested by Peter Mauzey.

New ckvker.mms for building C-Kermit on VAX/VMS, optionally with shared
library support, from Piet Plomp.

Added -DNOPUSH compile-time feature selector.  If defined, it disables all
sorts of "shell escapes" -- the PUSH and RUN commands, "!", "@", SPAWN, etc,
as well as the server's execution of REMOTE HOST commands, as well as
ENABLE HOST, plus OPEN { !READ, !WRITE } commands, job control, shell escape
from CONNECT mode, etc.

Changed SET HOST command to allow a TCP service name or number to be given as
a separate field, in addition to allowing it to be appended to the IP host
name or number (which it already did).  This way, the user gets useful ?-help,
and the syntax matches that of most TELNET commands.  So now you can say: SET
HOST foo, SET HOST foo:3000, or SET HOST foo 3000.  function setlin() in
ckuus7.c

Added a built-in TELNET command.  It is simply a shorthand for:

  SET HOST [ <ip-name-or-number> [ <tcp-service-name-or-port-number> ] ]
  IF SUCCESS CONNECT

except that if a hostname is not given, the previous session, if any, is
continued.  So now you can say TELNET, TELNET foo, TELNET foo:3000, or TELNET
foo 3000.  Also, cleaned up SET HOST / TELNET failure messages (no more "Error
0").  ckcnet.c, ckuusr.c, ckuus7.c.

Removed "/lis" and "/map/full" from ckvker.com -- it fills up my poor disk.

In trying to TELNET from C-Kermit to services on non-telnet ports, I
discovered that Kermit often did not work, but UNIX telnet did.  Many of these
services (like the University of Michigan Geographic Name server) don't do
TELNET option negotiations and need to be spoken to in "linemode".  So I
changed Kermit to assume half duplex linemode conventions (initially) if a
TCP/IP connection is not on a TELNET port.  ckcnet.c.

Checked to make sure Kermit didn't appear idle during remote-mode file
transfer.  It doesn't.

Merged in Rick Watson's Macintosh changes from edit 172.  This work consisted
mainly of putting #ifndef MAC..#endif around features that are not to be used
in Mac Kermit, plus converting a lot of static buffers to dynamically malloc'd
ones, plus adding some special code for handling the Mac's miniparser and
Command-. command cancellation, within #ifdef MAC conditionals.

Removed all occurrences of '\r' from the cku*.c modules: MPW C translates
this to linefeed, not carriage return!

Transferred all of the ck[cu]*.[ch] files from this edit plus all the latest
ckm*.* files from U of Texas to the Mac and compiled with MPW C 3.0 under
System 6.03.

Found a conflict between the fatal() routine declared in ckuusx.c (which takes
one argument) and the one declared in ckmutl.c (which takes two).  Changed all
fatal() calls, and the fatal() routine, in all ckm*.* files from fatal() to
macfatal().  macfatal() is different from fatal() -- it puts up a "stop alert"
box and exits to the Mac "shell".  The fatal() calls in the ck[cuw]*.c files
remain fatal(), for now.  The affected files are: ckmptp.h, ckmcon.c,
ckmco2.c, ckmini.c, ckmtio.c, ckmusr.c, ckmutl.c, and ckmwin.c.  Made all
changes via RCS in the /uw/mackermit directory.

At link time, found lots of unresolved references, mostly from routines or
variables declared in ckuusx.c and ckcnet.c -- the makefile didn't include
them.  Changed the makefile to include them, but then found that the ckm*.*
modules declared their own versions of many of the ckuusx.c functions, so
put the ones in ckuusx.c within #ifndef MAC...#endif.  Also, ckmxla.c needed
a lot of updating: missing items were copied from ckuxla.c.

The result of all this compiles without complaint and links without any
unresolved or duplicate references.  However, link says "Size of global
data area exceeds permitted size: (Error 34), Size of global data area:
40944."  Then it spews out thousands of "Computed Reference offset out of
range (Error 49).  The maximum size for the global data area is 32K, so we
need to eliminate about 8K more of this to compile with MPW 3.0 or 3.1 --
that would be a lot of work, and would introduce the possibility of further
errors, more releases needed for debugging, etc.

MPW 3.2, however, allows bigger global data areas.  Using MPW 3.2 with "-model
farData" (C compilation) and "-model far" (Link) (= "32-bit everything"), the
program builds with no complaints.  But file transfer doesn't work at all.
Mac loops or hangs, etc.

Discovered several places where z{in,out}{buffer,ptr} had not been changed
from CHAR to char, including in ckmfio.c and ckmxla.c.  Made these changes,
rebuilt on Mac, but still no improvement.

When sending a file, the Mac seems to put tons of garbage (like 4000 G's) in
the file header packet.  Noticed that this caused C-Kermit on UNIX to crash,
found that buffer bounds not checked in rcvfil() in ckcfns.c.  Fixed this.
Ditto for sfile().

Found a horrible bug in zrtol() in ckmfio.c (Macintosh only) that would make
it write all over memory.  Fixed it, but that didn't make the file transfer
problems go away.  At least now you can use pathnames in SEND commands, e.g.
"send disk:folder:filename" -- previously this would crash the Mac.

Finally, Rick suggested I recompile the whole thing with MPW, but without
any kind of -model, -m, or -srt switches.  I got the Link message "Warning:
Size of global data area exceeds 32K. (Error 34)".  But the resulting program
seems to work, at least on my Mac IIx.

Fixed \v(time), \v(date), \v(ntime), and \v(ndate) for  Macintosh Kermit.
ckmfio.c.

Added version herald, etc, strings for SHOW VERSION to Mac Kermit.  ckmtio.c,
ckmfio.c, ckuver.h, ckuus5.c, ckmker.mak.  Also fixed ckm[tf]io.c to have
all source lines < 80.

Received from Kai Uwe Rommel, at the Technical University of Munich, updates
to edit 176 for OS/2, including a whole new ckufio.c with conditionals
inserted for OS/2 (since the file system interface for C is very similar
to BSD UNIX).  Worked all of his diffs into edit 177, recompiled on various
UNIX versions and VMS to make sure these were not broken, including through
GNU CC with -Wall, tested to make sure wildcard expansion, file opening &
closing, etc, still worked; all seems OK (SUN BSD, SUN SYSVR3, SYSV/386 R4,
VAX/VMS, etc).  With any luck, the OS/2 version will be OK too.

Changed the SET KEY command to allow not only single characters, but also
character strings (no \Kverbs yet), and also to read keyboard scan codes
greater than 255.  Scan codes, of course, require larger key map arrays, for
example 4096 instead of 256.  For SUN Sparcstations, NeXT workstations, PCs
with Xenix, DECstations, VAXstations, Aviions, etc, that can also produce scan
codes via Alternate, Command, Option, Left, Right, etc, key combinations,
and/or with F-keys, I need to know the system call to get the scan code.  So
for now, scan codes > 255 are supported only in the OS/2 version.  (Note:
looking through man pages, it seems like this can only be done through window
manager calls -- but I sure don't want to drag in the X libraries just to read
a key scan code!)  Many thanks to Kai Uwe Rommel for doing the preliminary
coding.

A new function was added to the system-dependent console i/o module: congks()
(console get keyboard scancode).  For all but OS/2, this routine is currently
#defined to be "coninc", so no disruption should occur.  By the way, the code
works fine just as it is on the NeXT with Alternate-key special characters,
because these are just 8 bits.

Key mapping is compiled only if NOICP and NOSETKEY are not defined.  It is
used only during CONNECT mode, not for OUTPUT, TRANSMIT, or other commands
that can send characters to the host.  Furthermore, the key map is not used
in reading escape character arguments, nor is the escape character treated
as an escape character if it appears in a "key macro" (i.e. a key is mapped to
a string of length greater than one).  Characters obtained from the keymap
are subject to translation, shifting, and other operations governed by SET
TERMINAL, exactly as if the characters had been typed at the keyboard and
there were no keymap at all.  Key macros are null-terminated, and thus
cannot contain null (0) characters.  I could make them counted strings, but
then we'd need yet another big array.

Changed makefile to add -DNOSETKEY to all entries that already included
-DNOFRILLS, so this feature won't surprise any of the small versions.  Checked
to make sure the program builds and runs OK both with and without NOSETKEY
defined.

Added key mapping support to the VMS C-Kermit CONNECT command.  ckvcon.c.

Several MINIX changes from Kai Uwe Rommel.  ckcdeb.h, ckuus4.c, makefile.

Noticed that terminal character set translation didn't work at all during the
CONNECT command, except for Cyrillic, and probably hasn't since edit 174
(November 91).  Hey, doesn't anybody use this stuff outside of the ex-USSR?
Fixed in ckucon.c.

Ditto for the TRANSMIT command.  Fixed in ckuus4.c.  But after I fixed it, I
noticed that when it displays the remote host's echo, the echo wasn't
translated.  Fixed that too.

German Goldszmidt at IBM reported that the "ps2aix" make didn't work because
of some declarations in cku[tf]io.c.  Put these within #ifndef PS2AIX10..#endif
and added a definition for PS2AIX10 to the ps2aix makefile entry.  (This is
for PS/2 AIX 1.0 -- 1.2.)  Also added a program herald corresponding to this
symbol to ckuver.h.

Received some OS-9 fixes from Bob Larson at USC, passed them along to
Christian Hemsing in Aachen, and he sent them back after testing with edit
177, plus some changes he had.

More changes from Kai Uwe Rommel for OS/2, most of them related to ANSIC C
prototyping, argument passing, casts, etc.  Pervasive changes over all the
modules.  Much of this was necessary because on PCs, sizeof(int) is not
necessarily equal to sizeof(char *).  After applying his changes, I ran the
program through GNU CC with -Wall, and got thousands of complaints, mostly in
ckuxla.c -- items that Microsoft C apparently didn't care about.  Fixed these,
and many others.  Now the program is getting REALLY ugly (see, especially, the
function declarations in ckuxla.c).  Also, the 4th argument to debug() was
changed from int to long, but this should be transparent to everybody because
debug is a macro, and a cast to (long) was inserted into the macro definition.

Changed -DSIGTYP=void in makefile to -DSIG_V.  You can also use -DSIG_I to
force the type of signal() to be int.  This lets us not only define the
type of signal() (as before), but also to define a symbol SIGRETURN, which
for SIG_V is return, and for SIG_I is return(0), to make ANSI compilers
happy.

Received an updated CKVFIO.C module from Terry Kennedy that fixes console
output during local-mode packet operations.  For example, REMOTE commands
issued from C-Kermit/VMS now properly display the text sent back from the
server on the screen.

Tested James Harvey's CKVTIO.C module with all the other updated files, but
it has big problems -- flow control deadlocks, etc -- so I didn't include it
with edit 177.  He's still working on it.

------------------------------
5A(176) Thu Nov 28 22:08:52 1991

NEW FEATURES

Added PRINT command to print a local file on a local printer.  ckuus[r2].c.

Added DG-MULTINATIONAL (Data General Multinational Character Set) as a
file character set.  The tables between DG MCS and Latin-1 are invertible.
ckuxla.[ch].

Added ttsndlb() routine to ckutio.c.  It sends a "Long BREAK".  This routine
should be added to all the other system-dependent modules.  Added calls to
ttsndlb(): <esc-char>L in CONNECT mode, and OUTPUT \\L in script programs.
ckutio.c., ckucon.c, ckuus5.c.

Made SHOW MACROS command wait at end of each screenful (currently hardwired to
24 x 80 screens).  Does its own line wrapping, etc.  This is done by passing
each name and definition thru the new & improved shomac() routine.  Did the
same for SHOW GLOBALS.  ckuus5.c.  Also, made the "more?" prompter into a
separate routine, askmore(), shared by SHO MAC, SHO GLOB, HELP, can be
used by other commands that need to page the screen.  ckuusx.c, ckuus2.c.

CONNECT COMMAND

Fixed a bad bug introduced in edit 175: when escaping back from connect mode,
the connection is broken if there has previously been an error.  Diagnosis:
sjval in ckucon.c was not reinitialized after the first connection.  Cure:
initialize sjval to 0 each time the "if (setjmp(con_env) == 0)" path is taken.
Thanks to Tom Kloos at Sequent.  ckucon.c.  Also from Tom: move the call to
tthang() after the perror() call because tthang() resets errno (Tom also
suggested that tthang() should save and restore errno, but it's not worth it
-- there are no less than 33 different return points in tthang()!).  Also from
Tom, add a UTEK-specific bit here to prevent EWOULDBLOCK from being a fatal
error (UTEK always blocks or gives an error on any line that does not have
carrier asserted).  ckucon.c.

Added a check to the CONNECT command to make sure Kermit is not running in
the background.  If it is, the CONNECT command prints an informative error
message and fails.  You will see it if, for example, "at" or "batch" mails
Kermit's output back to you, or if you do something like:

  $ kermit -l /dev/tty4 -c &
  Sorry, Kermit's CONNECT command can be used only in the foreground

ckucon.c (UNIX), ckvcon.c (VMS).

Changed VMS C-Kermit's CONNECT command to report "Back at blah" when escaping
back, if local nodename is known.  ckvcon.c.

Changed C-Kermit's CONNECT command to enclose the "Back at blah" message in
parentheses rather than brackets, because brackets are national characters
in ISO 646 character sets.  ckucon.c.

Made UNIX and VMS CONNECT messages consistent.  ckucon.c, ckvcon.c.

Worked on the CONNECT command to make it more compact and efficient.  General
cleanup of ckucon.c, found a few minor boo-boos and fixed them.  Noticed that
lbuf[] was declared by both ckucon.c and ckudia.c.  Made them both static
(i.e. private to their respective modules), and made them both dynamically
allocated if DYNAMIC is defined.  Oddly enough, allocating these buffers
dynamically makes both modules slightly bigger (size cku{con,dia}.o).  Why is
that?  No matter.  Then I removed a huge chunk of ugly, redundant code from
ckucon.c, collapsing the two big sections of port-reading code into one.  This
was done by using a "programming 101" buffering strategy for characters coming
in on the communication line.  The final result is slightly smaller (and
should be more efficient) than before, and should also solve some echoing and
session logging problems.  But mainly, the code is now much cleaner and more
comprehensible.

BUG FIXES

Found a bug in the processing of incoming Attribute packets that has been
there forever: For each attribute, C-Kermit reads the length and then copies
that many characters into a buffer, advancing the input pointer to the next
attribute field.  Fine.  But if the announced length is greater than
C-Kermit's buffer length, C-Kermit cleverly declines to copy the excess
characters, so as not to write over random memory.  However, in this case
C-Kermit forgot to advance the buffer pointer to next attribute field.  It
turns out that certain Kermit programs (e.g. 2.10 BSD Kermit on a PDP-11) send
total garbage in the File Creation Date attribute field, and the garbage is
longer than the receiving Kermit's creation date buffer.  This made the
receiving C-Kermit interpret some random byte pair as the next (attribute,
length) pair.  Since the garbage often tended to contain a "1" character at
that point, Kermit thought it was now reading the file size attribute.  This
explains the persistent but until-now-unreproducable reports of about
local-mode C-Kermit reporting garbage for the incoming file's size.  Fixed in
gattr() in ckcfn3.c.

Changed the code in ckufio.c that constructs the file creation date for the
attribute packet.  It was using a very fancy printf format string, with
options that are apparently not supported by some C libraries, for example the
one for 2.11 BSD, and possibly also the AT&T 6300.  I fixed it to use a very
simple format string.  Before this change, C-Kermit on the PDP-11 with 2.11
BSD sent a date/time string that looked like "0yyyy0mmdd 0hh:0mm:01157"
instead of "yyyy hh:mm:ss".  Now it's fixed, at least for the PDP-11.

Fixed sending of TELNET BREAK via <esc-char>B and OUTPUT \\B.  ckcnet.c.

Corrected a formatting error in SHOW FILE.  Bob Larson.  ckuus4.c.

Corrected a printf in ckwart.c that had a %s without a matching variable.
Bob Larson.  ckwart.c.

Fixed bug in Telebit V.42 dialing in which it didn't recognize the modem's
connect message.  Bob Larson.  ckudia.c.

Changed declarations for zinbuffer, zoutbuffer, zinptr, zoutptr from CHAR
(unsigned char) to char.  The only place where the data type really matters
is in the zinfill() routine, that does an fread() into the buffer.  ANSI C
compilations fail because zinbuffer does not match the prototype for fread().
ckcmai.c, ckcfns.c, ckufio.c.

Fixed a mistake that might have been causing C-Kermit to put the wrong
filesize into outbound attribute packets.  Can't tell for sure, the symptom
only shows up on 16-bit machines, and I don't have one.  ckcfn3.c.  (Later,
discovered this is still not fixed -- the PDP-11 version reports wildly
incorrect file sizes...)

Moved some more X.25-related declarations from ckuus3.c. to ckuus7.c.  Thanks
to Chris Green in England.

Corrections to the parsing of the SET PAD command (for SunLink X.25). ckuus7.c.

Changed "fr-canadian" to "canadian-french" in the SET {FILE, TERMINAL}
CHARACTER-SET commands.  ckuxla.c.

Reset some additional counters in resetc() at transaction beginning to reduce
spurious statistics if "Ctrl-A" report is requested during S- or A-packet
exchange, and also after file transfer with a server (to avoid counting the
FINISH packet as the "last file transfer").  ckcfns.c.

Added "#define strlen (int)strlen" to ckcdeb.h in the CK_ANSILIBS section
after #including <string.h>.  The SVR4 compiler did not like constructions
like "if (strlen(foo) > bar)", where bar is an integer, because strlen() is
a size_t instead of an int in the ANSI C library.

Included a copy of inet_ntoa within #ifdef EXCELAN because Excelan TCP/IP
doesn't have this routine.  William Bader.  ckcnet.c.

Removed Olivetti X/OS from the list of systems that needed to define INADDRX
(see edit 175), based on a report from Fulvio Marino at Olivetti in Italy.
ckcnet.h.

Changed the wart program to omit the extraneous trailing comma from the
state table switching array initialization clause.  ckwart.c.

SIZE REDUCTION

The Coherent version of edit 175 could not be built because the compiler
runs out of space, so...

Demoted SET KEY to a "frill" (-DNOFRILLS gets rid of it).  ckuus[r35].c,
ckucon.c.

Demoted the PRINT, PWD, PUSH, ENABLE, DISABLE, SET PROMPT, and multiline GET
commands to frills (you can still use "!" to get at the shell or run shell
commands).

Removed "debug" and "transaction" keywords from LOG and CLOSE commands if
DEBUG and TLOG not defined, and "unk-char-set" from SET menu if NOCSETS is
defined, plus many similar changes.  ckuusr.c.

Tried creating a version of C-Kermit without server mode, via a new symbol
-DNOSERVER, because the state-table switching array generated by wart from
ckcpro.w has become too big for at least one C compiler (Coherent): the tbl[]
array is now pre-initialized with 1920 elements.  Unfortunately, there is no
straightforward way to remove the server-related states because #ifdef's don't
work in ckcpro.w.  But now #ifndef NOSERVER..#endif pairs are scattered
throughout the program, but they don't do anything except take out the
SERVER-related commands, which is useful if (for some reason) you don't want
your Kermit program to be used in server mode.  When built this way, C-Kermit
can still communicate with a server (GET, REMOTE, BYE, FINISH, etc, are still
present).  Savings in space is minimal.

Then I found a way to reduce the size of the state-table array.  There is
an entry for every combination state (currently 14 of them) with
each "input character" (128 possible).  (Input characters are the packet
types or pseudo-packet-types returned by the input() function in ckcfn2.c).
But input characters will never be in the control range (ASCII 0-31), so
by subtracting 32 from each input character, and adjusting various bits of
code accordingly, I was able to change the state table array size from
128 * nstates (= 1920) to 96 * nstates (= 1440), a 25% reduction.  Not a huge
savings in program size, but it could make all the difference for certain
borderline compilers.  Every little bit helps.  ckwart.c, ckwart.doc.

There's not much left to squeeze out.  On a SUN-4 (Sparc RISC architecture,
SUNOS 4.1.1), the resulting "minimum interactive" wermit is 180K, exactly the
same size as 4E(072).  Compared to 4E(072), the minimum interactive version
lacks the DIAL and SCRIPT commands, but adds sliding windows, proper handling
of interrupt and suspend signals, longer packets, improved handling of
lockfiles and suid operation, and numerous other improvements and bug fixes.
With command-line processing removed ("minimum interactive-only") it's 172K.
Adding the DIAL command back in brings it up to 196K, the SCRIPT command adds
another 8K to bring it up to 204.  These sizes should be smaller on non-Risc
architectures like the PC.

MAKEFILE

Added a new mechanism to let Kermit feature selection and other compilation
switches be given on the "make" command line without having to edit the
makefile, and also reduced its size somewhat.  To add any desired options to
CFLAGS, just include "KFLAGS=xxx yyy zzz" on make's command line, e.g.

  make sunos41 KFLAGS=-DNODEBUG
  make sunos41 "KFLAGS=-DKANJI -DNODEBUG -DNOTLOG -UTCPSOCKET"

(quotes are necessary if KFLAGS= clause includes spaces).

Added a new makefile entry for DIAB DS90 with DNIX 5.3 and ANSI C:
dnix5r3ansi.  makefile.

Special makefile for 2.10 / 2.11 BSD on PDP-11s: ckubs2.mak.  Changed ckustr.c
to look for environment variable KSTR before using hardwired pathname for
string file (which happens to be /usr/local/lib/kermit5.sr, which I don't have
write access to so I can't test the program after I compile it).

Added makefile entry du42 for DEC Ultrix 4.2, which adds "-O2" optimization
available with new C compiler.  "-O2" optimization cuts 24K off the executable
program size, compared "-O".  Also, just for amusement, I added a "du42s5r4"
entry, to build us in the System V R4 environment under Ultrix 4.2.  Oddly
enough, it works.  Also, "make posix" works on Ultrix 4.2.  Way to go, DEC.

Made a shar file of the old (Chris Adie, Feb 1988) OS/2 support files for
C-Kermit 4F and put them with the current files, so OS/2 volunteers can have a
relatively short and simple set of modules to look at, rather than plunging
directly into the longer and more complicated Chris Armstrong Presentation
Manager version from 5A(143), June 1990.  cko4f.sh.

Still can't compile on the local RS/6000 - any attempt to compile any but a
very small C source file, even without a makefile, results in "xlc: 1501-229
Compilation ended due to lack of space".  Others say they have no trouble.

watsun upgraded to SUNOS 4.1.1.  C-Kermit works ok.

Built full-blown C-Kermit on the Encore with and without -DYNAMIC.  The
DYNAMIC version was about 1K bigger than the nondynamic one!

Got a new CKVTIO.C module from James Harvey at Indiana/Purdue University.  It
makes VMS C-Kermit's CONNECT command work much better, but unfortunately it
breaks the REMOTE commands (returned data is not displayed).  It doesn't help
the MultiNet code at all -- still slow as can be.  Wait for fixed copy, add
ttsndlb(), before releasing 176.

------------------------------
5A(175) Fri Nov 22 13:55:18 1991

Added REMOTE LOGIN and REMOTE LOGOUT commands (if NOFRILLS not defined).
Client end only, not server end.  ckuusr.c, ckuus7.c.

Added SET LOCAL-ECHO {ON, OFF} as a synonym for SET DUPLEX {HALF, FULL}.
ckuusr.h, ckuusr.c, ckuus3.c.

Added "Trying <ip-address> ..." message for TCP/IP SET HOST connections,
like telnet, so users can see the IP address in case they gave a name.
Also added IP address to SHOW NETWORK display.  ckcnet.c, ckuus4.c.

Changed ckucon.c to use setjmp() in a simpler way to prevent "Macro setjmp
used in invalid context" failure from Cray UNICOS C compiler (reported by
Chuck Fuller <fuller@wccs.psc.edu>, diagnosed by Bill Homer at Cray Research).
Similar changes to ckudia.c.  Basically, it is against the law to use longjmp
to return a value through setjmp, because constructions like:

  if (x = setjmp(buf)) { ... } else { ... }

are illegal (the assignment isn't allowed).   All places where this was done
have been changed to make longjmp set a global variable.

Moved the code to get the local hostname to a separate function, ckhost(),
and put it in ckuusx.c so it can be used by different implementations.
Strictly speaking, it should go in a system-dependent module, but it's not
worth changing the interface definition and all the ck*tio.c modules just
for this.  Had main() call this function when the program starts up to fill
in a string called myhost, which can be printed by any module at any time.
ckcker.h, ckcmai.c, ckuus4.c, ckuusx.c.

Changed CONNECT message "Back at local system" to report the host name, if
known, e.g. "Back at watsun".  ckucon.c.

Fixes for MAIL and PRINT handling for VMS version from Terry Kennedy.
ckcfns.c, ckv[tf]io.c.

Changes to support for incoming files that are to be mailed or printed: if
mail or print fails, special return codes are now given by zmail() and
zprint(), passed along by reof(), and cause ckcpro.w to issue error packets
with appropriate messages, rather than "Can't close file".  So far, only the
VMS version actually returns meaningful return codes -- the UNIX version
always says it succeeds, even if it fails.  ckcfns.c, ckufio.c, ckvfio.c,
ckcpro.w, ckasys.doc.

Corrected a few dangling commas in keyword lists in ckuus[r3].c, reported by
Manfred Prange.  However, it still looks unlikely that an interactive version
of C-Kermit can be compiled under Coherent.  We get "out of space" errors on
ckuus3.c and ckuusr.c.

Deleted many unnecessary external declarations from ckuus*.c files, in hopes
of reducing compiler symbol table space requirements, "too big" errors, etc.

Moved some X.25-related declarations from ckuus3.c to ckuus7.c.  X.25 support
could not possible have worked in edit 174.

New OS-9 files: makefiles (accounting for ckuus7.c, allowing Kanji) and
ck9con.c, from Christian Hemsing <SE@DACTH51.BITNET>.

Obscure workaround for Altos 986 connect mode problem -- pressing DEL causes a
read error, pops you back to the C-Kermit prompt.  Reported by Bertie
Coopersmith in London, who furnished the fix.  ckucon.c.  Also, added Altos
986 banner to ckuver.h and A986 symbol typeout to SHOW VERSIONS.  ckuver.h,
ckuus5.c.

Removed redundant and spurious prototype for acucntrl() from ckutio.c.
Reported by Ryan Stanisfer <ryan@ponder.csci.unt.edu>.

Adjustments to makefile for 2.11 BSD from Steven Schultz at Contel.

SET DIAL MNP-ENABLE should now work for HST Courier modems too -- switch
settings provided by Bo Kullmar in Sweden.  ckudia.c.

Fixes to tthang() for SCO 3r2, 3r22, 3r22gcc (some automatic variables weren't
being declared in the POSIX case, which these make entries use), from Warren
Tucker.  ckutio.c.

New compile-time symbol: INADDRX.  Define this symbol for systems built with
the TCP sockets library in which the inet_addr() function is of type struct
inaddr (or in_addr), rather than the normal unsigned long.  Predefined this
symbol for Olivetti X/OS, Data General UX 5.40, and DEC Ultrix 2.0.  ckcnet.h,
ckuins.doc.

Simplified the conditionals in the reference to inet_addr() in ckcnet.c, and
changed the code to avoid the dangerous and illegal &inet_addr() construction.
I can't imagine how this ever worked.

New makefile entry for Data General UX 5.40 (= Sys V R4).  Identical to
s5r4sxtcp, but defines the symbol DGUX540, which in turn causes INADDRX to
be defined.  Added a herald for DG UX 5.40 to ckuver.h, and also to SHOW
VERSIONS in ckuus5.c.  Tested on a DG Aviion, works good.

Corrected spurious return code from tthang() in BSD environment, which
caused Kermit to say "hangup skipped" instead of "hangup ok".  ckutio.c.

Added makefile entry dynix31 for Sequent DYNIX 3.1.x with TCP/IP, from
Jack Woolley, SCT Corp, jwoolley@sctcorp.com.  makefile.

Added makefile entry sco386gcc for SCO Xenix/386 2.3.3 with gcc 1.37 or later
from Richard S Smith at Cal State.  makefile.

Moved WRITE command from #ifndef NOFRILLS to #ifndef NOSPL.  ckuusr.c.

Fixed bug with dynamic command buffers.  Now they work and they are used by
default if DYNAMIC is also defined.  ckuus[r56].c, ckcdeb.h.

Hirofumi Fujii reports that the Kanji support, including Sony News tty mode
manipulation, works fine: Sony News, DECstation/Ultrix, VAXstation/VMS.

A few trial compilations: SUNOS 4.1, POSIX, SVR4 -- so far, so good.  Size
is down a bit.

Tried compiling under 2.11 BSD.  After much ado, got it to compile and link.
It even works, once the file kermit5.sr is put into the right directory.
All this thanks to work by Steven Schultz.

------------------------------

5A(174) Mon Nov  4 21:34:48 1991

Fixed a BAD BUG in the 8th-bit prefixing negotiations, which has been there
for years: tinit() was initializing ebq to 0, rather than MYEBQ, which
interfered with 8th-bit-prefixing negotiations.  Discovered while testing
locking shift negotiations.  ckcfns.c.

Added code to rpack() to deduce the block check type using two heuristics that
totally violate its datalink role by looking at the packet type: if it is I or
S, the block check type is always 1, and if it is N (NAK) the block check type
is always LEN-2, because NAKs never have data.  This prevents deadlocks in the
case where (for example) the PC sends an S packet requesting type 3 block
check, C-Kermit sends the ACK and switches its block check type to 3, but the
PC retransmits the S packet with block check type 1.  ckcfns.c.

Fixed a bug in the VMS C-Kermit packet reader that caused it to sometimes
fail to strip parity from all the packet bytes.

Completely disabled LPASS8 processing.  It turns out to be entirely unreliable.
It only works on serial ports, and only then on systems that implement it
correctly.  It does not work on terminal servers, telnet connections, rlogin
connections, etc etc, because the connection method usually has no way of
learning that LPASS8 has been done.  The downside to this is the loss of flow
control during packet operations on BSD-based UNIX systems.  Let us hope that
this and the previous two changes clear up the last remaining problems with
binary file transfer.  ckutio.c.

Fixed a bug, introduced in 172, in which the new -l <numeric-file-descriptor>
option prevented Kermit from opening numeric X.25 addresses.  Reported by
Michael Schmidt at University of Paderborn in Germany.  ckutio.c.

Add sco3r22gcc entry from Warren Tucker.  makefile.

Added utsv entry to makefile.  It seems Amdahl UTSV does not define S_ISREG,
etc, macros correctly, similar to Olivetti OXOS, so we redefine them in
ckufio.c for these cases.  ckcdeb.h, ckuver.h, ckufio.c, ckuus5.c.

Put the "close(priv_open(...))" bit in ttopen within #ifndef SCO32..#endif,
to keep uugetty from grabbing the device.  Robert Johnson.

Changed SCO UNIX 3.2 and Xenix 2.3 makefile entries to explicitly link
libc.a before libx.a, to make sure that readdir() from libc.a (which uses
sys/ndir.h) is used, rather than readdir() from libx.a (which uses dirent.h,
which apparently does not work).  Reportedly, without this change wildcard
expansion does not work right.  Test before and after by typing "send ?"
at the C-Kermit prompt.  Suggested by Feng Chen <feng@mtnsys.wimsey.bc.ca>. 
If this doesn't do the trick, Feng suggests adding -DXNDIR to the CFLAGS
for these entries.

Fix for KANJI vs CYRILLIC conditionals in ckuxla.c so KANJI could be selected
without CYRILLIC, from Hirofumi Fujii.

Add new support for JIS7 and DEC-KANJI from Hirofumi Fujii.  ckuxla.[ch],
ckcfns.c.

Installed Short KOI as a file character set in its own right, and removed all
effects of "set language russian" in the TRANSLATE command, TRANSMIT command,
and CONNECT command.  This means that we don't get automatic transliteration
between Cyrillic and Roman characters unless we ask for it in the normal way,
i.e. by making SHORT-KOI one of the character sets.

However, this leaves us no way of sending Russian files to ASCII-only hosts
whose Kermits don't understand the Latin/Cyrillic transfer character set, nor
of translating received files from Short KOI to a real Cyrillic set.  So SET
LANGUAGE RUSSIAN still takes effect when either the transfer character set is
ASCII and the file character set is one of the 8-bit Cyrillic sets, and vice
versa.  ckuxla.[ch], ckuus4.c, ckucon.c.

Testing this revealed another problem.  The character set of the file header
packet (and its ACK) is translated by Kermit.  This must not happen, because
the file header comes *before* the Attribute packets that contain the
character set information.  In this case, translating an incoming filename
(which happened to contain lowercase letters) from "Short KOI" to Cyrillic
produced a filename with "random" 8-bit characters.

So the getpkt() routine was changed to require a second argument, a flag: zero
means no character-set translation, nonzero means to translate.  All calls to
getpkt modified to include the new flag.  Same thing in the other direction:
decode() has a new 3rd translate-flag argument.  Compiled with GNU cc and ANSI
function prototyping to make sure nothing was missed.  ckcker.h, ckcfns.c.

Changed the SET LANGUAGE command keyword table to make all the entries that
don't do anything invisible.  ckcxla.h, ckuxla.c.

Added a new field to the csinfo (character-set info) structure: alphabet.
It tells the base alphabet of the character set: Roman, Cyrillic, etc.
Changed tests in TRANSLATE, TRANSMIT (ckuus4.c) and CONNECT (ckucon.c)
to check this when deciding on the intermediate character set for translation,
rather than a whole series of "if" conditions for each character set.

Unfortunately, this requires changes also to ckixla.[ch], ckoxla.[ch], and
ckmxla.[ch].  So...  Amiga: uses ckuxla.[ch], so no problem.  OS/2: so far
behind, let's worry about it later.  Macintosh: fixed up ckmxla.h and ckmxla.c
(first time these have been touched in quite a while).  After some back and
forth with Rick Watson at the U of Texas, character-set translation is
finally working in Mac Kermit (user interface in command-window only).

Edit 173 check for "kermit -s" not specifying any files broke "kermit -s -".
Reported by Bob Larson, many others.  Now fixed.  ckuusy.c.

Fixed spelling of "lockfil" in Dynix/PTX support code (Jeff Gong).  ckutio.c.

Changed all occurrences of \r in ckudia.c strings that are sent to modems to
\015 for the benefit of C compilers (e.g. on Macintosh) that define \r to be
something other than carriage return.  Now DIAL command works in Mac Kermit.

The CD command always returned SUCCESS, even if it failed.  Reported by John
Hood.  Fixed in ckuus5.c.

Fixed HST Courier wakeup string -- it was missing the terminating CR (reported
by John Hood).  ckudia.c.

Changed Hayes/USR/HST/Telebit dialing code to allow for RINGING and RRING
responses.  Tested OK on Telebit (after telling Kermit it was a Hayes).
ckudia.c.

Totally rewrote the code for reading Hayeslike modem responses expressed as
digit result codes; added code to handle every known response, and structured
the code to make it easy to handle new responses.  Previously very few
responses were handled correctly because the code was originally written to
assume single-digit responses only.  ckudia.c

Corrected a bug where Telebits in digit-result mode were not handled at all
after initial setup.  And another where SET MODEM SLOW-TELEBIT didn't work
*unless* the modem was in digit response mode.  And another bug in which speed
changes based on digit result codes usually didn't work.  Also, cleaned up
dial display (seen when SET DIAL DISPLAY is ON) a bit.  ckudia.c.

Added new command SET DIAL MNP { ON, OFF } to enable / disable MNP negotiation
while dialing.  Presently effective only for Telebits; I don't know the switch
settings for other MNP-capable modems.  Previously, MNP negotiation in the
Telebits was coupled to the FLOW-CONTROL setting.  Now these are selected
separately.  The modem is told to use hardware flow control if Kermit's FLOW
is set to RTS/CTS; the modem is never told to use software flow control, since
it would then be impossible to send Ctrl-S or Ctrl-Q to the host.  Added DIAL
MNP-ENABLE to SHOW DIAL display.  ckcmai.c, ckuusr.h, ckuus2.c, ckuus3.c,
ckuus4.c.

New command: SET SERVER DISPLAY { ON, OFF } enables / disables file transfer
display during server operation in local mode.  In version 4E and earlier,
there was always a display, and at least one site depended on it; they had
some kind of script that was driven by the file transfer display messages.
For reasons lost in antiquity, the display was removed in 4F or 5A.  The new
command lets the user decide.  The setting is shown in the SHOW SERVER
display.  The "interrupt message" ("Type this to do that, blah blah") is shown
only once, immediately as server mode is entered, rather than ever time a
transfer begins (as it was in 4E).  Default is OFF.  ckcmai.c, ckcpro.w,
ckuusr.h, ckuus2.c ckuus3.c, ckuus5.c.

Fixed job control for SVR4 for Sys V R4, I think.  To do this, I had to make
Sys V R4 define the CK_ANSILIBS macro, which causes it to #include <unistd.h>,
which in turn defines _SC_JOB_CONTROL, like POSIX, so we can do sysconf() on
it.  Of course, this only tells us whether the underlying UNIX kernel supports
it, not whether the shell does.  Anyone who suspends Kermit under sh is in for
a rude surprise.  ckcdeb.h, ckutio.c.

Removed #define TELOPTS from I386IX (Interactive ISC Sys V R3).  According to
Mike Hickey <mhickey@dbri.com>, it is already defined in <arpa/telnet.h>.
It's a mystery why the #define was there in the first place, so the #define is
left there, but commented out.  ckcnet.h.

For the recently added HPUXPRE65 (HPUX Pre-6.5) make option, added "typedef
mflag int;", John Dunlap <dunlap@faraday.apl.washington.edu>.  ckutio.c.

In response to complaints from people who have supposedly ANSI-compliant C
compilers that do not support the token-pasting operator ##, I tried changing
the definition of _PROTOTYP not to use it.  Seems to work OK on Sys V R4, on
NeXT with GNU cc -Wall, and on RS/6000 with ANSI compilation forced.  So maybe
it's OK to dispense with it completely.  This should fix the "make convex9"
entry, among others.  ckcdeb.h.

While compiling with -Wall, noticed a function that had not been prototyped:
macini(), the one that allocates macro buffers dynamically on startup.  That
was being called from ckcmai.c, which is really inappropriate.  Moved the call
to cmdini() in ckuus5.c, and added the prototype to ckuusr.h.

Changed protocol error message prefix to be "Protocol Error:".  For a long
time it was C-Kermit's prompt string, but that implied that the message was
coming from C-Kermit, when it might have come in a E-packet from the remote.
Then it was "Remote Kermit says:", but sometimes the message is generated by
the local Kermit.  Given the structure of protocol routines, there's no easy
way to separate the two cases.  ckuusx.c.

New command: SET QUIET {ON, OFF}, default OFF.  Same as -q command-line
option.  It is supposed to eliminate most non-error messages.  Added various
messages to this category, including CONNECT and escape-back message.
ckuusr.h, ckuus3.c, ckucon.c.

New command: SET KEY \xxx \yyy.  A very limited key mapping feature.  The two
items are character codes, expressed in decimal or backslash notation.  For
now all you can do with this command is replace one character by another -- no
strings, no macros, no verbs, like in MS-DOS Kermit.  No extended scan codes
are recognized: only ASCII values (0-127) or (if you have 8-bit access to the
C-Kermit command parser AND if you SET COMMAND BYTESIZE 8) full 8-bit values
(0-255).  For now, the key mappings are effective only during CONNECT mode.
Key mappings are done before character-set translation.  ckuusr.c, ckuus3.c,
ckuus5.c, ckucon.c.

New make entry: encore88k, for Encore 88K with UMAX V 5.3 (System V R3) and
TCP/IP support, from David Kricker at Encore <kriker@encore.com>.

New make entry: sonynews, for Sony NEWS OS 4.01C with Kanji support.

New make entry: du4kanji, for DEC Ultrix 4.x with Kanji support.

Added special Kanji support for Sony NEWS.  Get tty Kanji mode when entering
Kermit: congm().  Get external device Kanji mode upon SET LINE or SET HOST:
ttopen().  Put terminal into ASCII mode before entering packet mode: ttpkt().
Restore Kanji mode after packet operations: ttres().  Restore tty Kanji mode
upon exit from Kermit: conres().  Suggested by Hirofumi Fujii, who also
provided documentation for the necessary ioctl's.  ckutio.c.

Added some new symbols to be displayed in SHOW VERSIONS.  ckuus5.c.

Fixed telnet option negotiation with Xyplex (and possibly other) reverse
terminal servers.  Users reported "getty babble" on the serial side.  I was
able to verify the problem on several different servers.  Changed the telnet
negotiations a bit, and the problem went away.  ckcnet.c.

Fixed telnet to IBM mainframe linemode terminal server.  Certain applications
(notably Kermit-370 and Wylbur, probably those using write-chained-to-read to
issue their prompt?) do not echo linefeeds from the terminal, so commands
would overwrite each other on the same line.  Now Kermit echoes the linefeed
that it supplies automatically when the user types CR.  ckucon.c.

Added Mark Williams Co COHERENT fixes from Manfred W Prange
<mwprange@vale.acs.oakland.edu>.  He says he can make a functional version
with no interactive command parser.  He can't include even a minimal
interactive capability because his compiler blows up on ckuus3.c -- "out of
space".  ckcdeb.h, ckutio.c, ckufio.c.

Took everything out of ckuus3.c that was not part of the doprm() function and
moved it to a new module, ckuus7.c.  Changed the makefile to allow for ckuus7.
Hopefully this will allow a minimal interactive version to be built for
Coherent.  Added ckuus7 to the UNIX makefile, the VMS makefile (ckvker.mak),
and the VMS DCL build procedures (ckvker.com and ckvker.mms).

Fixed an error in the translation of Latin-1 to many of the ISO 646 national
sets, in which broken bar and not sign were translated into vertical bar
and tilde (but vertical bar and tilde stand for national characters!).
Changed them to translate into UNK.  ckuxla.c.

Fixed a bug (I hope) where suspending C-Kermit during local-mode file transfer
and then fg'ing again caused CBREAK mode to be lost on the terminal, which
prevented single-character interruptions from working.  ckuusx.c.

Made the default SET SUSPEND status depend on the NOJC compile-time feature
selection switch, i.e. if you compile Kermit with -DNOJC, then SET SUSPEND
is OFF by default.  ckcker.h.

------------------------------

5A(173) Tue Sep 24 00:32:52 1991

Added \m(name).  Allows you to define (or assign) a "macro" and use it like a
variable.  This gives us "long variable names".  Required two lines of code.
Example: define number 7654321, dial \m(number).  ckuus4.c.

Added builtin variable \v(ntime), numeric time, seconds since midnite, 0
through 86399.  Use this for timing things.  Call it once at the beginning of
whatever you want to time, again at the end, then subtract the two using
INCREMENT or whatever, for example:

  define xx asg \%9 -\v(ntime), transmit foo, incr \%9 \v(ntime), ec \%9 secs

It's the user's responsibility to worry about timing things across midnight.
ckuusr.h, ckuus4.c.

Added REMOTE KERMIT command (just the client end, not the server).  ckuus3.c,
ckuusr.c, ckcpro.w.

Added APPEND option for logs.  Now you can append to the packet, transaction,
session, or debugging log, rather than always creating a new one, by including
the word "APPEND" at the end of the LOG command.  Added new prototypes for all
log-opening functions to include a second argument.  ckuusr.h, ckuusr.c,
ckuus4.c.

Added SET TERMINAL NEWLINE-MODE { ON, OFF }.  If ON, then whenever you type
CR during CONNECT mode, Kermit sends CR and LF.  Otherwise, it just sends CR.
ckuusr.h, ckuus3.c, ckucon.c.

Attempted to fix the TRANSMIT command (again), in response to reports from
Peter Mauzey. PROBLEM: binary file transmission is *much* slower than text
file transmission.  SOLUTION: if the file type is binary, put the
communication device in ttvt mode, rather than ttpkt mode, to inhibit the use
of software flow control (doesn't seem to help much, but doesn't hurt either).
The real problem is most likely that we're doing single-character output in
binary mode, compared to line-at-a-time in text mode.  Also, don't bother
setting up character-set translation if file type is binary.  Added SET
TRANSMIT LOCKING-SHIFT and separated it from SET TERMINAL LOCKING-SHIFT.
Added SET TRANSMIT PAUSE to specify number of milliseconds to pause between
each text line (text mode) or character (binary mode); default is 0.  Added
these to SHOW TRANSMIT.  Fixed up TRANSMIT ECHO vs DUPLEX interactions.
Verified transmission worked OK under most combinations of SET TRANSMIT
settings.

Fixed SET PROMPT to work in TAKE file, even when followed by ASK.  ckucmd.c.

Made "O" an invisible abbreviation for "OUTPUT".  ckuusr.c.

Discovered I was calling usleep() wrong on the NeXT, SUN, etc, so msleep
was not pausing at all, which is bad for the HANGUP command.  The argument to
usleep() is microseconds, not milliseconds.  Fixed in msleep(), ckutio.c.

Various cosmetic changes to messages, plus new help messages for new features.
Also, changed ermsg(), which is called when C-Kermit gets an Error packet,
to prefix the message with "Remote Kermit says:", not with its own prompt,
which was misleading.  Also, ermsg() is now called only when Kermit receives
an E-packet.  ckuusx.c.

Got rid of all references to cmerrp (big job).  ckucmd.c, ckuus5.c, ckuusx.c.

Reinstated code to allocate command buffers dynamically, saving many K of
static allocation and program size, using code from Rick Watson (who has been
modifying these modules for use in Mac Kermit).  The removal of cmerrp,
however, made this a bit tricky.  Unfortunately, the result doesn't seem to
work too well -- some commands are broken (at least "IF < VERSION nnnn" in my
init file).  Luckily, all of this is conditionalized on a unique symbol,
DCMDBUF, so for now it's not defined (see ckcdeb.h).  We can debug this later.
ckuus*.c, ckucmd.c.

Also, allocated mactab (the macro table) dynamically.  No problems here.
Saves about 8K (on NeXT).  ckcmai.c, ckuus[r456x].c.

It was reported by Donn Baumgartner at Dell that the System V R4 C
preprocessor for 386's has a broken ## operator, which is what was wrecking
all the ANSI C compilations on Sys V R4.  Changed the definition of _PROTOTYPE
for Sys V R4 not to use it.  Tested on an AT&T SVR4 system -- compilations
went OK.  ckcdeb.h.

Installed fix for TCP/IP under SVR4, in which bzero/bcopy were defined
to be memset/memcpy, but in fact these are not argument compatible.  New
definitions from Rob Healey and Marc Boucher.  ckcnet.c.

Made a new makefile entry was made for AT&T Unix SVR4 on 386/486 boxes with
Wollongong TCP/IP: "make sys5r4sxtcp".  ANSI function prototyping works,
thanks to the change immediately above, <sys/termiox.h> is used, so we get
hardware flow control, and regular Berkeley sockets library TCP/IP code is
used (apparently this is a different Wollongong TCP/IP release than the one
that requires -DWOLLONGONG in the makefile for the misplaced in.h and inet.h
files).  Debugged and tested successfully on a real 386 system with real AT&T
Sys V R4.  makefile.

Fixes for SCO UNIX 3.2 / Xenix 2.3 from Robert M Johnson of Hoboken, NJ, via
post.  He says that whenever Kermit attempts to write to a modem on a line
that has uugetty up, uugetty wakes up and hangs the line.  He also said HANGUP
doesn't work (so what else is new...).  Solution: first, set owner and group
for the kermit program to be uucp, and set kermit's permission to 06755 (i.e.
run it setuid).  Second - make some changes to ttopen() and tthang() in
ckutio.c.  These are within SCO32 conditionals, and a new makefile entry is
added.  These changes might turn out to be useful for others too.

New Amiga support files from Steve Walton, based on edit 172.  Broken server
responses to REMOTE commands now fixed.

New OS-9 support from Christian Hemsing, based on edit 172.

Fixed "kermit -s xxxx" not to say "Escape back and give a RECEIVE command..."
if xxx does not exist.  Still not perfect.  Only for UNIX, because most
non-UNIXes don't expand wildcards before passing command line to Kermit.  Still
not great.  "kermit -s a b c d" stops sending files as soon as it hits one
that doesn't exist (i.e. it doesn't skip past nonexistent ones).  But it was
always this way.

Simplified locking-shift protocol (pending approval by "the committee") to
require single shifts, and to be used only in combination with successfully
negotiated single shifts.  lshift.txt.

Changed locking shift negotiations accordingly.  ckcfns.c.

Set TRANSFER LOCKING-SHIFT to ON, rather than OFF, by default.  Won't be used
unless other Kermit announces this capability AND eighth-bit prefixing is
successfully negotiated.  ckcmai.c.

Totally rewrote getpkt() (again) to (a) make it more efficient, and (b) fix a
bug found by John Chandler, namely that locking shift codes could appear after
the repeat count rather than before it.  For example: XYZXYZaaaaaa (where
XYZXYZ have their 8th bits == 1, and aaaaaa don't) erroneously produced:
  #NXYZXYZ~&#Oa, which would be decoded as: XYZXYZ^O^O^O^O^O^Oa
rather than:
  #NXYZXYZ#O~&a, which would be decoded back into the original.
ckcfns.c.

Changed the translation tables for IBM code pages 437 and 850 to be totally
invertible.  Thanks to John Chandler and Andre' Pirard for the new tables, and
for keeping after me to do this.  Also removed as many of the UNK entries from
the Latin-1 to ASCII table as possible.  NOTE: MS-DOS Kermit's tables are not
invertible, so we still get bad translations for line/box-drawing chars when
sending CP850 files from CK to MSK.  ckuxla.c.

Made a first crack at adding support for Kanji character set translation
during file transfer.  All the Kanji-related code is within #ifdef
KANJI...#endif, and you have to add -DKANJI to your makefile entry if you want
to use it.  By default, all versions are built without it.  When KANJI is
defined, we use Japanese EUC as the transfer character set, and allow
Shift-JIS and EUC as file character sets.  So far, JIS X 0201 and JIS X 0208
are not supported as file character sets, but they can probably be added
easily.  Terminal character set translation is not yet supported, nor is
translation during the TRANSMIT command, nor is the TRANSLATE command.

The normal translation mechanisms (i.e. the array of translation functions,
translation tables, etc) is bypassed.  A small amount of extra code was added
to getpkt() and decode() which calls special algorithmic functions zkanji()
and xkanji() in ckuxla.c.  Japan EUC is announced in the attribute packet as
"I14/87E".  The Shift-JIS/EUC translation algorithm was adapted from code
provided by Dr. Hirofumi Fujii of the Japan National Laboratory for High
Energy Physics (KEK).  The choice of transfer character set and announcer was
made in conjunction with Dr. Fujii and other Kermit developers in Japan.
ckcxla.h, ckuxla.h, ckuxla.c, ckcfns.c.

Because Kanji within Japanese EUC is made up exclusively of 8-bit bytes (bytes
with their high order bits set to 1), a high degree of "8th-bit prefixing"
overhead (like 100%) would normally be incurred when transferring Kanji files
over 7-bit connections.  This is where the SET TRANSFER LOCKING-SHIFT command
comes into play.  With locking shifts, the overhead becomes insignificant.

Implemented Warren Tucker's suggestion of allowing an open file descriptor
to be passed to Kermit on the command line: -l nn, where nn is a number,
already locked (if necessary) and ready for i/o.  Works only for serial, local
connections, and it seems you have to tell Kermit the speed, also.  So, for
example, if you have opened a communication line at 2400 bps and you know its
file descriptor is 3, you can "kermit -l 3 -b 2400" to use it.  ckutio.c.

Changed the TYPE command to simply run the program specified in the TYPCMD
string, rather than using built-in code, at Christian Hemsing's suggestion.
Also, changed the TYPE, WHO, and DIRECTORY commands to look for the
environment variables CK_TYPE, CK_WHO, and CK_DIR, and if defined, use those
instead of the built-in commands.  This lets TYPE run more (or less), lets
you change the directory-command switches, etc.  ckuusr.c, ckuus6.c.

SMALL BUT IMPORTANT CHANGE: Got rid of LPASS8 processing for all but
SUNOS41/BSD.  Reportedly (by Terry Kennedy), this is what was causing binary
file transfers to fail on many, many 4.3BSD-based systems.  His speculation
jibes with the many other reports I got about binary file transfer failures
that couldn't be explained any other way: all of them came from people using
4.3BSD-based UNIXes.  At first I thought the problem only occurred when going
through terminal servers, but recent reports indicate it happens on direct
serial connections too.

Changed several args to ioctl(fd,fn,arg) from long to int, for PDP-11s, e.g.
for TIOCFLUSH calls in ttflui() and ttsndb().  I hope this doesn't harm anyone
else -- tested on SUN and NeXT with no ill effects.  From Steven Schultz.
ckutio.c.

Put #ifdef NOSPL around a couple references to maclvl in ckuus5.c that needed
them.  Thanks to Steven Schultz, Terry Kennedy for pointing this one out.

Added "pdp11" to the list of symbols that defines the maximum number of
wildcard matches (MAXWLD) to 50 rather than 1000, and smaller name string
space (SSPACE).  From Steven Schultz.  ckufio.c.

Changed the BSD 2.x makefile entries based on info from Steven Schultz,
who seems to have made the overlays work.  Added (for 2.x BSD only) Steven's
string extraction program and sed script as part of the make process.
makefile, ckustr.c (new), ckustr.sed.

Also installed ckubs2.mak from Terry Kennedy, an alternative makefile for
2.xBSD.

Changes to ckcnet.h #ifdefs for HPUX and to ckutio.c #ifdefs for HPUX job
control from Jim Barbour.  ckutio.c.  Also, yet another HPUX related makefile
entry, hpuxpre65, also from Jim.

When command-line -l argument is given, don't call ttgspd() to get the line
speed if the speed has already been set with -b.  Suggested by Dave Gluss.

Added support for Sequent Dynix PTX lockfile names to ttlock().  From Bob
Larson, USC.  ckutio.c.

Added makefile entry for ESIX SVR4+TCP/IP from Marc Boucher, U of Montreal.

Added makefile entry for SCO UNIX 3.2.2 with SCO TCP/IP from William Bader.

Added makefile entry "make install" suggested by Casey Leedom at LLNL.
Obviously this will need tailoring at different sites.

Added makefile entries for Altos machines with small memories, from Bertie
Coopersmith in London, sent via post.  Also two small fixes to ckucmd.c which
Bertie says keeps the Altos from dumping core.

Changed svr4amiganet makefile entry to use gcc rather than cc.

Fix for VMS INPUT command, which wasn't timing out, from Terry Kennedy:
gtimer() shouldn't have been calling rtimer().  ckvtio.c. 

NOT DONE: Changing the server to use pipes rather than temp files when
executing MAIL and REMOTE PRINT commands.  Have code for this from Seth
Chaiklin, but it will have to wait till next time.

Verified that C-Kermit works fine on the NeXT at 38400 bps.  There's no way
to set a higher rate, at least not using ioctl's with symbols defined in the
UNIX header files -- EXTB is the highest speed.

------------------------------

5A(172) Sat Jun 29 22:59:36 1991

Added GETOK command, to ask the user a question and then set SUCCESS or
FAILURE according to the user's answer, which is parsed from a keyword table
containing "yes", "no", and "ok".  For use in script programs.  Example:

  getok { Shall I go on\? }
  if failure stop

This command is removed from Kermit if NOSPL or NOFRILLS is set.  ckuusr.h,
ckuusr.c, ckuus6.c, ckuus2.c.

Added IF NUMERIC <constant-or-variablename>.  ckuusr.h, ckuus[r26].c.

SET FILE COLLISION UPDATE didn't work any more.  It refused the file all
right, but it deleted the existing file too.  Oops!  Reported by Nelson Beebe.
Fixed in reof(), ckcfns.c.

Made SHOW DIAL show default (built-in) dial init string (if any) instead of
"(none)" when user has not "set dial init-string".  ckuus4.c, ckudia.c.

Added optional numeric operand to END, POP, and STOP commands.  0 means to
set SUCCESS flag, nonzero means to set the FAILURE flag.  This allows macros
and TAKE file to return success or failure.

Create command synonyms for FTP users: PUT = SEND, MPUT = MSEND, MGET = GET.
ckuusr.c.

Changed all references to "alt-cyrillic" to "cp866", since the latter is
the character set we're really using.  ckuxla.c.

Changed zmail() not to put the word "file" in the subject line.  This paves
the way (not really) for a client program to use the "send-as" feature to give
the file-to-be-mailed an assumed name, which can be treated as the subject of
the mail message.  Unfortunately, no client programs do this as yet.  Another
barrier is that you can't create files with arbitrary names on most kinds of
computers, so the real solution to this problem is to make zmail pipe the
incoming file directly into Mail, and set the subject from the file header
packet data.  See note in rcvfil() in ckcfns.c.

Made "Usage:" message print actual name of program (argv[0]) rather than
"kermit", in case it was installed with another name.  Suggested by David
MacKenzie.  ckuus2.c.

Installed replacement code in ckudia.c for reading modem responses,
contributed by Jamie Watson.  It seems the original code kept comparing
responses with "didweget()" even after it found a match, so sometimes its
diagnosis would be wrong, like in the "RING" vs "RRING" case.  Now it stops as
soon as it hits a match.  ckudia.c.

Fixed data type of rfilop() routine.  Was declared int, should have been CHAR.
Noticed by Larry Rosenman.

HANGUP, revisited.  Changes from Jamie Watson in Switzerland for the RT PC,
plus one clue about why HANGUP might not be working for various other System V
systems -- in the default case, all the flags except CLOCAL are set to zero.
Jamie says that setting the HUPCL flag to zero specifically prevents DTR from
dropping.  So now let's try it the new way: set all flags except CLOCAL and
HUPCL to zero.  ckutio.c.  

Also from Jamie: he says the reason HANGUP didn't work on the RS/6000 was that
the TIOCMBIC/BIS ioctl's on the RS/6000 require an int, rather than (as SVID
says) a pointer to an int.  I made this change within #ifdef _IBMR2
conditionals (this symbol is predefined by the RS/6000 compiler).  RS/6000
users, please let me know if this helps or hurts.  ckutio.c

Corrected spelling: TIOC_RTS should be TIOCM_RTS.  Noticed by Jamie.  Jamie
also said that if you try to manipulate RTS and DTR in the same ioctl call,
everything gets screwed up.  So I left RTS alone (but again, only within
_IBMR2 conditionals).  ckutio.c.

Removed inappropriate error message when user edits WRITE command.  ckuusr.c.

Also at Jamie's suggestion, added -DTCPSOCKET to RTAIX makefile entry.

Added a makefile entry for the Commodore Amiga with Sys V R4 + TCP/IP,
contributed by Rob Healey.  Also, changed the names of the Kermit symbols
AT_ALL and AT_TYPE to AT_XALL and AT_FTYP (defined in ckcker.h), to eliminate
conflict with Sys V R4 vnode.h (Rob suggested switching order of #include
files, but that could have caused trouble).  Also, at Rob's suggestion,
replaced bzero with memset and bcopy with memcpy in ckcnet.c, but only for
SVR4 (to get around buggy UCB compatibility library).

Added makefile entry for RT PC with ACIS 2.2.1 = BSD 4.3.  Just like "make
bsd", but with -U__STDC__ added.  From a report by Mark Kennedy at IBM.

Added makefile entry for Ultrix 2.0.  It seems the TCP/IP code is different
there than in regular BSD, so -DDU2 activates a tiny snippet of code in
ckcnet.c.  Found by Jamie Watson (my Ultrix 2.0 MicroVAX died...).

Added -DDYNAMIC to HP-9000/HP-UX "hpuxlf" makefile entry (blessed by Bo
Kullmar in Sweden).

Apple Macintosh support for version 5A based on edit 171 from Paul Placeway.
New files in ckm*.*.  Recompiled with version 172 files OK.

Commodore Amiga support for version 5A based on edit 171 from Steve Walton.
New files in cki*.*.

OS-9 support for version 5A based on edit 171 from Christian Hemsing in
Germany.  New files: ck9*.*, plus several small alterations to ck[cu]*.[ch]
files within #ifdef OSK conditionals.

VMS changes from Terry Kennedy, St Peters College (notes from his CKVKER.UPD
file):

56. Correctly report the file size as (highest_block-1)*512+first_free_byte
    instead of allocated_blocks*512. (ckvfio)

57. Prevent captive or restricted users from invoking lib$spawn. This disables
    some built-ins (dir, etc.) as well as spawn/push. (ckvfio)

58. Fixed the LOG SESSION logfile. Previously it would contain random small
    chunks of text with extraneous line breaks. This change (of course) chan-
    ges the RMS structure of the session log file. (ckvfio, ckvcon)

59. Implement SET FILE TYPE LABELED for file receives. Also cleand up a few
    typos in the main code that dealt with labeled files. (ckvfio, ckuus3,
    ckuus5).

60. Correct a potential problem when flushing buffers after a disk error when
    receiving a file. (ckvfio)

Also from Terry, corrections to VMS labeled file support in ckuus3.c and
ckuus5.c.

------------------------------

5A(171) Wed Apr 24 12:36:02 1991

Added locking shift transfer protocol.  The new command is:

  SET { TRANSFER, XFER } LOCKING-SHIFT { ON, OFF, FORCED }.

Parsed in ckuus3.c.  Help text in ckuus2.c.  SHOW PROTOCOL and STATISTICS
material in ckuus4.c.  The negotiations are done in rpar() and spar() in
ckcfns.c.  The locking shift protocol itself is executed in getpkt() by the
file sender and decode() by the file receiver, both in ckcfns.c.  Locking
shifts are useful for transferring files containing long runs of 8-bit
characters through a 7-bit communication channel.  Good examples are Kanji,
Cyrillic, Hebrew, Arabic, or Greek text.  Binary files don't benefit very
much, nor do Roman-based text files.  Locking shifts are used in conjunction
with single shifts (8th-bit prefixes) for maximum efficiency in encoding 8-bit
data: long runs are lock-shifted, short runs are single-shifted.  To use this
feature, tell both Kermits to SET XFER LOCK ON (so far, only C-Kermit supports
this).  SET XFER LOCK FORCED means the sender uses locking shifts (but not
single shifts) regardless of negotiations, and for the receiver it means that
locking shift characters (Ctrl-N and Ctrl-O) in the data should be used as
shift characters rather than data, regardless of negotiations.  The new
protocol is described in detail in the file lshift.txt.

The interactive program prompt string is now evaluated each time the prompt
is issued, so you can have cute prompts like SET PROMPT \v(dir)>, or
SET PROMPT \v(time)>, etc, that change whenever the variables change.
ckuus3.c, ckucmd.c.

Added support for Wollongong TCP/IP for AT&T Sys V R3 on AT&T 3B series:
"make sys5r3net3b", from John Chmielewski at AT&T.  makefile, ckcnet.h.

Changed SET DIAL SPEED-CHANGING to SET DIAL SPEED-MATCHING, because this is
the term that is normally used, and inverted the corresponding logic.
ckuus2.c, ckuus3.c, ckuus4.c (SET DIAL, HELP SET DIAL, SHOW DIAL).

Fixed TRANSLATE, TRANSMIT, and CONNECT commands to correctly test for
language when determining the intermediate translation character set.  It's
not "language == L_RUSSIAN", but "langs[language].id == L_RUSSIAN".
ckuus4.c, ckucon.c.

Renamed file character-set "latin-cyrillic" to "cyrillic-iso".
Renamed transfer character-set "cyrillic" to "cyrillic-iso".  This makes
more sense, eh?  ckuxla.c, ckuus2.c.

Added "DOES NOT ANSWER" to the repertoire Rolm CBX responses.  ckudia.c.

Fixed SunLink X.25 support (many things were broken in a recent edit when
the network support was reorganized).  Fixes provided by Marcello Frutig
in Brazil.  Many modules.

Fixed shomac() not to core dump if the macro definition was a null pointer.
Still needs work -- the "more?" stuff only works for one macro definition.
ckuus5.c.

Fixed another bug in xxstring (the variable/function expander).  Some memory
was being malloc'd unnecessarily and later freed at possibly inappropriate
times.  The symptom was that certain functions, like \flpad(), \frpad(), and
\frepeat() would sometimes (rarely) fail to work if they appeared more than
once in a single command, e.g. "echo \flpad(\%a,8) \flpad(\%b,8)".  ckuus4.c.

Discovered that congm (get console terminal modes) prints scary error messages
if running under at, cron, or batch because open("/dev/tty") doesn't work ("No
such device or address").  Changed congm to skip mode-getting if !isatty(0).
ckutio.c.

Rewrote zchko().  There were two problems with it.  First, it copied the
filename into a local automatic fixed-size buffer that could easily have been
overrun.  Now it mallocs the buffer.  Second, reported by Fulvio Marino at
Olivetti in Italy, the call to access() would fail with EACCESS on X/OPEN
XPG3-compliant systems because zopen used "./".  Now "." is used if no
pathname is given, and "path/." is used if "path/" is included in the file
name.  ckufio.c.

Changed the assumption in ckcdeb.h that uid_t and gid_t exist for System V
R3.  No, they were first defined in SVR4.  The confusion stems from the way
that SVID issues are numbered.  "Issue 2" applies to SVR3, "Third Edition"
applies to SVR4.  This info from John Chmielewski, AT&T.  So the defaults have
now become:
    
  POSIX:      uid_t, gid_t
  SVR4:       uid_t, gid_t
  BSD43:      uid_t, gid_t
  All others: int, int

Watch out, some systems use short or unsigned short instead of int (even
though SVID Issue 2 Vol 3 says on p.31 they are "positive-integers").

Changed ckcdeb.h to automatically define NOSYSFILEH if POSIX is defined.
POSIX has no <sys/file.h> -- R_OK, etc, are defined in <unistd.h> instead.

Made -DTERMIOX the default for System V R4 (i.e. what you get when you
"make sys5r4"), meaning to use <termiox.h>.  Use "sys5r4nx" to omit it, or
"sys5r4sx" to use <sys/termiox.h>.

Added UID_T and GID_T definitions to tower32 make entries (from Robert
Andersson in Norway).

Made saval static in ckudia.c.  Previously it was declared global in both
ckudia.c and ckutio.c.

Fixed #ifndef NOSPL's in ckuscr.c (Bert Laverman).

Updated minixc68 and minix68k makefile entries (Bert Laverman).

Added a complete (?) list of C-Kermit's compile-time options as an appendix
to ckuins.doc.  Made corrections to ckaplm.doc.  Updated ckuker.mss,.doc,.ps.
Updated ckuker.bwr.

Some Amiga changes, and removal of (unused) "typedef long LONG", from Steve
Walton.

Some Fortune For:Pro 2.1 changes from Tom Krueger.

Reported problems not addressed in this edit:
. SVR4 suspend handling doesn't work (Ctrl-Z has no effect).
. File size is reported incorrectly on 16-bit machines...
. TRANSMIT command doesn't seem to work if TRANSMIT ECHO is OFF.
. switch statements in ckudia.c too long or deep for some compilers.
. There's no way to open the session log in append mode.
. Parity vs terminal servers vs LPASS8 vs rawmode...

VMS CHANGES:

Added new member to filinfo structure: unsigned int lblopts, for use with
labeled files.  ckcdeb.h.  Added definitions for VMS labeled file options to
ckcdeb.h, and a corresponding variable (bit mask), lf_opts, to hold them to
ckcmai.c.  Added SET FILE LABEL { ACL, BACKUP-DATE, NAME, OWNER, PATH }
command to ckuus3.c to set the lf_opts bitmask.  Copied lf_opts bitmask to
new lblopts member of the filinfo structure when opening a file, in opena()
in ckcfn3.c.  Added SHOW LABELED-FILE-INFO command to ckuus5.c.  Default for
NAME is ON, for others is OFF.  All of this is to allow the reception of
labeled files with selective restoration of the specified items, so Terry
Kennedy can actually add the code to receive labeled files in a future edit.

Made Kermit's command-line option interpreter ignore any fields
that begin with "/", so VMS switches can now be given on the command line,
like "kermit /input=foo.cmd /output=foo.log".  However, these switches have
no effect on Kermit because they don't actually make DCL redirect the input
or output -- the program has to do that itself.

------------------------------

5A(170) Tue Apr 23 22:21:07 1991

For VMS, from Terry Kennedy:

1. Fix to CKVFIO.C to properly handle the FAB journaling field (pre-3.1
   versions of VAX C don't understand "fab$b_journal").  Ditto for CKVCVT.C.
   ACL handling for labeled files added.

2. New makefile for VMS, using VMS MAKE (by Todd Aven, the Software Sweatshop,
   Long Beach, NY).  VMS MAKE itself is now available as CKVMAK.HEX, which
   is a VMSHEX-format encoding of a VMS BACKUP saveset containing the source,
   documentation, and executable files.  The new makefile is CKVKER.MAK, the
   MMS file (which was previously called CKVKER.MAK) is now called CKVKER.MMS,
   and there is also a new CKVKER.COM, which compiles all the modules
   unconditionally.

3. Removed "extern int errno;" declaration from ckcnet.h for VMS (it gets it
   from errno.h).

In edit 169, I removed what I thought was a duplicate #include for <fcntl.h>
from ckutio.c, but that kept Sys V versions from compiling.  Turns out it
wasn't really duplicated at all, so I put it back.  Sorry.

Finally tracked down the problem, reported by Jay Rouman, with getok() failing
to read modem responses when parity was not NONE.  I was ANDing the response
with the wrong mask in ttinc(): 0277 instead of 0177.  Actually, there is
another, deeper, problem: ckutio's global for parity, "ttprty", is set only by
ttpkt() but not by ttvt().  In practice, this doesn't matter because ttpkt()
is always called before any operation (dialing, file transfer) where parity
makes a difference.  During CONNECT, INPUT, or OUTPUT, the higher-level code
takes care of parity.  Not optimal, but better not to change the calling
conventions at this late stage.  Also, removed unused variable "m" from
ttinc().  ckutio.c.

Removed the assumption that POSIX can do a millisecond sleep using an ftime()
loop in msleep().  Until I learn better, the POSIX version just runs a stupid
busy loop for a short while.  ckutio.c.

Broke doprm() up into several smaller functions, for the benefit of some C
compilers that were having trouble with its length and block nesting level.
ckuus3.c.

Removed extraneous "x = 0;" from Sys V case in msleep() to get rid of
"statement not reached" warnings.  ckutio.c.

Removed "installation instructions" from the UNIX makefile and referred
readers to ckuins.doc, which contains more complete and accurate information.

Added missing comment delimiters to "#endif NETCONN" in ckuus5.c.

Adjusted #ifdefs for xx_strp in ckucmd.h (for SCO UNIX and Xenix); apparently
I did this wrong in edit 169.

Noticed that '-j' command-line option (= SET HOST) stopped working.  Added
#include "ckcnet.h" to ckuusy.c to make sure NETCONN definition was picked up.

Added system error message to DIAL "hangup error" message.  It seems we
always get "no such device or address".  Hmmm...

Got rid of yindex() routine from ckcnet.c, since it was only called from
one place, and was causing complaints from linkers when Kermit was built
without TCP/IP support.

Got rid of return-code variable from msleep() to eliminate "statement not
reached" warnings.  Also added a catcher for big arguments.  ckutio.c.

Removed the -i link option from several SVR3-based make entries.  Patrick
Wolfe of Kuck & Assocs reports that it is not known to SVR3-based compilers/
linkers on Esix, Intel, Olivetti, SGI, or Sequent SVR3 systems.  Added
comments where I took it out, and also comments in cases where I left it in
(such as all the PC-based makes).

After learning that the System V R3 <termiox.h> file (a) exists practically
nowhere, and (b) is sometimes found in <sys/termiox.h>, I backed off on the
assumption that makes based on SVR3 and later should expect to find it.
Now you have to explicitly include -DTERMIOX or -DSTERMIOX in the make entry
to get this form of RTS/CTS flow control.  The -DNOTERMIX flag was deleted
from all makefile entries, and four new entries were created: sys5r3tx,
sys5r3sx, sys5r4tx, and sys5r4sx.

Telnet negotiation loops reported.  Changed the code to behave according to
words of wisdom in the original telnet RFC 542: "The symmetry of the
negotiation syntax can potentially lead to nonterminating acknowledgement
loops -- each party seeing the incoming commands not as acknowledgements but
as new requests which must be acknowledged.  To prevent such loops: (a)
Parties may only request a change in option status; i.e. a party may not send
out a 'request' merely to announce what mode it is in; (b) If a party receives
a what appears to be a request to enter some mode it is already in, the
request should not be acknowledged."  The main problem was with the ECHO
and SGA negotiations, and this appears to be fixed now -- and still work
correctly (verified by telnetting to UNIX hosts and to IBM mainframe hosts).
There still seems to be some problem with the IBM mainframe sending several
"send terminal type" requests (which Kermit fulfills), but I think Kermit is
behaving properly in this case, as these are explicit requests for info.
ckcnet.c.

Improved the uucp lock-checking procedure to take into account EPERM
errors when testing for the existence of the process whose pid is recorded
in the lockfile, so now Kermit correctly reports that the device is in use
by another user (and shows who it is), rather than saying "Access to lock
denied".

Each ANSI C feature that is introduced seems to uncover more that are needed.
Steve Walton discovered that very strict ANSI compilers (such as the one he's
using on the Amiga), complain that the command-parsing function definitions in
ckucmd.c disagree with their prototypes in ckucmd.h.  So at his suggestion I
changed all occurrences "int (*f)()" in the argument lists to "xx_strp f",
which is typedef'd in ckucmd.h.  I had to change the typedef, however, for the
non-ANSI case.

Added another new compile-time option, -DNOANSI, to prevent the use of ANSI
C function prototyping in cases where they cause trouble.  ckcdeb.h.

Worked on TRANSMIT command.  Added SET TRANSMIT ECHO { OFF, ON }.  Added SET
TRANSMIT ECHO and SET FILE TYPE to SHOW TRANSMIT.  Made SHOW XMIT an invisible
synonym for SHOW TRANSMIT.  Totally rewrote TRANSMIT logic to echo if and only
if requested and to correct numerous problems like failure to send last buffer
in text mode if last line did not end with a line terminator, to insert
judicious pauses when a line turnaround ("prompt") character is not being
used, etc.  One test case fails miserably ("transmit foo", where file foo
contains 4000 x's), but that's not Kermit's fault.  The remote end (UNIX with
"cat > foo" active) just starts spewing out an infinite number of beeps after
the first 256 characters arrive, even though Xon/Xoff is active on both ends.

Removed scary error message that comes out on BSD-based systems sometimes
when DIAL HANGUP and DIAL DISPLAY are ON -- "hangup failed: no such device
or address".  For some reason, the ioctl that turns DTR back on sometimes
(not always) fails with this error.  But the subsequent close(open()) seems
to bring DTR back anyway.  Also, removed a gratuitous call to ttvt() from
within tthang().  ckutio.c.

For the ATT6300 only -- changed "if (debug) ..." to "if (deblog)".  This was
a dumb mistake, and drove the compiler crazy (now that it's doing ANSI type
checking).  Peter Mauzey noticed this one.  ckudia.c.

For POSIX, wait() returns a pid_t.  Added appropriate define to ckcdeb.h.

Moved "extern int errno;" (for all versions except VMS) to ckcdeb.h so all
modules have access to it, and removed "extern int errno;" from all modules
and header files except ckcdeb.h.  Certain modules still "#include <errno.h>"
and so may wind up with double declarations -- but not all <errno.h> files
include the declaration.

Minor cosmetic fix: if program was at command level and was suspended by
Ctrl-Z or with the SUSPEND command, then when it was fg'd again it would
display its command buffer, so the user could continue typing an interrupted
command.  This worked fine, except if a SUSPEND command had been given, in
which case the word "suspend" would appear again after Kermit was fg'd, with
the cursor sitting on its first letter.  Now the command buffer is redisplayed
only if the user was in the middle of a command.  ckuusx.c.

Added automatic implication rule for <dirent.h> for POSIX to ckcdeb.h, so
that anyone adding -DPOSIX to a makefile entry need not also add -DDIRENT.
Tested OK on SUN and DECstation 5800.

Noticed that you can't really run Kermit on the NeXT directly from NeXTstep.
If you launch it, NeXTstep makes a kind of terminal window for it and you can
type commands, but nothing really works.  So until somebody converts C-Kermit
to a real NeXTstep application, you have to start a real terminal window first.
Same deal, more or less, under OpenWindows on the SparcStation.

But Kermit works fine on the NeXT under Xterm.

Updated the user guide.  Added material about malloc debugging and core-dump
analysis to ckuins.doc.

------------------------------

5A(169) Fri Apr 12 13:30:57 1991

From Terry Kennedy: a brand-new CKVFIO.C that implements the sending (but not
receiving) labeled files.  For now, a separate program, CKVCVT.C, is provided
to decode labeled files uploaded (as binary!) to VMS.

From Piet Plomp: a new makefile for VMS C-Kermit.  Requires the DEC MMS
product.

From Thomas Krueger <tjk@csd4.csd.uwm.edu>: Fortune fixes, and also one for
everybody: it seems <fcntl.h> was being included twice in ckutio.c.

Correction for SCO Microsoft C on Xenix from Warren Tucker: this compiler
did not like the typedef for xx_strp in ckucmd.h, so now there is a special
one for M_SYSV.  ckucmd.h.

From Andy Fyfe: the stub for netinc() was missing an argument.  ckcnet.c.

Correct "statement not reached" at line 3983 of ckutio.c.  It was a typo
in the #ifdef (MLSFTIME != MSLFTIME).

Somehow all the work I put into addmmac() and addmac() disappeared (it
probably had something to do with watsun crashing every five minutes for most
of the week).  So I did it again.  Also, this time I found the real culprit
and fixed it (I malloc'd some space and then strcat'd strings to it without
zeroing it first; if malloc doesn't give you clear memory this would make
the strcats go off the edge).  ckuus5.c.

While looking at addmac and addmmac, I also found and fixed a problem with
delmac -- it was freeing storage for the wrong macro.  Oops.  ckuus5.c.

Then something much worse -- the _getargs command trashed memory on the NeXT.
Built Kermit with Howie Kaye's malloc debugging package and found several
problems and fixed them: mainly in xxstring() in ckuus4.c, a routine that
mallocs memory but doesn't always free it, and which calls itself recursively.

Finally it turned out that an automatic array in the new dogta() routine was
declared too small and a pointer was being overwritten.  Howie spotted it.
Thanks Howie.

Howie's malloc debugging module is now part of the C-Kermit distribution.  The
module name is ckcmdb.c.  Two make entries show its use: nextmd and sunos41md.
If anybody is having problems potentially attributable to malloc and free,
construct similar entries for your computer, rebuild, and run wermit with a
debug log.

Some people complained that ckuusr.c was still too big and causes hash table
overflows, etc.  I broke ckuusr.c in half, creating yet another new module,
ckuus6.c.

Fixed #ifdefs in tthang().  ckutio.c.

Made sure all n_NAME symbols in ckudia.c were unique.

Added more debugging statements to getok() in ckudia.c.

Fixed IBM linemode telnet, from a suggestion from Steve Layton
<swl27@cas.bitnet>.

Added a missing close comment delimiter in tthang() which gcc didn't catch!
Found by Andy Fyfe.  ckutio.c.

New makefile entries for 3B1 (UNIX PC) from Andy Fyfe.  makefile.

Change "\l" to "\n" in ckcmai.c for MINIX, Bert Laverman.  Somebody else
(Chuck Hedrick, maybe) had inserted these, don't know why.

Added additional debugging statements to ttlock() to help track down problems
with uugetty in SCO UNIX 3.2.2, from Warren Tucker.  ckutio.c.

Some notes on program size...  Here is how the program shapes up on a
Sun-4 (a RISC architecture machine, so big executables) built with various
options (all include the -s link option):

 417K  Full (except X.25)
 401K  No transaction log (-DNOTLOG)
 401K  No "frills" (-DNOFRILLS)
 393K  No DIAL command (-DNODIAL)
 385K  No character set translation (-DNOCSETS)
 368K  No debugging (-DNODEBUG) 
 401K  No network support (-DTCPSOCKET omitted)
 180K  Minimum interactive (-DNOxxx for all xxx except ICP)
 114K  Command-line only.

------------------------------

5A(168) Mon Apr  8 19:28:28 1991

New items for the VMS version from Terry Kennedy: allowance for expansion
factor in checking available disk space for incoming files; replacement for
zoutdump() from Gary Mussar (allows for some odd record-boundary conditions).
Removal of VMS-specific return codes from ckcdeb.h.  For details, see
ckvker.upd.

Fixed a place where doexit() was called without its second argument if
NOCCTRAP was defined.  Thanks to Terry Kennedy for noticing.  ckuusx.c.

Removed #include <sys/types.h> from ckutio.c because ckcdeb already includes
it.  Causes problems on systems like Tandy where this file doesn't protect
itself against multiple inclusion.  Thanks to Jay Rouman.

Changed msleep() from parallel, sequential #ifdefs to nested #ifdefs to prevent
compilers from complaining about "statement not reached".  Thanks to Jay
Rouman for pointing out the problem.  ckutio.c.

In edit 167, I assumed that UID_T and GID_T could be defined as uid_t and
gid_t in all AT&T UNIX versions.  Wrong.  Now they are int for System V R2 and
earlier (verified by checking SVID R2 and R3, as I should have done in the
first place).  Thanks again to Jay Rouman for noticing.  ckcdeb.h.

Fixed a bad problem with the DIAL command.  The most common symptom was that
dialing would not work if the PARITY was not NONE.  The reason was that the int
returned by ttinc() was being assigned directly to a signed char in the
getok() routine.  Now ttinc() is assigned to an int, and the int is truncated
and assigned to an unsigned character.  Thanks to Jay Rouman for reporting the
problem.  ckudia.c.

Removed an extraneous alarm() call from ckudia.c.

Reduced size of command buffers if -DNOSPL is selected, to save a few K.
ckucmd.h.

Fixed HELP command to speak the truth in various -DNOxxx configurations.
ckuus2.c.

Changed HELP command not to allow any subtopics if -DNOHLP.  ckuusr.c.

Changed the argument vector array to be \&@[] instead of \&a[] for aesthetic
reasons; the name of the argument vector should be special.  Made the new
argument vector array read-only.  ckuus[r45].c.

Added character set information to transaction log.  ckcfn[s3].c.

Cured a longstanding problem with INPUT: its timeout interval wasn't very
accurate, and furthermore it never timed out at all as long as characters
arrived in a steady stream.  Now it works properly.  ckuus4.c.

Added "convex9" entry to makefile based on info from Eric Schnoebelen at
Convex.  This is another working POSIX entry, but with the BSD 4.3 lockfile
convention.  Also, fixed getpgrp() call in ckutio.c to have an argument only
for non-AT&T, non-POSIX configurations.  Also, wrapped extern declaration of
getppid() in ckufio.c within #ifndef's for POSIX and SVR3, where it is already
declared in <unistd.h>.  Thanks to Eric Schnoebelen at Convex for the info.

Noticed that MYREAD was not defined for POSIX, so I defined it.  ckutio.c.

Jay Rouman pointed out that \v(time), \v(date), etc, did not work in POSIX
configurations.  That's because I forgot to add POSIX coverage to ztime().
Done now, on the possibly erroneous assumption that POSIX uses time() and
ctime() like System V.  ckutio.c.

Made msleep() call usleep() on NeXT and SUN.  select() was not a good choice
for the NeXT, which (of course) has redefined the calling conventions from
BSD -- it wants a list of some kind of hideous incomprehensible structure
pointers.  This makes the gcc -Wall warnings go away.  Also, Sys V builds
on the SUN previously had no way at all of msleep'ing -- now they do.
ckutio.c.

The call to ttres() in ckcpro.w that occurs at the end of a file transfer had
been commented out a long time ago at somebody's insistence.  I discovered
that this was the cause Kermit's failure to properly restore interrupt, quit,
and suspend characters after exiting the program if any files had been
transferred in remote mode.  See ttpkt() and ttres().  I uncommented it, and
now terminal interrupts seem to work fine again.

Made sure that ckcpro.w does not try to output terminal messages when in
background (probably need to do more of this elsewhere).  This started the
following detour:

Discovered that I could not run Kermit in the background any more.  The
problem (this time, ho hum) was that popclvl() was being called when Kermit
reached the end of its init file.  When popclvl() pops up to top level, it
calls concb() to put the console (back) in cbreak mode.  Doing this (at least
on BSD based systems) causes Kermit's process group to change into the same
one as the terminal's process group, so now conint() thinks Kermit is in the
foreground when it's really still in the background (just ask the shell!),
which in turn lets Kermit print messages to the screen, which in turn makes it
stop because it's trying to write the terminal when it's in the background.
To fix this, I told congm() "console get modes" not to bother getting the
terminal modes if Kermit is in the background, and concb() not to do anything
if Kermit is in the background.  An added benefit of this change is that
conres() "console restore modes" does not wreck your terminal modes if you
should happen to have started Kermit in the background (e.g. with "&") and
then fg'd it and exited.

Well, that's fine for the BSD version, but now the Sys V and POSIX versions
are totally broken, at least on the SUN.  I wasted hours and hours on this.
It seems that getpgrp() on the SUN returns garbage about half the time --
sometimes it returns the real process group, other times 0, and still others
-1.  So I added code to conint() to only believe the return value of getpgrp()
if it was greater than 0.  I tried the same code on the RS/6000 and it works
fine, so I'm willing to believe it's the SUN's fault -- trying to be all
things to all users...  It's probably something to do with the fact that Sys V
getpgroup takes no argument, but the BSD one does, and the Sys V version is
really the BSD one, and it's reading garbage as its argument.
The same thing happens on the SUN with "sunposix".  Anyway, the aforementioned
fix seems to work, in the sense that it keeps the prompt visible.  But this
prevented background operation from working at all, because getpgrp() fails
just as much when Kermit is in the background as it does when it's in the
foreground...  So I changed conint() YET AGAIN.  This time, if the getpgrp()
test fails, it does the SIGINT == SIG_IGN test instead.  And in both cases,
it also checks to see if it's running with redirected stdio, and that case
is treated like background too.  This seems to work ok in the Sys V version,
but not in the POSIX version unless I start Kermit from the Bourne shell.
I could go on, but it's making me sick.  ckutio.c.

To do: If Kermit is in server mode or somesuch on an external tty device, in
the background, and then it gets fg'd, it should rearm its SIGINT and SIGTSTP
interrupts so the user's terminal doesn't freeze forever.  Oddly enough, this
works by accident in the BSD version (dunno why), but in the Sys V and POSIX
versions, you have to go to another terminal and kill the process.

Discovered (and fixed) a typo that disabled job control for everybody who
should have it, and enabled it for everybody that shouldn't, oops.  An #ifndef
should have been an #ifdef...  puspend() in ckutio.c.

Roger Wallace reported that (some) SET SEND/RECEIVE command had suddenly
stopped working.  This was because I broke a switch statement in the wrong
place in the last edit.  Fixed now.  ckuus3.c.

Added support for terminal character set translation, shift in / shift out,
pushing to DCL, and "set debug session" to CKVCON.C, the VAX/VMS CONNECT
command module.  Also added telnet support within #ifdef NETCONN..#endif (but
of course, this is not turned on).  This was done mostly by pasting code from
ckucon.c into the appropriate places in ckvcon.c.  Noticed a few suspect items
in ckucon.c in the process and fixed them.

Began work on isolating network support into a separate module, ckcnet.c:

 1. Made a new symbol TCPSOCKET.  This means that TCP/IP sockets support
    is selected, using the Berkeley sockets library, and it implies that
    telnet protocol support is selected too.  The SUNX25 code also uses the
    sockets library, but does not do telnet.
 2. Changed all references to NETCONN in the makefile to TCPSOCKET.
 3. Removed all network-specific #includes and #defines from ckcdeb.h,
    ckucon.c, and ckutio.c, and moved them into ckcnet.h.
 4. Made ckcnet.h define NETCONN if TCPSOCKET or SUNX25 is defined.
 5. Moved network-specific routines from ckucon.c to ckcnet.c.
 6. Changed tn_doop() to give return codes to indicate whether the local
    echo status needs to be changed, and change conect() to use these codes.
    To do this, it must know the current duplex, so this has been added as
    an argument to tn_doop(), and all calls and prototypes have been changed.
 7. Moved netopen(), netclos(), and related routines from ckutio.c to ckcnet.c.
 8. Moved all X.25 code from ckutio.c to ckcnet.c.

Items 7 and 8 required detailed reconstructive surgery.  The result works
ok on the SUN, NeXT, and RS/6000 with TCP/IP, needs testing everywhere else.

Now, armed the TGV MultiNet manual for VAX/VMS I added a small amount of code
to CKVCON.C to allow for network connections, and added code to the ttxxx()
routines in CKVTIO.C to call the netxxx() routines if a network connection was
active.  The ckcnet.[ch] files should just about fit in without changes.  If
this works I'll be amazed...

 1. Compile VMS C-Kermit without NETCONN or MULTINET defined (OK).
 2. Modify CKVKER.COM to define MULTINET if MultiNet exists (OK).
 3. Recompile all modules with MULTINET defined.
 4. Figure out how to link the stupid thing with TGV's runtime system.

Because MULTINET:MULTINET_SOCKET_LIBRARY.EXE must be linked in as a sharable
library, a linker "options file" must be used (see the VMS Linker manual).
But when you use a linker "options file", it would seem that you have to
specify at least one module that is not in a library (LINK's complaint is
"%LINK-F-FIRSTMOD, first input file being a library requires module
extraction").

So...  The linker option file CKVKER.OPT was created, and CKVKER.COM was
modified (ugh!) to extract one module (CKCMAI.OBJ) from WERMIT.OLB before
linking.

Modified CKVKER.COM to define MULTINET automatically if it finds the Multinet
socket library.  I'm not a DCL programmer, so there's probably a better way
to do it.  See comments in CKVKER.COM.

Three days later... it works.  File transfer ain't bad at all.  But it's
horribly slow during CONNECT mode, at least on my MicroVAX II.  That's because
the VMS C-Kermit CONNECT command does not use two forks, like the C-Kermit
version does.  Instead, it uses a horrible kind of polling kludge (in the
contti() routine) because VAX C does not (at least as of V3.2) have a fork()
call.  If fork() were available, we could replace CKVCON.C with ckucon.c and
be done with it.

In an attempt to improve the speed, I added an internal network input buffer
to ckvtio.c and made the network code use it (another day).  No noticeable
difference.  It's incredibly slow.

This has been an exercise in making the network code more portable.  I dunno
how many people will actually be able to use the MultiNet support, but now it
should be easier to add support for other networks to both the UNIX and VMS
(as well as any other) versions of C-Kermit.  For example, now that most of
the SunLink X.25 code is in ckcnet.[ch], it might be relatively easy to adapt
it to also support VAX PSI on VMS -- at least the concepts are the same.

Added section on networks to CKAPLM.DOC.

Added SHOW NETWORK command.

Fixed SET HOST command when no hostname given.

Removed extraneous spaces from makefile (again).

Moved congm(), conres(), around to better ensure console modes properly
restored upon exit.  ckuus5.c, ckutio.c.

Added Telebit fixes from tk, Hellmuth Michaelis.

Improved HP-UX hangup from Hellmuth Michaelis.

Makefile entry for HP-UX 7.0 with network support from Hellmuth Michaelis.

Support for two more Telebit variations from Hellmuth Michaelis: V.42
and "slow" (i.e. don't even try to dial in any fancy mode).

Fixed POSIX version of ztime() to use BSD/V7 style time(), asctime(), and
localtime().

Fixed SHOW PAD command for SunLink X.25 (again).  Thanks, Marcello.

Added -X2 to dnix makefile entry to cut down on compiler complaints.
Bo Kullmar.

Fixed makefile entry for minixc68.

Changed name of _PROTOTYPE macro to _PROTOTYP because apparently it conflicts
with a predefined macro of that name, e.g. with the GNU cc cross compiler for
68000 code on SUNs.

Various fixes to ckutio.c for MINIX from Bert Laverman: Renamed variable
"clock" to "xclock" to prevent conflict with library routine clock(), Don't
include <sys/ioctl.h> because there isn't one, fix some function args, cast
some things, remove unnecessary prototypes, etc etc.

Fixes to the Apollo SR10 makefile entries from Chuck Fuller.

Put timer interrupt in ttclos() so we wouldn't hang up on exit, etc, any
more.  ckutio.c.

Added a new system symbol, SUNOS41.  It turns out there is another difference
between 4.0 and 4.1: the former did not have <stdlib.h>, the latter does.
ckcdeb.h.

Created YET ANOTHER new data type, PWID_T.  This is the type of the argument
expected by getpwid().  By default it is the same as UID_T, but it can be
changed independently, as it must be for SCO UNIX 3.2.2, where it has to be
int.  Use -DPWID_T=xxx in your CFLAGS to specify a getpwuid() arg type that
is different from UID_T.  ckcdeb.h, ckufio.c, makefile.

Removed forward declaration of real_uid() in ckutio.c.  Sergey Kartashoff,
Moscow.

The docmd() routine in ckuusr.c, even though the humongous switch()
statement was broken up into many smaller ones, is still too complicated for
some C optimizers, including VAX C 3.0.  Reportedly, on Microport System
V/AT 2.4 it crashes the compiler with "hash table overflow".  Ditto on ATT
6300.  On another AT&T system, it has "too many labels".  So no more switch
statements, now just a lot of if statements.  Let's see if that helps...
(It didn't help on the VAX -- optimization of CKUUSR.C is still suppressed.)
So then I took all the big chunks of code completely out of docmd() and
moved them to their own little functions within the same file.  That (at
least) made VAX C happy.  Phew!

If suspend is disabled and user tries to suspend, C-Kermit should now reissue
its prompt.  ckuusx.c.

Several people reported that edit 167 core dumped when starting up, and
traced the problem to a malloc call in addmac for the builtin multiline _forx
macro, now installed via the new addmmac procedure, which concatenates a
multine macro definition into a single string and then calls addmac to enter
it.  Reportedly, the core dumps happen only when debug is off.  If you start
Kermit with -d, the problem doesn't happen.

Piet Plomp in the Netherlands found that malloc in addmac was being called
with an argument of 0: strlen(nam) + 1 == 0 implies that strlen returns -1,
which should never happen unless the we have a string longer than 0x7FFF!
An inspection of addmac() did not show how this could happen, but it did
reveal that malloc was actually being called for the same name string twice.
So I removed the extra call to malloc, and I added lots of range checking
and debugging statements to both addmac and addmmac.

All this just to get around a restriction on the length of constant strings
imposed by some old C compilers.

------------------------------

5A(167) Fri Mar 29 21:36:58 1991

Put reference to TIOCSETD in ttres() within #ifdef TIOCSETD..#endif.

Moved #include <net/errno.h> for Interactive SVR3 (I386IX) further down.
Something was wiping out the definition of ENOTCONN where it was before.
ckutio.c.

Changed prototype for netclos() to spell it right (no 'e').  ckutio.c.

Moved call to conint() in stptrap() higher up, to make sure suspend trap
is rearmed asap.  Thanks to Peter Jones for noticing this STILL didn't work
on MIPS in edit 166.  And it still might not work!  ckuusx.c.

Moved #includes of Kermit-specific header files to below system header files
in ckuus3.c and ckufio.c to ensure that Kermit definitions take precedence
over system definitions.  For example, ATT Sys V R4 defines AT_ALL and AT_TYPE
(Kermit file attribute symbols) in <sys/vnode.h>.  Thanks to Andrew Herbert at
Monash U in Australia for pointing out the conflict.  This required a lot of
shuffling in ckufio.c, so testers watch out!

Protected Kermit header files against multiple inclusion.  ck*.h.

Continued ANSIfication.  More function prototypes added to header files and
most forward declarations of functions removed from C source files.

The -DNOTERMIX (no <termiox.h> file available) switch added to makefile
entries based on reports from testers: MIPS, Xenix SVR3 variations, ...

Added dialhup routine to ckudia.c.  Replaced all calls to tthang() from within
DIAL with this.  Changed tthang() to return 1 if it succeeds, 0 if it doesn't
even try, and -1 if it fails.  dialup() prints a message during dialing saying
whether DIAL is hanging up (if DIAL DISPLAY is ON).

Installed a correction to ttpkt() line speed setting code from Andy Fyfe at
Cal Tech.  Fixes problems some people have reported with DIAL happening at
the wrong speed.  ckutio.c.

Improved -DNOSPL (script programming language deselection compile-time option)
to still allow \nnn numeric escapes anywhere in a command.  ckuusr.c.

Fixed STATISTICS command to report effective data rate when program is
built with -DNOTLOG.  ckcfns.c.

Andrew Herbert says that his System V R4 version of Unix creates lockfiles
with names like LK.035.mmm.nnn, containing the major and minor device numbers
of the tty device.  Added code to ttlock() to handle this, controlled by
#ifdef LFDEVNO.  Defined LFDEVNO automatically if SVR4 is defined, on the
no doubt naive assumption that all Sys V R4 systems will be compatible in this
respect.  Needs major() and minor() macros, which may or may not be defined in
<sys/types.h> or <sys/mkdev.h> or <sys/sysmacros.h> or ...???  ckutio.c.

Added -DNOCYRIL compile-time switch to deselect the Cyrillic character set
translations, but still keep the others.  ckcxla.h.

Updated ckuins.doc to include the above two items.

Many edits ago (last summer) I wasted some days trying to program a FOR-loop
mechanism into the C-Kermit command parser, and eventually gave up and
"simply" implemented it as a macro, passing the parts of the FOR statement to
the macro as arguments.  This allows deeply nested loops, etc.  Then I did
WHILE loops the same way, and XIF (extended IF) the same way too.  BUT...
since these are implemented as macros, you couldn't use them inside of other
macros and use the enclosing macro's arguments in the object command of the
FOR, WHILE, or XIF statement.  For example:

  def aa for \%i 1 3 1 { echo \%i and \%1 }
  do aa 3

would echo "1 and %i" etc, instead of "1 and 3".  This restriction is now
lifted.  First I added two invisible commands: _getargs lets a macro replace
its own arguments with the arguments of the macro two levels up; _putargs lets
a macro replace the arguments of the macro two levels up with its own.
ckuusr.c.  Then I just added _getargs and _putargs commands in the definitions
of the FOR, WHILE, and XIF macros (these are macros that define another macro
and then execute it, hence the "two levels").  ckuus5.c.  (** NOTE: still
have to do something about RETURN and END issued from within these commands!)

Broke up the big switch statement in ckuusr.c into many little ones.  This
should fix the problems that some compilers have been having.

Broke up the big switch() statement in ckuus3.c into many smaller ones.

Put some feature-specific symbols in .h files into #ifdefs to cut down on
cpp symbol table size.  Maybe I need to do a lot more of this.

Casted all char/CHAR implicit conversions in function calls, as well as other
types of argument / pointer mismatches that were causing ANSI compilers to
complain.  Hundreds and hundreds of them...  Now GNU cc compiles C-Kermit on
the NeXT with -Wall (all warnings on) with only a few minor complaints.
Fixing these is left as an exercise to the reader (I can't do it!).  All
modules affected.

Added makefile entries for Minix on 68000-based machines (Atari ST, Commodore
Amiga, Macintosh) from Bert Laverman in the Netherlands.

Added support for Fortune For:Pro 2.1, which included a few fixes that might
be relevant for V7, Minix, Coherent, etc.  From Thomas Krueger.

Broke the string definitions for built-in macros up into arrays to get around
string-constant length restrictions in some compilers, and inability of some
compilers to handle line continuation within string constants.  ckuus5.c.

Changed keyword tables to use short rather than int to save a few K.  Could
save even more by using char, but that would unleash reams of complaints from
type-checking compilers.

Added new code to support X.25 call user data (SunLink X.25 only) from
Marcello Frutig in Brazil.

Added mechanisms to ck[cu]xla.h to allow addition of Japanese Kanji character
sets.  The actual translation support will be added later.

Added support for Sequent DYNIX/PTX to makefile file, "make ptx".

Added POSIX function calls to cku[ft]io.c for "make posix", removed all
ioctl() calls if POSIX is defined.  This is a totally new line of source code
selection and does not follow any of the System V or BSD specific code, except
in cases where System V code is explicitly shared via the new #ifdef
SVORPOSIX.

I have no idea if this was done correctly, since I don't have an up-to-date
POSIX specification yet.  Information based on SUNOS 4.1 man pages and header
files.  There seems to be no way in POSIX to (a) get modem signals, or (b)
check the tty input buffer without reading it.  Compiles and links OK on the
SUN, which supposedly provides a POSIX-compliant environment if you define
_POSIX_SOURCE, but without an ANSI standard C compiler (the opposite of the
NeXT, which has Standard C, but not POSIX functions).

The program runs on the SUN without core dumping.  Amazingly, most features
seem to work: remote mode file transfer, wildcard expansion and filename
completion, tilde expansion, CONNECT mode, local-mode file transfer, etc.

POSIX questions:

 - What is the real POSIX name for d_ino?  d_fileno or gd_ino or what?
 - How to read modem signals?
 - How to check tty device input buffer?
 - Correct/preferred way to do nonblocking reads (O_NONBLOCK)?
 - Where are the major() and minor() macros located?
 - Does it have <sys/termiox.h>?
 - Where are fflush, fclose, [fs]printf, [fs]scanf, rewind, toupper, tolower,
   _filbuf, _flsbuf, [f]puts, perror, fclose, ungetc, setbuf, wait, pclose
   supposed to be declared?
 - How to do millisecond sleep?  (usleep()?)
 - What's different about POSIX job control?
 - What is symbol for maximum filename name length and where is it defined?
   _D_NAME_MAX, _POSIX_NAME_MAX, NAME_MAX, FILENAME_MAX, or what?
 - Ditto for pathname length.
 - Watch out for getpgrp() vs getpgrp(0)

In ttclos(), hang up the phone first, then reset the device modes (rather than
the other way around).  ckutio.c.

Put all job control (suspend) code within #ifndef NOJC..#endif conditionals.
Add -DNOJC to MIPS and SCO UNIX 3.2.0/3.2.1 makefile entries, created new
makefile entry sco3r22 for SCO UNIX 3.2.2, which does indeed support job
control.  ckutio.c, makefile.

Updated ckuins.doc, ckuker.bwr.

Modified SCRIPT command to not echo the script string if it's being executed
in a TAKE file and TAKE ECHO is OFF, or if it is being executed in a macro
and MACRO ECHO is OFF.  ckuscr.c.

Changed doclean() to call conres() and connoi() AFTER executing the on_exit
macro, rather than before.  Previously, if you had an on_exit macro defined,
your terminal modes could be fouled up after exiting from Kermit.  ckuusx.c.

Fixed telnet support in ckucon.c to handle unknown telnet options by refusing
to do them.  Previously, it just ignored them.  Also, allow for negotiated
mode changes from local echo back to remote echo.  Also, don't attempt to
print the name of an unknown option to the debug log or debug screen, print
"unknown" instead.  These three fixes allow SET HOST to a NeXT to work.  The
NeXT telnet server attempts to negotiate a lot of options that Kermit doesn't
support, like terminal speed and linemode (not to mention a few that aren't
even in the NeXT's <arpa/telnet.h> file!).  ckucon.c.

After all the changes described above, compiled, linked and ran the program
successfully on:

 [ok] MicroVAX-II VMS 5.3 (@ckvker.com)
 [ok] MicroVAX-II Ultrix 2.0 (make bsd)
 [ok] VAX-11/750 with 4.3BSD (make bsd43)
 [ok] Encore Multimax 510 with UMAX 4.3 (make encore)
 [ok] SUNOS 4.1 BSD environment (make sunos41)
 [ok] SUNOS 4.1 SVR3 environment (make sunos41s5)
 [ok] SUNOS 4.1 POSIX environment (make sunposix)
 [ok] SUNOS 4.1 POSIX environment with gcc and -Wall (make gccsunposix)
 [ok] NeXT with gcc and -Wall (make nextg)
 [ok] DECstation 5800 Ultrix 4.1 BSD environment (make du4)
 [ok] DECstation 5800 Ultrix 4.1 POSIX environment (make posix)
 [ok] IBM RS/6000 AIX 3.1 (make rs6000)

Phew!

------------------------------

5A(166) Sun Mar 17 00:36:15 1991

Major fix from Paul Placeway: the spack() function cleverly manipulated the
data buffer pointer to avoid recopying packet contents, allowing the packet
control fields to be deposited around the prebuilt data field in place.
However, each time it was called, it backed up the "data" pointer again, but
never restored it to its original position.  After repeated calls to spack(),
all sorts of memory could be trashed.  The problem never showed up on most
systems, but had horrible effects on others, depending on how the linker
ordered variables, where things were malloc'd to, etc.  Solution: manipulate a
local copy of the data pointer in spack() rather than the global copy.
Thanks, Paul!  ckcfn2.c.

Also from Paul: A more efficient implementation of debug() that avoids
function calls unless debugging is actually requested, at the cost of an
"if" test:

  #define debug(a,b,c,d) if (deblog) dodebug(a,b,c,d)

Also I cleaned up the program to make sure that all explicit references to
deblog were within #ifdef DEBUG..#endif.  This frees up even more space with
compiling with -DNODEBUG.

The new definition of debug() should reduce execution of the program at the
cost of some space.  To put things back the way they were, change this to:

  #define debug(a,b,c,d) dodebug(a,b,c,d)

Checked performance before and after this change on a long file transfer
from a SUN-4/280 to a PS/2-50.  No apparent difference.  Presumably an
improvement would be noticeable on a slower computer.  ckcdeb.h and ckuusx.c.

UNFORTUNATELY, this innocent-looking change adds about 16K to the program
size, at least on RISC architectures like SPARC.  Backed off as shown above
except for Macintosh (Paul says it makes a noticeable performance difference
on the Mac).  ckcdeb.h.

Changed dodebug() to malloc its string buffer rather than allocate it
statically, to save about 2K.  ckuusx.c.

Made "in" an acceptable abbreviation for "input" ("i" already was). ckuusr.c.

Added telnet option negotiation support to INPUT and OUTPUT commands, so now
script programs can work on telnet connections too.  (Funny nobody noticed
this never worked before...)  ckuus4.c, ckuus5.c.

Added SET FILE TYPE BINARY [ { FIXED, UNDEFINED } ] to the VMS version.  This
allows the user to specify whether received binary files should be marked as
having FIXED or UNDEFINED record format in the RMS attributes.  The file is
stored in exactly the same format either way.  This is to accommodate an
application called "Thoroughbred BASIC", which perversely requires its program
and data files to be "undefined sequential".  ckuus3.c, ckuus4.c (for SHOW),
ckcfn3.c, ckcfil.h, plus changes by Terry Kennedy to ckvfio.c.

Added a call to conint(trap,stptrap) in stptrap() itself, after the suspended
Kermit is fg'd (continued), so the suspend interrupt trap is rearmed.  This is
required for System V.  Many thanks to Peter Jones and Warren Tucker for help
with this one.  Removed special "no-suspend" default for MIPS.  ckuusx.c,
ckcmai.c.

Got rid of the bit in ckcmai.c that declared nettype to be "TCP/IP streams"
for System V systems except if there was an explicit #ifdef to make it BSD
sockets (like there was for about 10 different ones -- HPUX, Xenix/Excelan,
A/UX, etc etc etc).  After all, C-Kermit doesn't support TCP/IP streams
anyway, so I just made the default network type to be TCP/IP Sockets for all
UNIX implementations that define NETCONN.  This was prompted by noticing that
"set host" didn't work on the RS/6000 until after I gave the command "set
network tcp/ip".  Now it works fine.  Also made a few other minor changes to
get Kermit to compile cleanly and look better on the RS/6000 with AUX 3.1.
Also, added "LNKFLAGS = -s" to the makefile to strip during linking.  This
reduces the size of the program on disk by about 200K (!) (from 600 to 400 --
love that RISC architecture).

Made \v(filespec) work for arriving files too.  One line of code added to
rcvfil(), ckcfns.c.  And for files that the server gets a GET command for, one
line added to fnparse(), ckuusx.c

Changed zsout() to use write() rather than fputs() for session log, to keep
WRITE SESSION and other session log material synchronized.  ckufio.c.

Changed dooutput() to write to session log only on half duplex connections.
Otherwise, doinput() writes the echo.  ckuus5.c.

Add optional syntax to INPUT command: INPUT n {text}.  Use optional
orthodonture (braces) around INPUT text to prevent leading or trailing blanks
from being stripped.  Ditto for OUTPUT command.  Until now, it was not
possible to have INPUT or OUTPUT strings with leading or trailing spaces.
This is similar to the change that was made to SET PROMPT a while back.
To actually INPUT a string that begins and ends with braces, use 2 of each,
as in "INPUT 20 {{foo}}".  ckuusr.c.

Added REDIAL command.  ckuusr.[hc], ckuus2.c.

Changed doexit() to prevent the ON_EXIT macro from calling itself
recursively, for example if a user put an EXIT command in the ON_EXIT
definition.  ckuusx.c.

Made server execute cleanup code from doexit(), including running the
ON_EXIT macro, when a BYE command is received.  ckcpro.w, ckuusx.c.

Made SET FILE TYPE BLOCK be an invisible synonym for SET FILE TYPE IMAGE for
VMS, for compatibility with Kermit-32.  ckuus3.c.

Fixed DIAL command to show all dialer output, rather than just the part that
doesn't match the "waitfor" string, when SET DIAL DISPLAY is ON.  Also make
sure that "Call completed." message comes on a new line if DIAL DISPLAY is
ON.  ckudia.c.

Added partial completion for filenames, within #ifndef NOPARTIAL..#endif, in
cmifi() in ckucmd.c.  Works fine in UNIX and VMS.  For partial completion, I
had to make mtchs array in ckufio.c and ckvfio.c global rather than static
(hidden).  If this breaks any implementations, they should compile with
-DNOPARTIAL.  Changed ckasys.doc to include description of "char *mtchs[]".

Changed the definition of CR in ckcasc.c from '\r' to 015.  We want a real
carriage return here, not whatever the C compiler defines \r to be.  This
messed things up quite a bit on the Macintosh, where MPW C 3.0 appears to
define \r as linefeed (???).

Changed name of command keyword structure member "val" to "kwval" because some
old C compilers have only a single name space for structures, so every member
of every structure should have a unique name (or at least the names must be
unique if they reference different data types).  The .val of the keyword
structure conflicted with the .val of the file attribute structure, zattr.
Similarly, changed name of command stack structure "val" to "lvl", and macro
stack value "val" to "mval".  ckuu*.[ch].  Reported by APPP Scorer at Leeds
Polytechnic, UK, who was able to get C-Kermit 5A to compile and run under V7
UNIX (2.4BSD).

The CONNECT code is supposed to cancel privileges for its lower fork, and it
did so.  However, it did it in the wrong place -- outside of the new fork
instead of in it.  This prevented the uucp lockfile from being removed upon
program exit if (a) the lockfile directory was write-protected against the
user, (b) the program was setuid or setgid to the owner &/or group of the
lockfile directory, and (c) the user had given a CONNECT command.  Moved the
call to priv_can() to inside the lower fork.  Tested, works right now.
ckucon.c.

William Bader reported that C-Kermit hangs in CONNECT mode every so often,
and suggested this might be caused by the "pause()" that is executed if the
keyboard-reading code gets an error.  Since this is in the upper CONNECT
fork, there's no reason for a pause(), so now it just beeps if this happens.
ckucon.c.

Fixed the text-mode session logging yet again.  This code is really getting
hairy, full of code duplication.  But it's hard to clean up without adding a
lot of function- and/or system-call overhead.  ckucon.c.

Changed the file collision mechanism that is used to create files with version
numbers on UNIX to use version numbers compatible with GNU EMACS, i.e.
<name>.~<n>~, where <n> is a number from 1 to 9999 (previously it was simply
<name>~<n>).  This allows EMACS to purge old versions, as well as EMACS-
oriented-version-purging shell scripts to work on Kermit backup files.
Function znewn(), ckufio.c.

I also considered adding a "version retention count" mechanism (automatically
delete oldest version when creating a new one) and a PURGE <name> <n> command,
but decided against it because of (a) creeping featurism, (b) space
considerations, and (c) unexpected behavior when FILE COLLISION is not set to
BACKUP.

Added support for old old DNIX/Luxor-ABC versions to makefile & ckufio.c,
from Bo Kullmar.

Added explicit SHELL=/bin/sh to makefile because some of its line
continuations confused csh.  Reported by Sergey Kartashoff, Institute-with-
Long-Name, Moscow, USSR.  Several fixes to makefile & cku[ft]io.c for
Interactive Sys V R3, also from Sergey.

Ever since C-Kermit was first written, its ttpkt() function (the one that puts
the communication device in packet mode) has always turned on the System V
ISIG flag (whereas the ttvt() function always turned it off), meaning the tty
driver should check for interrupt characters.  That's bad because a stray
noise character of ^Z or ^\ during file transfer could suspend or kill the
process.  On the RS/6000, NUL characters also killed the process for some
reason (reportedly a busted TTY driver).  I have no idea why ISIG was left on
in ttpkt, but in response to complaints that remote-mode file transfer did not
work on the RS/6000, I tried turning it off.  Tested on an RS/6000 in both
remote and local modes, and it seems to work fine.  Ditto for the SUN-4,
compiled in the System V environment.  You can, of course, still interrupt a
remote-mode Kermit while it's in packet mode by typing Ctrl-C twice in a row
-- this is not done using interrupts; rather ttpkt() looks for it explicitly.
This change needs thorough testing on all System V UNIX systems.  (Sent a
message to ckermit list asking about this, all responses so far have been
positive.)  ckutio.c.

Added translation for IBM code pages 437 and 850, same procedure as outlined
for NeXT character set in edit 164.  These code pages are used by Unix systems
running on IBM PCs, RT PCs, and RS/6000s.  Select them with SET { FILE,
TERMINAL } CHARACTER-SET { CP437, CP850 }.  ckuxla.[ch].

Added translation for Apple Quickdraw character set, used by Apple A/UX Unix
running on Macintosh computers.  SET { FILE, TERMINAL } CHARACTER-SET
APPLE-QUICKDRAW.  These tables taken from Paul Placeway's ckmxla.c, which in
turn were adapted by Paul from tables developed by Andre' Pirard at the
Universite' de Lie'ge in Belgium.  ckuxla.[ch].

Updated ckasys.doc to show procedure for adding a new file character set.

Fixed TRANSLATE command not to core dump when translating from an 8-bit
international character set to ASCII when SET LANGUAGE is adding characters
(e.g. German a-umlaut => ae).

Added SET TERMINAL CHARACTER-SET TRANSPARENT, to be like MS-DOS Kermit, and to
make sense (it's silly to tell users to SET TERM CHAR <same> <same> to do
this).  The cost was adding a copy of the file character-set table, plus one
entry, in ckuxla.c.  ckuxla.[ch], ckuus3.c.

A SunLink X.25 user reported that SHOW PAD crashed at the end of the
parameter list.  I attempted to fix this, and also changed the code to
display the X.3 parameter number that goes with each keyword.  ckuus4.c.

Added a fix for a bad bug in fgen() (the wildcard file list builder), which
might also be present in the VMS and other versions, which just copied the
same code: the loop that frees the malloc'd memory segments wasn't really
freeing them or (worse) was freeing something else.  Thanks to Steve Walton
for this one.  ckufio.c.

Charlie Epstein complained that he could not "send *" from a directory that
had lots of files in it.  There are two factors governing how many files can
match a wildcard: (1) the size of the "char *mtchs[]" array, determined by
the symbol MAXWLD (normally 1000), and (2) the size of the string space for
holding the names.  Previously, the latter was in a static array in ckufio.c,
allocated (for most systems) at 2000 characters.  I changed this to dynamic
allocation and 10,000 characters.  This should allow sending of 1000 files
with an average name length of 10.  This code is all within #ifdef DYNAMIC
brackets.  ckufio.c: near the top, and in function fgen().

Changed server's handling of REMOTE PRINT command to feed the file to be
printed to lp[r] as standard input, rather than giving its name to lp[r]
on the command line.  This allows the file to be printed even when lp[r]
doesn't have access to it (because, for example, it is running setuid to lp
and lp doesn't have read access to the file is).  Suggested by Bo Kullmar.
zprint() in ckufio.c.

Removed obsolete keywords from SET keyword list to save a little space.
These are the ones that were moved to the SET { SEND, RECEIVE } section
years ago.  ckuusr.c.

Added -DNOXMIT compile-time option to omit the TRANSMIT command.  Saves a
little space (not measurable on the SUN-4, which saves executable program
images in 8K increments).  ckuus[r2345].c.

Added -DNOFRILLS to get rid of BUG, CLEAR, DELETE, ERROR, MAIL, REMOTE PRINT,
REMOTE TYPE, REMOTE WHO, RENAME, TEST, TYPE, WHO, and WRITE commands, along
with invisible aliases like MV, RM, etc.  This one also has no measurable
effect on Sun-4.  ckuus[r2345].c.

Added -DNOSPL compile-time option to omit script programming language: macros,
variables, functions, INPUT/OUTPUT/CLEAR, IF, GOTO, etc etc etc.  Saves less
space than everybody hoped it would -- only about 66K on the Sun-4.  Seems to
work ok, but was not tested exhaustively.  ckucmd.c, ckuus[r2345x].c,
ckcpro.w, ckuins.doc.

Built a minimal interactive C-Kermit 5A on the Sun-4.  Dynamically allocated
packet buffers, no network support, no script programming, no built-in help,
no dial, no transmit, no debugging, no character sets, etc etc, but still with
the new file transfer protocol stuff: sliding windows, long packets, file
attributes.  Result is 172K (down from 393K for a fully configured version on
the same computer).  I hope this is smaller on an 80x86 architecture machine;
it should be, because RISC architecture executables tend to be quite large.
If I build the same program with no interactive command parser at all, the
result is 114K on the same machine.

Corrected a problem with MSEND, or rather the lack of it: if you build
C-Kermit with -DNOMSEND, you couldn't GET files from it when it was in server
mode.  Fixed in ckcpro.w.

Added display of the compile-time options to SHOW VERSIONS (which, of course,
only works if you you haven't compiled the program with -DNOICP).  We need
this now that there are so many -DNOxxxx compile-time options.  Also includes
most of the C preprocessor predefined variables that C-Kermit might encounter.
ckuus5.c.

Chet Creider <creider@csd.uwo.ca> sent in a version of ckutio.c that had Mark
Williams Co Coherent OS support added by Simon Hania in the Netherlands, from
version 4E of C-Kermit, plus a fix from Chet himself for sending BREAK during
connect mode.  I moved the changes into the current ckutio.c.  Later, ditto
for ckufio.c.  Also, made some changes to the makefile suggested by Bo Kullmar
in Sweden, after he tested "make coherent" on a PC at ABC-Klubben.

Changed COHERENT makefile entry to use -DNOSCP to see if a minimally
configured interactive version can be built.  Also added suggestion about
trying -DNOSCP to MINIX entry.  makefile (ckuker.mak).

Fixed RS/6000 makefile entry to spell "-DDYNAMIC" right.

The symbol UXIII was getting on my nerves, so I changed it (everywhere)
to ATTSV.  Sorry folks, I know what it does to the diffs...

Worked on POSIX makefile entry a little, added POSIX entry to ckuver.h.
However, I don't have a current POSIX specification yet (it's on order), and
cannot complete this work until I do.  SUNOS 4.1 has a lot of _POSIX_SOURCE
junk in its header files, but they seem to be wrong.  For example, I can't
"make posix" on the SUN because <termios.h> refuses to define CBAUD, IUCLC,
IXANY, and TCFLUSH (these symbols in termios.h are defined only within #ifndef
_POSIX_SOURCE..#endif, even though they are listed in my 1986 IEEE 1003.1
POSIX draft).  Anybody out there have a truly POSIX compliant system I can
work with?

Defined a _PROTOTYPE() macro for forward declarations of functions, for use
with ANSI C.  It makes an ANSI-style prototype if __STDC__ is defined (as it
must be by ANSI compilers), otherwise it makes an old-style forward
declaration with no parameters.  Suggested by Bert Laverman at RUG in the
Netherlands, but done in a slightly different way (thanks to Howie Kaye at
Columbia for help with this).  ckcdeb.h.

To make malloc debugging a little easier, I moved the forward declaration of
malloc() into ckcdeb.h, using the new _PROTOTYPE() macro.  Now it is no longer
necessary to change the malloc declarations in many modules.

Added ANSI prototyping for the functions in ckcfn*.c, by declaring prototypes
with the _PROTOTYPE macro.  Added these prototypes to ckcker.h.
Unfortunately, this provokes millions of warnings from GNU cc (gcc).  Even
though the whole idea of prototyping is to have the compiler perform type
conversions on function arguments, it feels compelled to issue an "argument
passing between incompatible pointer types" message every time it converts
(say) a (char *) to an (unsigned char *).  There are hundreds of these in
C-Kermit.  Has ANYONE EVER had a use for "signed character"???  Grrr...  Added
-w to "next" makefile entry, which uses gcc.  Other gcc entries will have to
do the same, but this also suppresses useful messages.

The function definitions themselves are left in the old style, because there's
no way (that I can think of) to construct a portable macro for declaring
functions both the old way and the new way.  Unfortunately (from K&R 2nd Ed):
"If the function declaration is old-style, then the type of each parameter in
the prototype visible at the call must agree with the corresponding parameter
in the definition, after the definition parameter's type has undergone
argument promotion."  Without new-style function declarations, char arguments
are promoted to int, and then the compiler chokes when it sees the type
mismatch.  So #ifdef __STDC__..#else..#endif declarations have been added for
a few functions, like spack() and logpkt().  Functions without char arguments
seem to be ok.

Same deal for all functions declared in ck*[ft]io.c and used in other modules.
Only one in ckufio.c (zchout) needed the #ifdef __STDC__ treatment, but
several in ckutio.c (ttoc, ttinl, concb, conbin) needed this.  Owners of
ck*[ft]io.c will have to add the __STDC__ baloney to the declarations of these
functions.

Had to move the material from ckcfil.h into ckcker.h to make the prototypes
work right.  Got rid of all references to ckcfil.h, and replaced ckcfil.h by
a file that contains only comments.

This ANSI- and POSIX-ification has been a useful exercise.  Many potential
problems were uncovered -- variables possibly used before set, variables
possibly clobbered by longjmp, etc etc.

Compiled successfully on SUN/BSD (not ANSI), NeXT (ANSI), VAX/VMS (not ANSI),
DECstation (not ANSI), RS/6000 AIX 3.0 (very weird -- ANSI, but does not
define __STDC__ so the prototyping doesn't kick in).  Also tried "make posix"
on the RS/6000, but it crashed the compiler.

Fixed ttoc() to call setjmp before the read() rather than after it, oops!
Pointed out by Benn Schreiber at DEC.  ckutio.c.

Added Xoff-clearing code to ttoc() if it times out.  ckutio.c.

SET FILE COLLISION DISCARD didn't work.  It refused the file all right, but
it deleted the existing file too.  Oops!  Reported by Peter Jones.  Fixed in
reof(), ckcfns.c.

ASKQ worked correctly in interactive mode, not echoing what the user types.
On Unix systems, however, it did echo when issued from a C-Kermit application
file.  And reportedly on VMS systems, it echoed even from within a TAKE file.
Fixed by adding an explicit call to concb() in the ASKQ code.  ckuusr.c.

Moved big hunks of code out of the humongous switch() statement in docmnd().
This might make some compilers happy that previously had complained or failed
on this module.  ckuusr.c.

Added Telebit modem support.  Should work for Trailblazer, T1000, T1600, and
T2500.  "set modem telebit" means to let it configure itself automatically to
the answering modem (PEP, Bell 103, Bell 212, CCITT V.22).  "pep-telebit"
means to force PEP mode, and allows it to be used with or without the "Kermit
spoof" ("set dial kermit-spoof { on, off }").  "set modem v32-telebit" means
to dial in V.32 mode but allow fallback to 2400/1200 (only works with T1600
and T2500).  Much code and info from Warren Tucker and Larry Jacobs.  Tested
on my early-model Trailblazer (1985 Model 962 = RA12E, Firmware
Q2.22/PROT/MNP-026), which tends to go into a tailspin when it receives those
long register-setting commands, so I added code to feed it gently and to try
each command several times before giving up.  Needs testing on newer Telebits
(T1000, T1600, T2500).  So far there's no provision for turning on MNP.  The
DIAL module needs reorganization to allow users to select modem features
individually: MNP, compression, etc.  ckudia.c.

Added a new routine getok(n) to the dial module.  Reads response to
initialization commands given to Hayeslike modems (including Telebits), looks
for <CR>0 and OK<CRLF> (returns 1); <CR>4 or ERROR<CRLF> (returns -1).  Has
own built-in timer, returns 0 if none of these responses seen within n
seconds.  This makes the new Telebit code work nicely if (for example) you
"set modem v32-telebit" and then try to dial on a Trailblazer (which does not
support this).  The ERROR (or 4) response to the register-setting command is
now picked up and the dial command fails immediately.  Also added check for
'5' (= CONNECT 1200) return from dialing command in the HAYESNV section.
ckudia.c.

Changed TAKE ERROR default action from QUIT to PROCEED.

Fixed the command parser to always go back into cbreak (single-character
wakeup) mode when it returns to top (interactive) level.  popclvl() in
ckuus5.c.

Discovered that GOTO was case-sensitive about targets and labels.  Fixed it to
disregard case by calling xxstrcmp() (caseless string compare) instead of
strncmp().  ckuusr.c.  Changed xxstrcmp() to have a length argument like
strncmp() does.  ckuus4.c.  Changed all other xxstrcmp() calls to include a
length argument.  ckuusr.c.

Added -DNETCONN to sxae50 makefile entry at Dezawa-san's request.

The fact that the C-Kermit command parser does not allow typeahead is
annoying.  I remember having to add code to flush command typeahead years ago,
but can't remember why, and now I can't find where it happens.  cmini() and
cmres() just fiddle with the command buffer.  When there are no characters to
read in the buffer, gtword() calls regular old C getchar().  The command
parsing loop calls concb() each time thru, which calls setbuf to make stdin
unbuffered, but removing the call to setbuf doesn't make any difference.

Added SET ATTRIBUTES ALL { ON, OFF }, which turns all individual attributes on
or off, as compared with SET ATTRIBUTES { ON, OFF }, which turns the attribute
mechanism on and off.  Thanks to Brian Hamilton Kelly at Cranfield U (?) in
the UK for pointing out this omission.  ckuus3.c.

Made some attempt to parameterize the data type used for process IDs.
Defined symbol PID_T to be int in ckcdeb.h.  If anybody has a computer that
uses something besides ints for pids, try including "-DPID_T=pid_t" on the cc
command line.  ckcdeb.h, ckufio.c, ckutio.c, ckucon.c.

Same deal for user and group IDs: UID_T and GID_T are now used.  ckcdeb.h,
ckutio.c.  Thanks to Bob Larson and Karl Berry for pointing out the problem.

Made sure that telnet-init'ed flag was reset any time that ttclos() or
tthan() was called in ckucon.c.

Fixed TRANSMIT command in text mode to use its prompt character and echo
the echoes.  I broke this a couple edits ago.  Thanks to Peter Mauzey for
pointing out the problem.  ckuusr.c.

Added entries for AT&T System V Release 4 to makefile, ckcdeb.h, and ckuver.h.
They don't really do anything yet except make a new version banner.
Reportedly, C-Kermit 5A(165) builds cleanly under SVR4, but: (a) the UUCP
lockfile name has changed, (b) modem controls don't work, (c) REMOTE DIR
doesn't work, etc.  Based on report from  Andrew Herbert at Monash University
in Australia.

Added SET DIAL SPEED-CHANGING { ON, OFF }.  Removed the [{ CHANGES-SPEED,
MATCHES-SPEED }] optional trailing field from the SET MODEM command.
Reformatted the DIAL-related SHOW information accordingly.  ckuus3.c,
ckuus4.c.

Added SHOW DIAL command.  Added line & modem info to SHOW MODEM.
ckuusr.[ch], ckuus4.c.

Added support for RTS/CTS and DTR/CD flow control.  Well, sort of.  They are
now included as SET FLOW options, and show up in SHO COMM.  But they only take
effect on System V R3 and later, and then only if there is a <termiox.h>
include file that defines the appropriate symbols and structures.
Unfortunately, there is no mechanism to notify users whether their SET FLOW
commands took effect or not.  They have to be documented as "request Kermit to
ask the underlying operating system to select the specified kind of flow
control the next time you give a command that puts Kermit into packet mode,
with no guarantee that it will truly take effect."  Btw, I looked on the
RS/6000, whose AIX is supposed to be based on Sys V R3, POSIX, etc, and could
find no sign of <termiox.h>.  However, it does have a <tty.h> and an <mpqp.h>
that contain things about flow control.  I have no idea how to use them.
ckuus3.c, ckuus4.c, ckutio.c.

Added warning about -DNOTERMIX to all Sys V R3 or later based makefile entries.

SET FLOW RTS/CTS is hooked into the Telebit modem support.  If you tell Kermit
to use RTS/CTS, it'll tell the Telebit by setting its S58 register to 2.

Tried TAKEing MSKERMIT.INI from "Using MS-DOS Kermit", and then using
HAYES.SCR to "do dial <number>" from C-Kermit with a Hayes modem.  Very few
alterations required -- MS-DOS Kermit 3.10 and C-Kermit 5A can execute
practically identical script programs.

Tested WAIT xx CD on the NeXT with real modem -- works like a champ.

Tested sliding windows using non-speed matching modem.  When sending a file,
the Send light stays on solid.  When receiving, the Receive light stays on
solid (NeXT vs PC).

An early version of edit 166 was tested on NCR Tower 32/700 with "make
tower32".  Compiled fine, DIAL & CONNECT fine, transfer of short text files
OK, but problems were reported (later, when I wasn't there) transferring
binary files.
 
An early version of edit 166 was tested successfully on SCO Xenix/386 2.3.2
with Racal/Interlan TCP/IP.

The final version of edit 166 was tested successfully on MicroVAX-II Ultrix
2.0, SUN-4/490 with SUNOS 4.1.1, SUN-4/280 SUNOS 4.1 (both BSD and System V R3
versions), SUN SparcStation IPC, VAX-11/750 with 4.3BSD, Encore Multimax with
UMAX 4.3, NeXTstation with NeXTstep 2.0, IBM RS/6000 with AIX 3.1, DECstation
5800 with Ultrix 4.0, and MicroVAX-II with VMS 5.3 and C 3.0.

The various compile-time feature selection options were also tested at the
last minute: NOSPL, NODIAL, NOCSETS, and various combinations of these.

------------------------------

5A(165) Sun Jan 20 02:00:11 1991

VMS changes from Terry Kennedy.  His notes from CKVKER.UPD:

36. Add support for SET FILE RECORD-LENGTH <n>. This applies only to received
    files (correct size is detected automatically when sending) and only for
    files of TYPE BINARY. Any recordsize may be selected; however it is wise
    to a) use one smaller than the file size, and b) one that RMS can handle
    without crashing (i.e. <= 32768, regardless of what the VMS manual says).
    (ckuus2, ckvfio, ckcdeb)

37. Do lots of testing with asynchronous I/O, deferred writes, read-ahead,
    pre-allocation of the file, etc. No item or combination of items improved
    operation by more than .5%, which is in the noise anyway. One useful side
    effect: all modules except ckuusr are now compiled with optimization.
    (ckvker.com)

38. Fix a problem reported by Joe Doupnik <jrd@usu.bitnet> where single-char-
    acter lines at the end of a file would cause access violations in the
    memmove() call in the zoutdump() routine. (ckvfio)

39. Add more detailed debug loggin when creating an output file. The file mode
    being used (TEXT, BINARY, IMAGE or LABELED) is logged. If an unknown mode
    is presented, the mode number is logged as well. This should help locate
    future problems with unexpected file modes. (ckvfio)

40. Completely replace the zstime() function. When a remote Kermit supplies a
    valid date/time in an attribute packet, the created file will have the
    specified time as the VMS file creation time. Also, SET FILE COLLISION UP-
    DATE now functions, although it is perhaps less useful on VMS, as VMS has
    file version numbers. (ckvfio)

41. Add support for the zchkspa() function. Files which are too large will now
    be rejected. Lack of rejection does NOT imply a file can be received; other
    considerations such as disk quota and other users filling the disk prevent
    certainty of successful reception. (ckvfio)

42. Move the debug() call in zxpand() inside the if statement to prevent access
    violations, per fdc. (ckvfio)

43. Extensively re-work ckvfio internals to support DECnet access to files. The
    existing stat() and access() calls in zchki() were replaced with a single
    native RMS call, various tests (such as $idtoasc) now handle DECnet results
    from non-VMS operating systems where the feature isn't supported, an expli-
    cit SET FILE TYPE IMAGE forces opens in BIO mode rather than BRO, since a
    non-VMS DECnet implementation may not allow mode switches in mid-stream.
    Note that the filespec (all info to the right of the '::') may need to be
    quoted, since VMS RMS attempts to interpret fields which may be illegal on
    a VMS system (such as a non-octal digit in a PPN). Example:
      SPC11Z::[49,7]CKVFIO.C
    must be quoted as:
      SPC11Z::"[49,7]CKVFIO.C"
    Note: embedded spaces in filenames must be coded as \32, e.g.
      NODE"USER\32PASSWORD"::DEV:[DIR]NAME.EXT
    when talking to the C-Kermit command parser, or when sending filespecs 
    in a GET command to a C-Kermit server.

44. Correct a long-standing bug with the READ command. (ckvfio) (so now the
    READ command works for VMS).

Fixed an error, noticed by Terry, in the description of zstime() in ckasys.doc.

Added new symbol DFESC = default CONNECT-mode escape character.  Initialize
escape variable to this value.  It's Ctrl-] for OS/2 and NeXT (because new
NeXT keyboards don't let you type Ctrl-\), Ctrl-\ for all others.  ckcker.h,
ckcmai.c.

Added SHOW ESCAPE command, and also added escape character display to
SHOW COMMUNICATIONS.  ckuusr.h, ckuus[45].c.

Initialized suspend variable to DFSUSP.  It's 0 for MIPS (because of reports
that job control doesn't work on MIPS machines), 1 for all other UNIX systems
(but isn't actually enabled unless SIGTSTP and SIGSTOP are also defined at
compile time), 0 for all others  When it's zero, Kermit refuses to issue the
kill(0,SIGSTOP), so the suspend never happens.  ckcmai.c.

Changed variables dialtimo and dialhang to dialtmo and dialhng.  dialtimo,
in particular, was indistinguishable from dialtime() by certain linkers that
had 6- or 7-character limits on identifiers.  ckcmai.c, ckuus[34].c, ckudia.c.

Moved COHERENT/PEEKTYPE #ifdefs around so SUNOS X25 version will compile
again (G. Mussar).  ckutio.c.

Corrected a typo in SUN X25 code, x2ibuf => x25ibuf (G. Mussar).  ckucon.c.

Added -DSVR3 to sco3r2 make entry (David MacKenzie).  makefile.

Changed HDBUUCP / SCO lockfile name to be right when compiling under gcc,
which does not define M_SYS5 (David MacKenzie).  ckutio.c.

Kermit application file correction from G. Mussar.  Don't check argv[0],
because it might or might not come with a pathname.  ckcmai.c.

Fixed dotake() to use its argument rather than global line[] array.  G.
Mussar.  ckuusr.c.

Changed gattr() to call zchkspa() (check disk space) only after it had already
read all the other attributes.  This way, zchkspa() can make its decision
differently based on whether the file is text or binary (binary requires no
expansion, text sometimes does -- e.g. in VMS, each line gets a record
descriptor).  ckcfn3.c.

Fixed C-Kermit to report file refusals to user's screen when in local mode,
including the reason for the refusal (size, date, etc).  ckcfn3.c, ckuusx.c,
ckcker.h.

Fixed formatting of command-line help message.  ckuus2.c.

Changed \v(platform) variable to replace all blanks by underscores so it can
be used conveniently in string comparisons, as in:
 IF EQUAL \v(platform) NeXT_Mach_1.0 set escape 29
ckuus4.c.

Changed \v(success) to \v(status) upon being convinced by Joe Doupnik that
this was more sensible -- and also to stay compatible with MS-DOS Kermit 3.02,
which is also getting this feature.  Also, reversed the sense of this
variable: \v(status) == 0 means success, \v(status) != 0 means failure.
Allows for different failure codes.  ckuus4.c.

Corrected a minor mistake in how the C-Kermit receiver reacts to the file
type given in an incoming attribute packet (I think!) in the opena() routine,
which affected VMS only.  Also made C-Kermit/VMS refuse an incoming file whose
type attribute is TEXT if the global file type is set to LABELED.  ckcfn3.c.

Bob Larson noticed that if C-Kermit receives bad parity (or, for that matter,
random noise) while reading packets in ttinl(), that it could core dump.  The
reason is that the failure return code from parchk() was not being handled,
and worse, the global parity variable was being set to the error code.  Fixed
in ckutio.c and ckvtio.c.

Jay Rouman noticed that UNIX text-mode session log was broken -- carriage
returns were appearing in it again.  Rearranged the code in ckucon.c to
prevent this, and combined some duplicated code sections for a slight size
reduction.  ckucon.c.

In previous edit, forgot to include part of Wm Bader's changes for supporting
Interlan TCP/IP (needs <interlan/il_types.h> rather than <sys/types.h>).
ckutio.c.

Changed SET BUFFERS command to not allow user to specify anything below 80.
ckuus3.c.

Changed server's parsing of filespecs in incoming GET commands.  A few edits
back, it became ok to give the C-Kermit server more than one filespec in a GET
command.  The tricky bit was how to separate the filespecs.  Space was being
used, but space is a legal character in VMS filenames (separating the DECnet
user id and password), not to mention Mac, OS/2, and others.  So now C-Kermit
allows backslash codes in GET command filenames.  Spaces within filenames must
be quoted like "\ ", or "\32", or "\x20", etc.  Unquoted spaces separate
filespecs.  Any other numeric backslash codes that evaluate to 8 bit values
can also be used in these names.  Done by having fnparse() call xxesc()
whenever it sees a backslash.  ckuusx.c.

In preparation for Telebit modem support (which Warren Tucker is working on),
added two new commands:

  SET DIAL KERMIT-SPOOF { OFF, ON }.  OFF by default; if ON, modem is
  instructed to turn on its "Kermit spoof" (modem executes Kermit protocol
  between itself and the computer, rather than passing Kermit packets
  transparently to the other computer), if it has one.  For now, this command
  does nothing. 

  SET DIAL INIT-STRING <string>.  User can define any string at all to be sent
  to initialize the modem, overriding the DIAL command's built-in
  initialization string for each modem type.  Use this to set S-registers,
  etc.  The string can be any length allowed by the command buffer (i.e.
  nearly 1000 chars), and can contain any backslash codes (like \13 for
  carriage return).

  SET DIAL DISPLAY { OFF, ON }.  Normally OFF.  If ON, displays dialing
  dialog on your screen.  A lot of characters seem to be missing, though.

SHOW COMM displays the SET DIAL settings.  ckcmai.c, ckuusr.h, ckuus[34].c,
ckudia.c.

Changed doexit() to have 2 arguments.  First is symbolic GOOD_EXIT or BAD_EXIT
or else user-supplied code.  Second is -1 (take first arg literally) or any
other number, which is presently ignored in VMS, and is OR'd in with the first
arg in UNIX.  When the second arg is not -1, it is supposed to be a bit mask
denoting protocol operations that failed: 2=send, 4=recv.  This may still need
some revision.  ckcmai.c, ckcpro.w, ckucon.c, ckutio.c, ckuus[r5xy].c.

Fixed stptrap() to restore terminal modes properly in all cases after
C-Kermit is continued/foregrounded after being suspended from command mode,
connect mode, or the local-mode file transfer display screen.  ckuusx.c.

Added character-set translation and SO/SI support to the TRANSMIT command.
ckuus4.c.

Changed UNIX zprint() to use lpr rather than lp for Tandy 6000, based on
report from Jay Rouman.  ckufio.c.

UNIX version still halts sometimes when transferring files overs a SET HOST
telnet connection to a VAX/VMS system with CMU TCP/IP, apparently after a
"ttinl myread failure, n = -3".  Added some more debugging statements to this
part of the code.  ckutio.c.

Checked modem signals on NeXT 68040 RS-423, /dev/cua (dialout) and /dev/cufa
(dialout with RTS/CTS) thru a Telebit Trailblazer.  Works perfectly both ways.
RTS/CTS is a function of the device driver, and works transparently to the
Kermit software.

Built on a new Sun-4/490 with SunOS 4.1.1.  No problems.

Tested on a Sun-4/110 workstation with Xterm.  Found that Latin-1 characters
are supported nicely.

Updated manual, man page, etc.

------------------------------

5A(164) Wed Jan  9 16:45:11 1991

Made sure all debug and transaction logging related code is within the
appropriate #ifdefs.  ckuus[r2345x].c.

Changed '=' to '==' in two important places in xxstring().  ckuus4.c.

Changed second tower32: entry in makefile to tower32g.

(above 3 changes sent in diff form via e-mail to ckermit list Dec 1, 1990.)

Removed extraneous "-O1" from tower32g makefile entry.

Changes for VMS C-Kermit from Terry Kennedy, St Peters College.
From CKVKER.UPD:

34. Corrected the performance hit when an ASCII transfer into CK exceeded 32Kb.
    New ASCII zoutdump() code by Ben Cohen, <ben@spcvxa.spc.edu>.  ckvfio.c.

35. Corrected the problem where 2 nulls would be inserted into received binary
    files every 32Kb when DYNAMIC is defined. The z<in | out>buffers must be
    a multiple of 512 bytes. DYNAMIC defined them as 32766, the fix changes
    them to 32768.  ckcker.h.

Changed declaration of time() function in ckutio.c to use time_t rather than
long because of conflict with sys/time.h in Ultrix 4.1.  Since time_t is used
unconditionally elsewhere in the same module, this should cause no problems.
ckutio.c.

Changed "make du4" for Ultrix to include -Olimit 1619 to suppress complaints
and enable optimization of ckuusr.c, in which the docmd() function has a very
long switch() statement.  Jack Bryans.

Added a line for IBM RT PC with ACIS 4.3 to makefile, after successful testing
using "make bsd" was reported by David MacKenzie.

Removed a spurious "extern char cmdstr[];" from ckuusx.c.

Changed screen() function not to output anything if Kermit is in server
mode, because screen() is called from errpkt().  Noticed by Joe Doupnik in
his packet logs.  ckuusx.c.

Changed all occurrences of maxsize in getpkt() to bufmax, and removed the
declaration of maxsize.  Not needed, was never defined, and it's a miracle
this code worked at all!  Also, increased the size of the leftover buffer in
the same function from 6 to 7 bytes, to allow for a run of 8-bit-quoted
control characters that turned out to be only two and was therefore deposited
as two 3-byte prefixed sequences.  This was an obscure boundary condition that
has been in the code forever, and could have been tickled any time 8-bit data
was being sent using 8th-bit prefixing.  The result was that the terminating
null of the 6-byte leftover sequence would overwrite some other variable, with
unpredictable symptoms.  Thanks to Steve Walton for spotting both of these.
ckcfns.c.

Changed dopar() to put entire argument of (CHAR) cast in parens.  Thanks to
Larry Rosenman.  ckcfn2.c.

Made a safe copy of the command file name in case XXTAK in docmd(), so the
call the cmcfm() could not destroy it.  Thanks to Mike Hickey.  ckuusr.c.

Fixed a bug in the completion of filenames beginning with tilde when user
types ESC or TAB, reported by many.  Thanks to Mike Hickey for the fix to
cmifi(), case 2 (just uncomment the call to tilde_expand()...  The filename
was being found correctly, but the echoing was wrong.)  ckucmd.c.

Added a makefile entry for the Tektronix 4336 with the Utek OS, from Tom Kloos
at Sequent Computer Systems, plus special Utek support within #ifdef UTEK
conditionals, most of it for a wierd kind of hardware flow control -- DTR/CTS.
ckutio.c, ckufio.c, ckuus2.c, ckuus3.c, ckuus4.c, ckuver.h.

Added symbols for flow control to ckcdeb.h and replaced numeric values in
various modules with symbolic references.  In preparation for adding more
widespread support for hardware flow control, e.g. with high-speed modems.

Made a change to the CONNECT code to put console back in binary mode after
returning from suspend (^\Z).  Thanks to Tom Kloos.  ckucon.c.

Added a second make entry for Apple Macintosh A/UX, "make auxufs", which is
just like "make aux" except it uses <dirent.h>, which is apparently required
on ufs file systems (reported by Jon Hamilton at Iowa State U).  It is not
known whether this same entry works with svfs systems, or if the "make aux"
version should be used.  If you're using A/UX and you can't "send *" (i.e.
wildcards are not expanded correctly), use the new make.  Maybe "make auxufs"
applies to all?  makefile.

Added support for Racal Interlan TCP/IP for SCO Xenix 2.3.x, from William
Bader.  makefile, ckcmai.c, ckucon.c, ckutio.c.

Added support for Interactive 386/ix 2.x both with and without TCP/IP,
from Mike Hickey <mike@iti.com>.  makefile, ckucon.c.

Added improved support for Ventel modem dialing from Tony Querubin at the U of
Hawaii.  ckudia.c.

Changed declaration of sstate in ckcmai.c to be CHAR rather than char to agree
with declarations in other modules (William Bader).

Fixed dialing code for Microcom modem not to confuse NO CONNECT and CONNECT
(William Bader).  ckudia.c.

Changed all calls to ttclos() to include an argument: ttclos(0).  The argument
is required because ttclos() is sometimes used as a signal handler, and signal
handlers must have an argument.  ckudia.c, ckucon.c, ckutio.c, ckuusx.c,
ckuusy.c.

Sergey V. Kartashoff of the Institute of Precise Mechanics and Computer
Equipment in Moscow reported that if you put "set line /dev/tty" in your
.kermrc file, then after executing a "set line" command for any other device,
the command parser loses CBREAK mode.  The problem was that ttclos() was
calling ttres() even when the device was the controlling tty.  Moved the calls
to ttres() and tthang() to within "if (xlocal) { ... }" section.  ckutio.c.

Mike Hickey reported that tthang() could fail if the communication line was
Xoff'd.  Two ioctl's added to tthang() to unblock a blocked port - TCXONC
and TIOCSTART - whose execution is #ifdef'd on the existence of those
symbols.  ckutio.c.

Added some dialing code to catch DF100-specific modem single-letter responses,
from Tony Querubin, U of Hawaii.  ckudia.c.

Gary Bilkus suggested that Kermit make the tty file descriptor available to
other programs as an environment variable to allow other Unix communication
programs to take advantage of Kermit's script and login facilities in a
painless way.  This would have required system-dependent code for setting and
exporting environment variables on different systems with different shells,
and doing it in many places -- a can o' worms.  Instead, I added a new
variable \v(ttyfd) which, for UNIX only, contains the current tty file
descriptor.  So now, with only moderate pain, you can do things like:

  take <login-script-file>
  ! KERMIT_FD=\v(ttyfd)
  run <program-name> <args>

or whatever syntax your system, shell, and communication program might use.

Added new built-in variable, \v(program) ("C-Kermit"), for portability (MS-DOS
Kermit 3.02 will have this too, but its value there will be "MS-DOS_Kermit").
ckuus4.c, etc.

Cleaned up a few help messages in ckuus2.c, and made them all static -- a
small load off the linker's mind.

Discovered that the NeXT workstation has a bizarre character set -- not ISO,
not Apple, not IBM, not DEC...  Looked it up in their manuals (not just the
user manuals, but also the Mach 1.0 technical manuals), but they don't list,
describe, or even name it anywhere.  Figured it out from dumping all 8-bit
characters to the screen and added a new file character set to C-Kermit for
it:

 . Added definition for FC_NEXT and increased MAXFCSETS to 16 (19). ckuxla.h.
 . Added NeXT into the fcsinfo array.  ckuxla.c.
 . Added "next" entry to file character set table, fcstab.  ckuxla.c.
 . Added a translation table from Latin-1 to NeXT: yl1ne[].  ckuxla.c.
 . Added a translation table from NeXT to Latin-1: ynel1[].  ckuxla.c.
 . Added translation functions xneas(), xnel1(), and xl1ne().  ckuxla.c.
 . Added xlation function pointers to xls and xlr tables.  ckuxla.c.

After some trouble in which it seemed these changes didn't work, noticed that
the makefile didn't have enough dependencies on the translation header files;
added those that were needed.

To use it, SET FILE CHARACTER-SET NEXT in combination with your favorite
TRANSFER CHARACTER-SET.  But you'll only be able to see the results on the
NeXT console.  Tested with the entire Latin-1 alphabet in both directions --
works fine.  Imported the result into WriteNow and looked at it in Courier,
Helvetica, Ohlfs, and Times fonts, and all characters were correct in each
font.  Obviously this won't work for Symbol.

All this makes me wonder about Xenix -- will we have to add IBM code pages
to our list of file character sets???

Tested Cyrillic translations (all three) against MS-DOS Kermit 3.02 of 5 Jan
91.  The translation mechanisms themselves (sending in both directions,
automatic switching based on attribute character set announcer, etc) seem to
work just fine.  A few small character translation problems, but I can't tell
easily whether they are in C-Kermit, MS-DOS Kermit, or Dimitri's "CP866"
Cyrillic PC code page.

Improved the TRANSLATE command.  Formerly it was "TRANSLATE <file1> <file2>"
and it always translated from the current transfer character set to the
current file character set, which was unreasonably limiting.  Now it's:

  TRANSLATE <file1> <charset1> <charset2> [ <file2> ]

which you can read as "translate file-1 from character-set-1 into
character-set 2 and put the results in file-2".  The two character sets are
C-Kermit file character sets.  It works by translating file1's charset1 into
Latin-1 (or, if "set language russian", into Latin-Cyrillic) and then the
Latin-1 or -Cyrillic into charset2, putting the result in file2.  If file2 was
not specified, the result is shown on the screen.  Thus TRANSLATE now
simulates a file transfer between two C-Kermits.  Any pair of character sets
can be specified.  ckuusr.c, ckuus2.c, ckuus4.c.

Made XLATE an invisible command synonym for TRANSLATE, and XMIT for TRANSMIT,
to allow for shorter abbreviations (XL and XM rather than TRANSL and TRANSM)
when typing commands.  Similarly, you can now use SET XFER CHARACTER-SET (SET
XF C) as a synonym for SET TRANSFER CHARACTER-SET and SET XMIT (SET XM) for
SET TRANSMIT.

Having a NeXT on one's desk makes one realize the need to be able to translate
character sets during terminal emulation too.  Hence another new command:

  SET TERMINAL CHARACTER-SET <remote-set> [ <local-set> ]

This tells C-Kermit's CONNECT command to translate the characters you type
from the local-set to the remote-set before transmitting them to the remote
host, and to translate characters that arrive from the host from the
remote-set to the local-set.  The local-set and remote-set can both be any of
C-Kermit's file character sets.  The local-set defaults to the current file
character-set.  Translation takes place via the Latin-1 intermediary except
when LANGUAGE is set to RUSSIAN, in which case Latin-Cyrillic is used in the
intermediate step.  (Works just like the TRANSLATE command.)  If remote-set is
the same as local-set, no translation occurs, which is the default.  This
command has no effect on VMS -- support for it must be added to CKVCON.C (it's
simple, just copy from ckucon.c).

The new command and supporting CONNECT code work fine, but explaining how to
use them is another matter.  Terminal emulation works when C-Kermit is in
local mode: there is one connection from local C-Kermit to the remote host
(thru the communication port or network) and another from the local C-Kermit
to the user's keyboard and screen.  These connections are independent of each
other, and either one can be either 7 bits or 8 bits wide.  C-Kermit assumes
both are 7 bits.  If you are using an 8-bit character set between C-Kermit and
your keyboard and screen, you have to SET COMMAND BYTESIZE 8.  If you are
using an 8-bit character set between your communication port and the remote
host, you must SET TERMINAL BYTESIZE 8.  (These command names may be a little
misleading.)

Another word of caution: if you tell C-Kermit that your remote character set
is a 7-bit national replacement character-set (NRC), this will cause
characters such as brackets to be translated into accented characters, which
in turn will prevent VT100 escape sequences from working.  For example, if you:

  SET TERMINAL CHARACTER-SET GERMAN NEXT

then the VT-100 control sequence introducer ESC [ is translated to ESC
A-umlaut, and the NeXT's VT-100 emulator simply prints the remaining
characters of the escape sequence.

And one more caveat: The special accented-character-to-digraph translations
(such as German umlaut-u translated to ue) that are enabled during file
transfer by the SET LANGUAGE command do not occur during terminal emulation.
Only one-to-one translations are done.  This is (a) to prevent terminal screen
displays from becoming misaligned and (b) because the character-stuffing
tricks used in the translation functions are set up to work with disk i/o
buffers, not the communications device or the keyboard.

Added a SHOW TERMINAL command to show all the current terminal settings, plus
the command bytesize.

The undocumented (and invisible) command SHOW KEY lets you see what code
C-Kermit gets when you press a key.  The result depends on the COMMAND
BYTESIZE setting.  There is, as yet, no SET KEY command.

Added the SET TERMINAL SHIFT-IN/OUT { ON, OFF }.  OFF is the default, meaning
everything continues to work as before.  ON means that if you type an 8-bit
character during terminal emulation (which is only possible if you have SET
COMMAND BYTESIZE 8), it will be surrounded by Shift-In and Shift-Out
characters (Ctrl-N and Ctrl-O) and reduced to 7 bits before transmission.  The
shift state is remembered, so a run of 8-bit characters is included within a
single shift-out/shift-in sequence.  For received characters, C-Kermit sets
the 8th bit of received characters based on the current incoming Shift Out/In
state, which is maintained separately.  For now, Shift-In/Shift-Out is done
only on the Kermit-to-Remote part of the connection, not on the
Kermit-to-terminal part.  ckucon.c, ckuusr.h, ckuus3.c, ckuus5.c.

Added SET DIAL TIMEOUT <secs> command.  It seems that new fancy modems can
take a very long time to negotiate a common protocol -- MNP level,
compression, V.{32,42}[bis], PEP, etc etc, sometimes longer than the timeout
calculated automatically by the dial code.  Also, the dial code doesn't allow
for the extra time it may take to complete an international call.  The new
command lets the user override the built-in calculation.  NOTE: it only
applies to the interval that begins when the dial-string is sent to the modem.
There are also several other fixed timeouts of about 10 seconds each in which
the code waits for a response to its wakeup signal to the modem, etc.  So the
total timeout is usually 10 seconds plus the SET DIAL TIMEOUT value.  Added
dial hangup and timeout settings to SHOW COMM display.  ckuus2.c, ckuus3.c,
ckuus4.c, ckcmai.c, ckudia.c.

Robert Weiner noticed that remote-mode C-Kermit packets were Xoff-able, even
after SET FLOW NONE.  ttpkt() did not bother to put the tty in raw mode in
this case (after the addition of the new LPASS8 code in edit 155).  This is
fixed.  But now it seems that after giving the SET FLOW NONE command (which
works), subsequent SET FLOW XON/XOFF commands do not work -- the right code is
executed, but flow control remains nonfunctional.  However, if you "set line"
(which closes and reopens the tty), you can SET FLOW control back to XON/XOFF.
So (gag!) I put code into ttpkt to do just that, but only in this particular
case (BSD with LPASS8 defined, setting flow to Xon/Xoff on controlling
terminal after it had been set to none).  Works ok.  ckutio.c.

Added new command SET SUSPEND { OFF, ON }.  On some Unix systems, most notably
the MIPS, suspending Kermit causes it (and the terminal it was running on) to
hang forever for unknown reasons.  This, at least, can prevent that from
happening.  A better solution, of course, would be to find out why Kermit
can't be suspended on the MIPS.  A MIPS wizard is required.  The default is ON
for all UNIX systems except MIPS, and OFF for everything else (MIPS, VMS,
etc).  ckcmai.c, ckuusr.h, ckuusr.c, ckuus3.c, ckuus5.c, ckutio.c.

Rec'd new Mac Kermit ckm*.* source files from Paul Placeway.  He has done a
lot of work on them, but they don't quite result in a working program yet.
They are designed to be built with MPW C 3.0.  No changes to the C-Kermit
5A(163) ckc*.[ch] modules were required to get the ckm* files to link with
them successfully.

Updated copyright notices to 1991.  Another year, sigh...  All modules.

Updated documentation to mention new features (and the new year).

------------------------------

5A(163) Fri Nov 30 16:52:56 1990

NEW FEATURES

Added \v(host) variable for UNIX and VMS.  For AT&T UNIX it calls uname().  I
sincerely hope this exists for pre-SVR2 implementations, since it is selected
by #ifdef UXIII.  For 4.2 BSD and later it uses gethostname().  For VAX/VMS,
it uses getenv("SYS$NODE"), with the double colon (if any) stripped from the
end.  For all others, and if any of these fail, it uses getenv("HOST").
ckuus4.c.

If dialing is interrupted by Ctrl-C and the modem type is Hayes, send CR to
modem to interrupt dialing.  ckudia.c.

Changed Hayes support in ckudia.c to recognize CONNECT followed by no number
to mean 300 bps, and to change speed to 300 if MATCHES-SPEED not set.  Also
fixed a bug in which string comparison for CONNECT could possibly start at the
wrong place.  John Dunlap.

NEW SYSTEMS AND OTHER MAKEFILE CHANGES

Added support for four NCR Tower 32 operating systems, from Robert Andersson,
ra@intsys.no (International Systems A/S, PO Boks 3356, 0405 Oslo 4, Norway).

Added new makefile entries for Minix: "make minixnew" (uses new beta-test C
compiler and linker, based on info from Nate Williams,
osynw@umbriel.oscs.montana.edu), and "make minix386" (for Minix/386 only,
based on info from John Nall, nall@sun8.scri.fsu.edu).

Added new makefile entry for PFU Compact A Series UNIX System V R3, SX/A TISP
V10/L50, from S. Dezawa (kddlab!oda.fujifilm.co.jp!dezawa@uunet.uu.net),
including some minor changes to ckutio.c and ckucon.c within #ifdef sxaE50.

Made first attempt at correcting Coherent makefile entry (now uses V7 as basis
rather than BSD4), based on tests by Manfred Prange (fred@cetus.mi.org).

Added -DDYNAMIC to various DIAB and HP makefile entries after users reported
successful testing.  makefile.

Added suggestions about using "makeL" to SCO Xenix/286 makefile entry (sco286)
and fix sco286hdb entry to agree with it.  makefile.

COMMAND PARSER BUG FIXES

Fixed bug in which a leading tab in a command file would prevent the command
from being recognized (first character was being skipped in untab() function).
Reported by S. Dezawa.  ckucmd.c.

Fixed bug in which cbreak mode (and therefore ?, ESC, etc) stopped working
after executing a '!', RUN, or PUSH command.  Case XXSHE, ckuusr.c.

Fixed a parsing bug that had been there forever.  Any number of words could be
typed after the last word of a command and the parser would not complain until
the command was finally entered.  Now it complains as soon as the first wakeup
character (space, question mark, ESC or TAB) appears after extraneous
characters were typed.  cmcfm() in ckucmd.c.

Added new flag to command parser keyword tables: CM_ABR.  If set in a
keyword's flag field, it means that the keyword is an abbreviation for another
keyword.  This allows the full keyword list to be listed when the user types ?
for a menu.  Before this change, for example, there was no way to find out
what commands started with C because C was an invisible abbreviation for
CONNECT; C? would just list C.  With this change, cmkey() will no longer
consider a match on an abbreviation to be an exact match if the user types ?,
but instead will list all keywords that start with the abbreviation.
ckucmd.c, ckucmd.h, ckuusr.c.

Strengthened xxstring() (variable and function expander) against pathological
cases, as where very long invalid builtin function or variable names are
entered, or when a trailing parenthesis omitted from a variable or function
reference.  This fixes the bug that Peter Mauzey reported in which "send
xxx.*" followed by "delete \v(fi" would fail to work.  ckuus4.c.

Fixed the bug that Terry Kennedy has been reporting for months, which occurs
only in the VMS version: "send ckv?c?" should give a list of all the ckv files
when the first question mark is typed, and then all the ckvc files at the
second one, but instead the second question mark resulted only in "No files
match".  I can't explain why this was happening (because it never happened in
UNIX, which uses exactly the same code), but I fixed it by reinitializing a
pointer.  ckucmd.c.

MISCELLANEOUS BUG FIXES

Changed Ventel modem dialing string from "<K%s\r>" to "<K\r%s\r>", based on
a report from Tony Querubin at the University of Hawaii.  ckudia.c.

Fixed doexit() to return right type of exit code -- had #ifndef VMS instead of
#ifdef VMS.  ckuusx.c.

Fixed lockfile in IBM RC PC AIX 2.2.1 implementation (again).  Piet Plomp.

Reportedly, during local-mode file transfer with the local C-Kermit running
on certain System-V based UNIX systems, typing ^\A to get a status report
would badly confuse the protocol, resulting in a series of timeouts and
retransmissions, and sometimes total failure.  This does not happen on BSD
based UNIX systems.  The difference is that System V (at least up thru R3)
cannot inspect the terminal input buffer without actually reading it, so
System V users must type the quit character (normally ^\) first, causing an
interrupt handler to be invoked.  This code hasn't changed in a long time, but
I tried to tighten it up a little -- now it only handles one request at a
time (i.e. per packet), instead of looking for a bunch of them queued up.
chkint() in ckuusx.c.

Changed (Ctrl-)A status display to correctly report the number of window
slots.  ckuusx.c.

Added missing SunLink X25 definitions to ckcnet.h, and changed SHOW PAD
parameter loop limit to correct value.  Marcello Frutig, Catholic University,
Sao Paulo, Brazil.

COMPILER ADJUSTMENTS

Fixed declaration of (*sx)() to be extern in ckuus4.c, to prevent multiple
definition error at link time (only seems to have been a problem on the Amiga).

Removed multiple definitions of debfil[], pktfil[], and sesfil[] from ckuusx.c.

Fixed dozens of function returns to cast their arguments to the type of the
function, thanks to Amiga C (Aztec and/or SAS) compiler complaints reported by
Larry Rosenman.  ckuus3.c, ckuus5.c, ckcfn2.c.

Changed declarations of signal handlers to include a dummy argument, in an
attempt to satisfy the ANSI C prototype for signal() (e.g. in System V Release
4).  The tradeoff will be lots of new lint complaints ("argument not used").
ckuus4.c, ckucon.c, ckutio.c, ckudia.c, ckuscr.c.

Changed partab[] (parity table) to cast each and every initializer (256 of
them) to CHAR (= unsigned char) because ANSI C complains that "initializer
does not fit" in cases like "unsigned char foo = '\222'" -- ANSI C casts the
constant to (yes) signed char.  Also added L's after all the constants in the
CRC generation tables.  ckcfn2.c.

There is a similar problem (-1's initializing a unsigned character array) in
ckcpro.c, generated by wart from ckcpro.w.  Attempted to fix this by defining
the table type to be (signed) char rather than (unsigned) CHAR.  ckwart.c.

Removed unintentional trigraphs ("???") from comments in ckuus5.c, ckcfn2.c.

PROTOCOL CHANGES AND FIXES

(Physical layer) - If the attempt to read a packet results in a timeout,
and if Xon/Xoff flow control is selected, send an XON character in case the
other Kermit was blocked by a spurious XOFF.  rpack() in ckcfn2.c.

In response to several reports of "NAK out of window" errors, changed the
input() code to be more tolerant of NAKs that are received for packets that
haven't been sent yet, but still treat a NAK for a packet from the previous
window as a fatal error, because there's no way to resend it.  ckcfn2.c.

Added a new state to the protocol interpreter, or rather, separated two old
states: <rdata,rattr>Z.  Having these two states combined prevented a
zero-length file from being created by C-Kermit if an Attributes packet came
with it.  Suggested by Alan Grieg at Dundee Tech in Scotland.

Somehow some code disappeared from C-Kermit's transport layer, the input()
function, namely that after getting a NAK for a packet that is in its window,
and retransmitting the packet, it should go back and wait for another packet
to arrive, rather than returning to the protocol state machine.  This was
causing all sorts of failures of the "Unexpected packet type" type.  Added a
"continue" statement at the right place.  ckcfn2.c.

The sdata() function would always attempt to send a windowful of new packets
in the absence of any arriving packets.  Obviously wrong -- the maximum number
of new packets it should send at once is equal to the number of free
send-packet buffers.  I'm not sure what the symptom of this overzealousness
was other than messages about "can't allocate send buffer" in the debug log.

Inspection of a long debugging log of a windowed transfer showed the number of
send buffers to decrease each time there was an error causing packets to be
received out of order, and never increase again until a new file was begun.
For example, when transferring a long file with 12 window slots, the number of
effective window slots would gradually work its way down to one and stay
there.  Diagnosis: The transport layer returns an ACK to the application only
when it is the ACK for the packet at window-low, and only frees the send
buffer at this time.  As soon as the application gets this ACK it sends
another packet, thus immediately reusing the send-buffer that was just freed.
Theoretically, a send-buffer could be freed any time an ACK arrives for it,
because it will never have to be retransmitted.  But the ACK'd status is kept
in the packet structure, and if the packet is freed before it reaches
window-low, this information is lost.  Cure: Keep a separate structure (an
array indexed by packet number 0-63), to show whether each packet has been
ack'd.  Tried this: created an array sacktbl[] to hold the ACK'd flag for each
active packet.  This seems to work -- after a lost ACK is received, the number
of free send-buffers grows back to a higher number.  Needs a lot of testing!
(left old code in place to revert easily, look for all occurrences of
sacktbl[].)  ckcfn2.c, ckcfn3.c.

VMS CHANGES

Made wildcard expander return 0 (meaning no files match) rather than -1
(meaning too many files matched) if there is an unexpected RMS return code.
Alan Grieg.  ckvfio.c.

Made wildcard expander return -1 if too many files match.  ckvfio.c.

Added a bandaid for the Ctrl-C during DIRECTORY command problem.  Doesn't
really fix it, but alleviates it somewhat.  William Bader.  ckuusx.c.

Added "ckermit_init" to the list of logical names.  This one, unlike
"ckermit_ini:", can stand for the entire filename, rather than just the
device:[directory].  Jim Barbour.  ckvfio.c.

New C-Kermit/VMS help file.  Jim Barbour.  ckvker.hlp.

Yet another DCL command procedure for building C-Kermit/VMS.  Jim Barbour.
ckvbld.com.

Nothing done for CKVTIO.C -- BYTLIM quota exceedings and data overruns will
still be a problem until someone who knows more about VMS than I do can
overcome these problems.  Added a few comments to highlight known problem
areas.

------------------------------

5A(162) Sat Nov  3 13:54:22 1990

Quick fixups:

The change to parchk() in edit 161 was (a) a bad idea, and (b) done wrong.
This prevented C-Kermit from receiving 8-bit data files when packets were
longer than 256.  I declared an index variable to be a CHAR rather than an
int, oops.  But then I realized that including the block check in the parity
checking scheme was (a) risky and (b) overkill, so I removed all of that code.
Works fine now.  Thanks to quick reports from Robert Weiner, Bo Kullmar, and
Jay Rouman.

Robert Weiner also noticed that Berkeley-based versions had become suspendable
by keyboard interrupt during file transfer.  The problem was in the new
ttpkt() code that uses LPASS8 mode when available (the benefit of which is to
allow both 8-bit data and Xon/Xoff flow control during packet operations).  An
explicit system call must be made to disable the suspend character.  This was
added.

------------------------------

5A(161) Fri Nov  2 21:32:21 1990

PROTOCOL FIXES

Charles Lasner found that the edit 160 C-Kermit server went into text mode
after responding to any REMOTE commands, even if its global mode was binary.
Found the statements that saved and set the file mode in syscmd() were
transposed.  They have been this way at least since version 4E, but some
recent change seems to have exposed this problem.  Put the offending
statements in the right order.  Later, Terry Kennedy found another place
where this happened (REMOTE HELP).  ckcfns.c.

Terry Kennedy found that the file control block (fcb) was being filled in
before the attribute packet was interpreted, which prevented zopeno()
from ever opening a file in binary mode.  This affected only VMS, because
UNIX, Mac, Amiga, etc, have only one way of reading data from a file.  Moved
the attribute interpreting-code to above where the fcb was filled in and
binary/text mode determined.  ckcfn3.c.

Terry Kennedy found a problem introduced by the parity-sensing code. The
parchk() routine was examining the next-to-last byte of the packet [n-2]
rather than the last byte of the packet [n-1], which worked for UNIX, but not
for VMS.  The length returned by UNIX ttinl() included the packet terminator,
but the VMS version did not.  Changed parchk() to not depend on whether the
terminator was included, but to search for the rightmost printable character.
ckcfn2.c.

Patrick Wolfe of Kuck & Assocs sent in a packet log that showed yet another
foulup that can occur in the packet-zero-recycling area.  Server receives GET
command (R packet), replies with S packet, but client does not get the S
packet, so retransmits the R packet.  There is no state in the protocol
machine to handle this, and it's not handled at the transport layer either
because packet number zero is being reused.  The server failed to allocate a
receive buffer for the next packet and gave up with "Internal error 18".
Fixed by (a) adding a new state, "<ssinit>R", to the protocol state machine,
that resends the S packet and frees a receive buffer, and (b) changing input()
to return rather than reading another packet if it got an unknown packet type
when expecting an ACK or a NAK.  ckcpro.w, ckcfn2.c.

Similar fix for when REMOTE HOST (C) or REMOTE <other> (G) packet arrives
again.  ckcpro.w.

Changed file input and output buffers to be allocated dynamically if
DYNAMIC is defined.  ckcker.h, ckcmai.c, ckcfns.c, ck?fio.c.

VMS-SPECIFIC CHANGES

Changed VMS C-Kermit to use file i/o buffers of size 32766 (the maximum RMS
record size) rather than 4096 if built with DYNAMIC defined, in which case the
big buffers are allocated dynamically with malloc().  This allows for transfer
of files that have very long lines, such as IGES CAD interchange files, etc.
No more "line too long for internal buffer" (as in Kermit-32) except when a
line is also too long for VMS itself.  (By the way, this still doesn't fix
the problem with the interrupted DIRECTORY command.)  ckcker.h, ckvfio.c.

Fixed zsyscmd() to close the inferior process when done.  Previously, any
RUN-like command would prevent subsequent SEND commands from working.
ckvfio.c.

Changes from Terry Kennedy at St Peters College:

29. Correct the behavior of zopeno() so that a superseded file will work
    correctly (for example, when a version limit is set). ckvfio.c

30. Make a local copy of the binary flag when the output file is opened.
    The binary flag tends to change state before we are done needing it.
    ckvfio.c.

31. Make IMAGE mode work. This is the continuation of item 24, in ckvker.upd.
    Note that image mode is only useful in very unusual circumstances --
    normally it will give you an unusable file.  This mode works by sending
    you all of the bytes in the file verbatim, including ones normally used by
    VMS for record attributes and delimiters. Also, note that this mode only
    applies to files sent from VMS C-Kermit and is ignored when files are
    received by C-Kermit.  ckvfio.c.

32. Remove a spurious return from the zsoutl() routine. This was generating
    spurious <CR>'s when log files were viewed using an editor.  ckvfio.c.

UNIX-SPECIFIC CHANGES

Added CONNECT-mode escape to suspend Kermit: <escape-char>Z or <escape-char>^Z.
UNIX only.  ckucon.c.

Turns out that LPASS8 and Annex terminal servers just don't mix.  Since Encore
computers use Annexes, I changed the makefile entry for Encore to include
-DENCORE, changed ckuver.h to include a special banner for Encores, and
changed ckutio.c to #undef LPASS8 if ENCORE is defined.  Tested, works ok.
Probably need a more general mechanism to let "pass8" mode be selected by the
user at runtime, since one machine might have different terminal servers,
different ports on the same terminal server can be configured differently, etc
etc etc.

Added code to znewn() to prevent optimizing compilers from warning about
"Element buf[-2] outside array bounds" (which would never really happen).
ckufio.c.

Added support for the Mark Williams Company Coherent OS, from ancient code
based on UNIX Kermit 1.0, circa 1983, Coherent-specific modifications added by
Lauren Weinstein, source sent in by Bo Kullmar in Sweden.  This old version
(the one with the tar-like user interface) is still being distributed with
Coherent.  This is one of those 64K-limit systems, so my first cut at a
makefile entry builds a bare-bones version -- no interactive command parser,
no character sets, no debug, etc.  Totally untested.  ckutio.c, makefile.

Added entry "du3" to makefile for DEC Ultrix 3.x, from Gordon Harrington.
Like the entry for Ultrix 4.0, but without DIRENT.

Changed name of entry "ds4" to "du4", since it should apply to all Ultrix 4.0
systems, not just DECstations.

Added entry "cray" to makefile for Cray X-MP, Y-MP with UNICOS System V R3,
from Lou Muccioli, Swanson Analysis Systems.  Straight Sys V R3, but defining
the make variable NPROC to be 1.

Added entry "hpux7sf" to be used with HP-UX 7.0 systems that don't support
long filenames.  Apparently there are some.

------------------------------

5A(160) Sat Oct 20 18:20:52 1990,

Changed Unix DIRECTORY command back to "/bin/ls -l", and made default
filespec be the null string rather than "*".  This works better than "ls -ld"
and "*".  Robert Weiner's suggestion.  ckuusr.c.

SEND <prefix><ESC><completion> didn't work in edit 159.  Fixed in cmifi(),
case ESC.  ckucmd.c.

Changed \v(ndate) to omit punctuation, so now it is yyyymmdd, like
19901019 rather than 1990-10-19 or 1990/10/19.  This way it won't conflict
with anybody's file naming conventions, and it fits within the MS-DOS filename
length limit.  Suggested by Jay Rouman.  ckuus4.c.

Commented out the line: "if (didweget(lbuf,"RING")) status = FAILED;" from the
Hayes modem dialing section of ckdial().  There's no reason why dialing should
fail if the modem reports it's ringing (as Telebits do)!  Thanks to David
Dyck, John Fluke Mfg Co.  ckudia.c.

Changed Hayes modem speed changing code not to set the speed to zero if the
modem reported a non-numeric speed, like "CONNECT FAST" (used by Telebit
modems).  Untested.  Reported by David Dyck.  ckudia.c.

Removed mdmtyp = 0 from '-l' command-line option handler.  This prevented "set
modem hayes" in initialization file from working with -l on command line.
Reported by David Dyck.  ckuusy.c.

Changed restoral of global file type to use actual value of binary (could
be 1, 2, 3, etc, in VMS) rather than 1 always.  ckcfns.c.

Added missing #include "ckcfil.h" to ckuusx.c, needed for VMS.  Thanks to
William Bader.

William Bader found that VMS Kermit server, after having received some number
of REMOTE commands (which cause it to start a fork) began to give "quota
exceeded" messages.  He diagnosed two problems: (1) zclosf() in ckvfio.c was
not closing and releasing the process, and (2) subsequent ttinl() calls were
failing because the piled-up processes ate into the user's BYTLIM quota.
William supplied code for zclosf() to delete the process.  ckvfio.c.

William also noted that the subsequent failure of ttinl() caused the higher
level code to become confused.  Here is what was happening: C-Kermit server
gets REMOTE command, successfully starts a process to handle it, turns around
the direction of transmission by sending an S-packet, then goes to read the
acknowledgment.  At this point ttinl() fails.  Kermit assumes this was because
of a timeout, so it goes to retransmit the S packet.  But (aha!) the S-packet
had been sent "out of window" and was not stored anywhere to be retransmitted,
so resend() failed with mysterious BPX code.  This was because a send buffer
had not been allocated for the S-packet at the time the direction of
transmission turned around.  So... I added code to sipkt() to allocate a send
buffer if one was not already allocated.  This makes all the "sending packet
out of window" errors disappear from the debug log, and should make the
protocol insensitive to ttinl() failures.  I hope that was the last packet
allocation buffer foulup!  ckcfns.c.

In the face of persistent complaints that file transfers were failing because
too-short timeouts weren't being adjusted in some cases, I was finally able to
track down the problem and (I hope) fix it.  C-Kermit was adjusting the
timeout too early, and its adjusted value was being overridden by the value
requested from the other Kermit during the protocol negotiation phase.  Now
the timeout adjustment is postponed until after protocol parameter negotiation
is complete.  But remember, automatic timeout adjustment only works (and is
only attempted) if C-Kermit can learn the transmission of the communication
line.  ckcpro.w.  Also, moved chktimo() to ckuusx.c so it can also be used
with -DNOICP.

Rewrote packet and buffer length #define's in ckcker.h.  They were allowing
VMS C-Kermit to say it would accept much more input at a time than it really
is capable of.  Also changed ckcfns.c and ckuus3.c to make sure that in
all cases the requested packet length is less than the #define'd maximum
packet length, and the product of the packet length and the window size is
less than the #defined maximum buffer size.  UNFORTUNATELY, it is still
possible to send enough input into VMS C-Kermit to make it crash AND log out
your job!  (at least when coming in through a terminal server via CMU's TCP/IP
package for VMS, and using any window size > 1 with any packet length at all,
but only while receiving files -- sending works OK, even with big window
sizes.)

Later, same tests on hardwired terminal line...  It can send packets no longer
than 1920, at least on my VMS system, without getting "quota exceeded" errors
(BYTLIM quota, no doubt).  With window sizes greater than 1, it can receive
only very short packets without getting "data overrun" errors in ttinl():

Window  Max Send  Max Recv
 Size    Packet    Packet
  1       1920      1920
  2       1000*       70   (* = MS-DOS Kermit restriction: 2000 / Window size)
  3        666*       35

There is something very wrong with VMS-specific sliding windows receive
code...  Checked to make sure that HOSTSYNC setting in VMS Kermit was
effective during packet mode.  It is.  I can't find a way to test READSYNC,
but I think it must work: my alt-typeahead buffer is 200 and I can send VMS a
1920-byte packet at 9600 bps without losing characters or getting errors, so
it must be working.  The dismal failure of sliding windows on input must be
related to Kermit's telling VMS to do output at the same time that input is
arriving.  But then how can any full-duplex applications work???

When sending files, VMS C-Kermit can use pretty large window sizes -- tested
successfully with sizes up to 12, with lots of error insertion and recovery.
With larger window sizes, it sometimes gets data overruns under error
conditions when it attempts to retransmit a window full of packets.

Discovered that cmdir (as used in CD and DIRECTORY commands) does not work for
VMS.  It uses zxpand() to see if the directory specification contains
wildcards, but the VMS version of zxpand() expands a directory name into the
list of all the files in the directory.  If the directory contains more than
one file, CD refuses to work because it claims the user typed a wildcard.  If
the directory contains no files, the program crashes in zxpand().  Changed
cmdir() to simply call "iswild()" to see if the directory spec contains
wildcard characters, and not to verify it any further.  This works a lot
better.  Now you can type "cd [.subdir]", "cd [-]", "cd foo:", etc.  ckucmd.c.

Realized that all the expanding and checking being done by cmdir() was totally
unnecessary.  Commented it all out, and made Unix work like VMS (except the
UNIX version also converts tilde to user's home directory name).  ckucmd.c.

Found that the Ctrl-C trap works in VMS if I remove the PASTHRU/PASALL setting
in concb(), but there is still no way to trap Ctrl-Y.  If PASTHRU/PASSALL is
left in effect, the command parser uses vms_getchar() in ckvtio.c to read from
the keyboard, which looks for Ctrl-C or Ctrl-Y itself and if it sees them,
restores the terminal and exits.  After concluding that there is truly no way
to trap Ctrl-Y from Kermit, I went ahead with Plan B: leave PASTHRU/PASSALL
set in concb(), make vms_getchar() call the Ctrl-C handler if it sees Ctrl-C
or -Y, make sure the Ctrl-C handler peels back the command level, closing all
active TAKE files and macros (by calling dostop()), add calls to conres() at
beginning of TAKE, DIRECTORY, DIAL, DO, and before any local-mode file
transfer command, etc etc.  Many modules affected.

Added parity-sensing code to ttinl() in ckvtio.c, within #ifdef PARSENSE
conditionals.  This required moving parchk() into ckcfn2.c, where all the
ck?tio.c modules can share it, and it can use the partab[] that is already
there, rather than a separate space-consuming copy.  Doing this is a little
strange, because normally the ck??io modules don't call or depend on anything
in the system independent modules.  Debugged and tested ok.  Compared
performance with non-parity sensing version on slow MicroVAX II -- the parity
sensing version was actually a little bit faster (don't ask me why).

Noticed that VMS version cannot receive ASCII files with lines longer than
1024.  This is because zoutdump() in ckvfio.c is record-oriented (as it must
be, because the VMS file system is record oriented).  The file input and
output buffer sizes are the same, INBUFSIZE = 1024, defined in ckcker.h.  I
made a separate symbol for the file output buffer, OBUFSIZE, and defined it to
be 4096 for VMS (for compatibility with Kermit-32) and 1024 otherwise.
ckcker.h.  Changed all references to output buffer size to use the new symbol:
ckcmai.c, ckvfio.c.  Also changed zoutdump() to not exit() (!) when "line is
longer than input buffer, but rather to return -1.

When decode() calls zmoutchar(), and zmoutchar() calls zoutdump(), and
zoutdump() returns -1 up thru decode() to ckcpro.w, the program hangs.  This
must be why somebody made zoutdump() exit() when this happened.  The reason is
that after sending its failure return, the transfer is shut down correctly
with an error packet ("Error writing file") and then Kermit tries to close the
file, but the zclose() calls zoutdump again to flush remaining buffers, and
then we get in an infinite loop.  Solution: set zoutcnt to 0 when this
happens, so subsequent calls to zoutdump() return immediately.  ckvfio.c.

VMS Ctrl-C/Y trap summary:
 1. When command parser is reading from the terminal: vms_getchar().
     Terminal is in PASSALL/PASTHRU mode, and Ctrl-C/Y are read as normal
     characters, only so that Ctrl-Y won't kill Kermit and leave the user's
     terminal in no-echo mode.  vms_getchar() checks for Ctrl-C and -Y and
     calls trap() in ckuusx.c (indirectly thru the function pointer that was
     passed to conint()) if it sees them.
 2. When command parser is executing from take file or macro: conres() is
     called to take terminal out of PASSALL/PASTHRU mode so that real Ctrl-C
     (SIGINT) trap can take effect, also trap().
 3. During DIAL and SCRIPT execution: Same as (2).
 4. During local-mode file transfer: Same as (2).
 5. During execution of certain commands like TYPE and TRANSMIT: real SIGINT
     trap, as in (2), but local to that command.
 6. When command parser invokes an inferior process: connoi() is called to
     turn console interrupt processing off.  Let the inferior process handle
     Ctrl-C/Y. 
 7. During remote-mode file transfer: ttinl() reads Ctrl-C/Y, passes special
     return code up through the call stack.
 8. During CONNECT: ignored entirely.

In case 1 and 7, Ctrl-Y is treated like Ctrl-C, just gets you back to the
prompt.  In cases 2-6, Ctrl-Y really stops the process so that it can be
CONTINUEd, and in each case the user's console terminal modes are reset so
that keystrokes echo, etc.

One problem with commands like DIRECTORY was that they were ultimately
executed in VMS by calling system().  Ctrl-C would indeed be caught by Kermit,
but Kermit had no way of stopping the inferior process.  Replaced all calls
to system() by calls to zsysmd(), so that the Ctrl-C handler, when it calls
zclose(ZIFILE), will kill the inferior process.  It does indeed kill them,
and returns control properly to the command parser, but something has gone
very wrong: the screen remains blank until we exit from the program.  It seems
as if terminal output (or perhaps standard output) has been redirected to
somewhere else (like maybe the NL: device).  I spent a lot of time trying to
track this one down, but a VMS expert is needed.  ckvfio.c.

------------------------------

5A(159) Mon Oct 15 13:46:39 1990

Added missing forward declaration of long for ttgspd() (pointed out by
everybody).  ckutio.c.

Fixed zxpand() to not core dump when trying to write to debug log when no
files match.  ckufio.c.

Jay Rouman pointed out that a last-minute change in edit 158 broke the
C-Kermit server's ability to convert uppercase names in incoming GET commands
(as from an Apple II that only has uppercase) to lowercase.  I moved all of
that (il)logic from gnfile() in ckcfns.c to zxpand() in ckufio.c to ensure it
can't possibly be skipped, and because it is, after all, UNIX-specific.  Ditto
for calls to tilde_expand().  This also called for changes to cmifi() and
cmdir() in ckucmd.c.  Seems much better now.  Also, added a quoting mechanism
to fgen() -- if it gets a backslash, it takes the next character literally.
But to get a backslash to fgen() from the command parser, you have to type two
of them.  But now, for the first time, you can send a file whose name is "*".
This quoting mechanism is consistent for both KERMIT and SHELL wildcard
expansion.

Fixed zchdir() and zgtdir().  Moved tilde-expansion stuff from ckcfn2.c into
zchdir() because it is, after all, UNIX-specific.  Fixed zgtdir() to make its
directory-name buffer static rather than automatic, so the return value is
always accessible.  Also made zchdir accept uppercase directory names, and
convert them to lowercase if the chdir to the uppercase name didn't work.
ckufio.c, ckcfns.c.

Changed UNIX-specific part of cmdir() to convert directory name to lowercase
and try again if it fails the first time.  ckucmd.c.

Looked at making server's response to REMOTE TYPE, REMOTE DIR, REMOTE SPACE,
etc, be case-independent too.  It could be done, but only at the expense of
a lot of code.  Given the present size factor, it's probably not worth it.

Strengthened UNIX ttol(), which is used to write packets.  Made it attempt to
recover if write()'s return code indicated it had only written a partial
packet.  It now allows itself up to 5 tries to complete the requested write().
Have not, however, been able to cause the retry code to actually be exercised.
ckutio.c.

Another problem related to ttol()...  If ttol() returned a failure code to
spack(), spack() failed to finish updating the packet structure.  Rearranged
this code to make sure packet was always fully installed in the packet info
structure by spack().  This clears up a lot of the mystery related to blank
packet types encountered by resend() and friends.  Thanks to Peter Mauzey for
sending in a debug log that uncovered this one.  ckcfn2.c.

Finally, about ttol()...  Alan Grieg suggested it incorporate a timer to break
xoff deadlocks.  I decided not to do this for several reasons: a timer is
already active during packet operations (unless the user turned it off); such
a timer could wipe out the alarm() values set by higher level routines,
especially the ones in ckdial(); and it's just more complicated, hairy code.
Before we start cluttering Kermit up with lots of conflicting timers, we need
a general-purpose alarm manager.  Fortunately, we developed one here for
another (now-dead) project.  It can probably be adapted to Kermit without too
much pain, but for now it doesn't seem to be necessary.

Changed resend() to fail if (ttol() < 0) rather than < 1.  Fixes problems with
VMS version, whose ttol() returned 0 on success, rather than a positive number.
Thanks to Alan Grieg, Dundee Tech, Scotland, for noticing the problem.
ckcfn2.c.

The resend() function has been a major irritant for many months.  Hopefully
the changes listed above will alleviate most of the problems we've been
seeing, but I also made one change to resend() itself: if it gets an i/o error
back from ttol() or spack(), it no longer treats it as fatal.  If the packet
was not successfully retransmitted, let the retry counter take care of it.
That's what higher level protocols are for.  ckcfn2.c.

Kermit's version string, versio, and version number, vernum, are not
sufficient for identifying divergent strains of the program.  Added a third
variable, verwho, to show "who" produced a particular version of the program:
0 = Columbia University, other numbers to be assigned.  Added text at top of
ckcmai.c explaining this convention and urging people to follow it.  This
should help to clear up confusion from non-Columbia-released versions floating
around.  ckcmai.c, ckuus4.c, ckuus5.c.

Added variable \v(speed) - current line speed, or "unknown".  ckuus[4h].c.

Added percent done and VMS file types to local-mode (Ctrl-)A file transfer
status display.  ckuusx.c.

Fixed up more help messages.  Put all character-set related help messages
within #ifndef NOCSETS...#endif.  ckuus2.c.

Changed ttgspd() to not refer to certain speed variables like B75, B50, etc,
even if they are defined, in MINIX, in which values of many of these variables
collide, causing "duplicate case in switch" errors.  ckutio.c.

Changed lowercasing of tty device name for lockfile (/dev/ttyA => /dev/ttya)
to depend on #ifdef M_XENIX rather than M_SYS5 because it was felt that
M_XENIX is more indicative of SCO Xenix than M_SYS5.  ttlock() in ckutio.c.

Changed makefile entries for 286-based versions to use -M2let64 instead of
-M2let32.  32 was resulting in "Cannot alloc mem for env.. Stop" messages.

Put conint() back the way it was before.  If SIGTSTP is defined, Kermit allows
itself to be suspended.  If the user's login shell doesn't support suspended
jobs, too bad.  There's no way Kermit can know this.  If the user doesn't want
the session to hang whenever she types Ctrl-Z, she should "stty susp undef".

Rearranged the declarations of cflg, and made global declarations of "char *p"
in ckucon.c and ckcpro.w static, because Minix loader, asld, complained p was
multiply defined.  Ditto for a few other variables - n, msfiles, action (found
by Bert Laverman).  After these changes, the program (in its minimum
configuration) compiles ok, but does not load: "/usr/bin/asld: out of memory".

Size (apropos of Minix)...  On the SUN-4, this edit, compiled in its minimum
configuration ("make sunos4m"): no anything except file transfer, connect, and
command-line parser) looks like this:

  text   data   bss    total   disk size
  98304  16384  14400  129088  129088

Which is still pretty big.  But the SUN-4 has RISC architecture, and therefore
the C code generates tons of machine instructions.  On a VAX-11/750 ("make
bsdm"), the same compilation looks like this:

  text   data   bss    total   disk size
  67584  14336  23068  104988   82944

Which is more reasonable.  The text size almost makes it under the 64K limit,
and probably would on a PC, with its variable-length instructions.

Got new ckvfio.c and ckvtio.c, plus minor changes to ckcmai.c (reformatted
server help message) from Terry Kennedy.  Changed ttol() in ckvfio.c to return
number of characters actually written, rather than 0, on success.  Changed
Terry's change to ztime() to always use ctime(), which is apparently available
even for the oldest versions of VAX-11 C, rather than asctime().  These
changes suggested by William Bader.  Wrapped lines > 80 in ckvtio.c.

Added (local) WHO command (yes, there was a request).  Only 4 lines of code.
ckuusr.c.

Made VERWHO symbol ("who produced this version") that can be defined on the
cc command line so the ckcmai.c source does not have to be edited.  ckcmai.c.

------------------------------

5A(158) Sun Oct  7 22:18:34 1990

WILDCARD EXPANSION

Added a new option, SET WILDCARD-EXPANSION { KERMIT, SHELL }, for UNIX only.
The default is KERMIT, meaning Kermit itself expands wildcards in SEND and
MSEND, as well as what it receives while in server mode in GET commands, just
as it has always done.  The new option, SHELL, means Kermit calls upon the
user's preferred shell (via SHELL environment variable, or failing that, the
user's login shell via getpwuid) to expand them.  The tilde_expand() function
is still active, so "~" can always be handled, even if the shell or UNIX
version doesn't support it.

Advantages of the new method include more flexibility in file selection,
consistency with the user's shell, and ability to handle a larger number of
files.  But there are drawbacks.  It's noticeably slower.  Characters in
filenames that are special to the shell (like |, &, `, etc) must now be quoted
with \ (this was not necessary before).  And the same Kermit command (SEND,
MSEND, or GET sent to a server) may behave differently depending on what your
login shell is.  For example, "{aaa,bbb}" is expanded by the csh, but taken
literally by sh and ksh; "[a-z]" is expanded by csh and ksh, but taken
literally by sh.

The expansion is done by passing "echo " concatenated with the user's filespec
to the shell.  This assumes that echo is a built-in shell command, or if it's
not, then the echo program is in the user's path (risky).  "echo" is used
rather than "ls -d" because ls says "xxx not found" if xxx does not exist
(unfortunately, the csh version of "echo" says "echo: no match" if you give it
a string containing metacharacters and no files match, wherease sh and ksh
simply echo the string back at you).  It doesn't matter much, because C-Kermit
checks each word that is returned for its existence as a file (but of course,
you could have a file called "echo:", "no", or "match"...).  And then what
happens if the user has a file called "-n"? ...

Most of these pitfalls were brought up by Kristoffer Eriksson.  So that's why
we now have a SET command to select the expansion method, and why "shell" is
not the default.

Kristoffer also raised a related, and very important point: If Kermit expands
wildcards in filenames it gets from the command line (this change was made in
edit 151), what happens if a filename contains a metacharacter?  For example,
what if one of the files has the name "*"?  (Think about it!).  The change was
made for a good reason, namely to let VMS, OS/2, and other non-Unix systems
(that don't have shells that expand metacharacters) give Kermit wildcard
filespecs on the command line.  Therefore, the UNIX version of C-Kermit no
longer expands filenames inherited from the command line, but the others
continue to do so.


X.25 SUPPORT

Added supporting code for SunLink X.25 network connections and X.3 pad
control, contributed by Marcello Frutig of Catholic University, Rio de
Janeiro, Brazil.  To use this code, you must have (a) a SUN, (b) the SunLink
product (libraries and header files), and (c) an X.25 connection into your
SUN.  There are numerous new commands: SET NETWORK X.25; PAD CLEAR, PAD
INTERRUPT, PAD RESET, PAD STATUS; SET/SHOW PAD (most X.3 PAD parameters may be
set, like escape, echo, forward, editing characters, etc); SET X.25 (call
options); and some new CONNECT-mode escape options.  Code added to ckcmai.c,
ckucon.c, ckutio.c, ckuus[r2345xy].c, and new entries added to makefile:
sunos4x and sunos41x.  This code is totally untested.  The selection of
SunLink X.25 support is governed by the CFLAG -DSUNX25; ckcdeb.h was changed
to ensure that this becomes undefined for any non-SUNs that try to include it.
THIS CODE IS TOTALLY UNTESTED.  It is based on edit 153 of C-Kermit 5A, fitted
into edit 158 and reworked in various ways.  The original code was written and
tested on a SUN-3 with SUNOS 4.0; SUN-4 testing is needed, as is SUNOS 4.1
testing.  The best I could do locally was ensure that the program still builds
and runs without SUNX25 defined.  I also tried compiling each module
separately with SUNX25 defined, and got no errors other than missing SunLink
header files and undefined SunLink-related symbols.  I wonder if any other
UNIX systems support X.25 connections, and if so, whether their support
libraries resemble SunLink enough to make this code more widely usable...
Does anybody out there have SunLink X.25?  Please report results, good or bad,
if you do.


SUPPORT FOR CYRILLIC CHARACTER SETS

Several translation tables were replaced based on discussions with Konstantin
Vinogradov in Moscow, John Chandler in Boston, and others.  New
Latin/Cyrillic-to-xxx tables were furnished by John, which are more invertible
than the first ones, and also correct a few mistakes.  Also, a new case was
added: C-Kermit sending a file with file character-set ASCII, transfer
character-set CYRILLIC, and language RUSSIAN.  In that case only, the file is
interpreted as "Short KOI" (KOI-7), and all lowercase ASCII letters (actually,
all characters in columns 6-7 except DEL) are converted to uppercase
Latin/Cyrillic letters.  This restores a file that was received with F=ASCII,
T=CYRILLIC to its original orthography, except the result is all uppercase
and hard signs are lost (Short KOI does not have a hard sign, so incoming
hard signs were translated to apostrophe).


OTHER CHANGES
 
Added a new command string, DIRCM2, to the system-dependent module.  This
tells the command the C-Kermit server should use if it receives a REMOTE
DIRECTORY command with no arguments, as distinct from the command to use when
arguments are given.  Necessary because in UNIX we use "ls -ld" (to avoid
recursive listings), but if no argument is given to ls -ld, it just prints a
listing for ".".  Keepers of all other C-Kermit based versions (Mac, Amiga,
etc) will have to add this definition.  ckufio.c, ckcpro.w.

Changed opena() for VMS case.  If user has set C-Kermit's file type to image
and an attribute packet comes in reporting type B (binary), C-Kermit should
not change its file type to binary, but rather leave it at image.  On the
other hand, a file type of binary reported in the incoming attribute packet
should continue to override a locally prevailing file type of text.  ckcfn3.c.

Changed ttlock() to lowercase the device name if it was uppercase on SCO
Xenix systems, which use lowercase lock names for uppercase tty devices
(e.g. /dev/tty2A is really /dev/tty2a, but with different modem control).

Changed \v(ndate) to use dashes rather than slashes, so it could be used in
filenames, and to supply a leading zero for the day of the week (rather than a
leading blank).  So today is "1990-10-06" rather than "1990/10/ 6".  Thanks to
Jay Rouman.  ckuus4.c

Changed DIAL command to set alarm after it outputs the dial string, rather
than before, to prevent the alarm set by ttoc() from undoing the alarm set for
the modem response.  Suggested by Mike Wuerth of BASES Burke Institute,
Cincinnati, OH.  Can't test here, because I don't have a modem connected, and
so DIAL always times out looking for its "wake string" response.  ckudia.c.

Changed all signal(SIGALRM,xxx) calls in ckutio.c to save and restore the old
signal handler.  This didn't make any difference in the dial time either.
This is probably because subsequent alarm() calls destroy the alarm(waitcnt)
call in the DIAL command.  What is needed is a general purpose facility for
stacking alarm calls, values, and handlers, and keeping track of elapsed time.
Not to mention a total rewrite of ckcdia.c to make it comprehensible.  Sorry,
not me.

Paul Placeway, working on Mac Kermit, found he could save a lot of space if he
defined NOICP and NOCMDL, but then the only statement in ckcmai.c that ever
got executed was "doexit()".  Added a special section for the MAC when both
NOICP and NOCMDL are defined.

Paul also complained that the srvcmd buffer was allocated statically, taking
up a lot of space (9K) when DYNAMIC is defined.  This is now allocated
dynamically by inibufs() in ckcfn3.c if DYNAMIC is defined, still static
otherwise.

Changed the default filespec for the DIRECTORY command in UNIX to be "*"
rather than ".", now that "ls -ld" is used.  This gives the desired effect.
In previous edits, "dir" with no operands just listed ".".  ckuusr.c.

Tested latest changes on SUN, NeXT, and Macintosh II with A/UX.  Also
discovered that I could add -DNETCONN and -DDYNAMIC to the makefile entries
for A/UX, with a slight change to the initialization of the variable nettype
in ckcmai.c -- A/UX is System V, but with a BSD sockets library.  Tested
SET HOST from A/UX, works fine.  Also added -DDYNAMIC to "make next".  That
works fine also.

Changed SHOW COMM to say "Terminal bits" rather than "Data bits", since this
reports like "parity: none, data bits: 7" were confusing and misleading.
Also, "Terminal bits" is reported only if the program is in local mode, since
it's the terminal bytesize setting.

Changed ckuusr.h for Minix to include <sys/types.h> before <pwd.h>.  John
Nall (new Minix tester) says it didn't work the other way.  This change should
only affect Minix, because the "#include <sys/types.h>" is within #ifdef MINIX
conditionals.

Changed makefile to make the object file type a variable EXT rather than
constant "o".  EXT is defined to be "o", but can be changed on the "make"
command line, as in "make minix EXT=s" (Minix uses s rather than o).  This is
done internally for the Minix make.  Thanks to John Nall for the information
about Minix object files.

BUGS FIXED

Fixed a typographical error that resulted in Kermits built with -DHDBUUCP
to write an integer, rather than string, pid into the lockfile.  ckutio.c.

Changed ttsspd() to make local-mode speed changes permanent by also putting
them in the ttold structure, where ttres() reads them.  ckutio.c.

Fixed a bug that caused C-Kermit to send unnecessarily short packets because
of confusion among the size given in a SET SEND PACKET-LENGTH command, the
size negotiated in the Send-Init parameters, and the dynamic packet length
calculation: (1) don't let dynamic packet length calculation kick in until
after the first couple packets have been sent; (2) create a new variable,
spsizr, for the send-packet length requested in SET SEND PACKET-LENGTH, as
distinct from any negotiated or recalculated value.

Fixed a bug introduced by the new "multiple get" code in edit 157.  "GET xxx"
sent to the C-Kermit server caused the server to hang if the file xxx did not
exist.  This involved a total reorganization and rewrite of sinit() and
gnfile().  This also fixes several other lurking problems that nobody reported
yet, and (I hope) does not introduce too many new ones.  ckcfns.c.

Thanks to persistent reports from Peter Jones, I finally realized that it is
bad to turn on trapping of the keyboard stop (suspend) signal if the user's
shell does not support job control.  It leaves the terminal permanently
wedged.  I added a test to conint() within the #ifdef SIGTSTP section: if the
SHELL environment variable is "/bin/sh", I signal(SIGTSTP,SIG_IGN) rather than
to the normal suspend-interrupt handler function.  This is still not optimal,
however -- it seems that the MIPS version of sh can be started as "sh -J" to
enable job control...  ckutio.c.

Added missing help messages.  ckuus2.c.

Compiled and tested on SUN-4 (both BSD and System V environments), Encore
Multimax, NeXT, DECstation 5810 Ultrix 4.0, Macintosh II A/UX 2.0, and
MicroVAX II with VMS 5.3.

------------------------------

5A(157) Wed Sep 26 20:57:53 1990

Rewrote gnfile() (get next file).  Previously, it worked either with a list of
nonwild filenames, or a single wild filespec.  The new version works with both
at once, and it's much simpler too.  So now you can feed C-Kermit a list of
filenames on the command line, some of them wild, some not.  C-Kermit expands
the wild ones itself.  This allowed a big chunk of Data-General-specific code
to be removed.  ckcfns.c.

Added MSEND command (at David MacKenzie's suggestion).  Just like SEND,
except you can give a list of filespecs (separated by spaces), rather than
just one, e.g.:

  C-Kermit>msend cku*.c cku*.h ckc*.c ckc*.h ckw*.c ckcpro.w makefile

All the files on the list are sent in a single transaction, i.e. between
one pair of S and B packets.  This command adds about 200 words of storage,
plus a small amount of code.  Put -DNOMSEND in your CFLAGS to compile it out.
ckuusr.[hc].

Yes, it would have been better to change the SEND command to allow a list of
names and asnames, as in:

  C-Kermit>send foo bar, x*.*, *.old *.new, etc

but this is just too much work -- the command parser would need a new function
added (cmcomma) and this could break many other commands that allow commas,
and it would probably take a week to put things right again.  Save this for
5B.

Changed the server to read multiple filespecs in GET string, so now you can
give a list of filespecs (separated by spaces) in GET commands from MS-DOS
Kermit or wherever.  The GET string is broken up into its component filespecs
by a new function fnparse, which I put in the user interface section
(ckuusx.c).  C-Kermit implementations that use different user interfaces
and/or which allow spaces in filenames (like Macintosh) will have to alter or
make their own version of this function.  You can restore the old behavior
by adding -DNOMGET to your CFLAGS.  ckuusx.c, ckcpro.w.

Changes to Cyrillic translations suggested by Konstantin Vinogradov and
"Kermit Gang" at ICSTI in Moscow.  Also nomenclature changes - "Old KOI-8"
rather than "KOI-8" (it's a long story)...  Added a new table for translating
Cyrillic into ASCII -- it uses the widespread convention ("Short KOI") of
converting all ASCII letters to uppercase, and all Cyrillic letters to
lowercase Latin letters having approximately the same sound, using braces,
bars, etc, for the few letters that have no phonetic equivalents (like cha,
sha, shcha, yu, etc).  ckuxla.c.

Added DEC-MCS-to-ASCII translation of OE ligature to O and E (both capital
and small).  ckuxla.c.

Added new variable \v(home) to contain user's home directory.  For UNIX,
it includes the trailing slash, like "/usr/fdc/", and for VMS it looks like
"$DISK1:[FDC]".  Thus it can be concatenated with a filename, as in
"take \v(home)compuserve.tak" in both UNIX and VMS.  This lets TAKE commands
can work no matter what directory the user is cd'd to, if the user keeps the
command files in her home directory.

During local mode file transfer, typing any character other than a legal
interruption command (A, X, Z, etc) will now reprint the list of legal
interruption commands.  Suggested by David MacKenzie.  ckuusx.c.

Added error messages for all commands that were not giving them if the user
omitted mandatory fields.  ckuus*.c.

Removed double error messages for most other commands when they are
incompletely entered: close, delete, log, mail, take, translate, transmit,
type.  ckuusr.c.

Fixed most error message to be more informative and not to make a blank line
unnecessarily.  ckuus*.c, ckucmd.c.

In GET command, initialized "as-name" to the null string.  There were reports
of files arriving in response to the GET command being stored with the wrong
name, like (yes) "*.*".

Moved declaration of mdmspd (modem changes/matches speed flag) from ckuus3.c
to ckcmai.c, in case program is build with -DNOICP (Jay Rouman).

Changed SCRIPT command to recognize \\b as a code for sending BREAK, just
like OUTPUT.

Finally found a Xenix/286 tester, Ethan Lish, Tomorrow's Horizons, Bethesda,
MD.  Naturally, Kermit would not compile or load -- compiler crashed, segments
too big, etc.  After much correspondence and hints from Kristoffer Eriksson
and Warren Tucker, success.  New "sco286" entry in makefile.  Another "?"
becomes a "+"...

Added support for Excelan TCP/IP for SCO UNIX 3.2.0 and SCO Xenix 2.3.x,
from William Bader.  ckcmai.c, ckutio.c, makefile.

Added BUG command (tells how to report bugs).

A couple fixes for ATT7300 from Andy Fyfe.  Add two missing closing right
parens in dialer code, and hangup just by setting speed to zero.

A couple fixes for AIX 3.1 on the RS/6000 - It uses a PID string in its
lockfiles, but it is not HDB UUCP.  Changed variable name hz to hertz because
hz is defined as a symbol in a system include file.  Larry Rosenman, Lehigh
University.  ckutio.c.

Tested building program with -DNOICP.  Found a couple other misplaced items
and moved them to better places.

------------------------------

5A(156) Sun Sep 23 13:26:18 1990

DYNAMIC PACKET LENGTH

Charles Lasner reported a wierd interaction between MS-DOS Kermit and the
C-Kermit server, when GETting files.  As soon as an error occurred, all
subsequent files were being reported by MS-DOS Kermit as "100% received".  The
C-Kermit side of this problem was caused by the dynamic packet length
calculation, which was a little too draconian.  I had changed this a while
back to kick in on every packet, not every 8th.  Somehow this seems to have
disturbed some assumption made by the hairy algorithm, and in Charles's case
the packet length would drop down from 1000 to 31, yow!  This prevented
C-Kermit from sending its Attribute packet, which is longer than 31 (so MS-DOS
Kermit, because of a bug, would think the incoming file was 0-length, hence
the constant 100% report).  Charles also pointed out that once an error
occurred, it took forever for the packet size to recover to its original value.
Solutions: (1) replace the hairy packet-length calculation with a much simpler
and faster one that I understand, and (2) don't refuse to send an A packet
just because the current dynamic packet size is something ridiculous like 31.
The new resizing algorithm is: if there was an error (timeout or checksum) 
receiving the most recent packet, cut the send-packet length in half (down to
a minimum of 20); if there was no error, increase it by 5/4.

Here's another idea for packet length resizing that keeps a history of the
last n packets.  Push a 1 into the left end of an n-bit shift register if the
current packet is bad, otherwise push a zero.  The current n-bit value, w, of
this register is a weighted sum of the noise hits for the last n packets, with
the most recent weighing the most.  The current packet length is some function
of w and the negotiated packet length, like:

  (2^n - 1 - w) / (2^n - 1) * (negotiated length)

If the present resizing method causes problems, think about this one a little
more.

NEW COMMANDS AND FEATURES

By popular demand (the vote was 21 to 5), changed the UNIX version of C-Kermit
to not match "hidden" files (whose names start with ".") when SEND filespec
starts with "*" or "?".  The overwhelming sentiment was that Kermit should
behave like ls and the shell.  This is a simple 1-line comparison added to
match() in ckufio.c.  You can still send hidden files by starting the SEND
filespec with ".", as in "send .*", "send .k*c", etc.  Unfortunately, this
change means that there is no way to send all the files in a directory -- both
hidden and nonhidden, in a single command.  "send *" gets the nonhidden files,
send ".*" gets the hidden ones.  To put it back the old way, add -DMATCHDOT to
your make entry.  "*.*" does not match hidden files (nor does it in the shell
or ls).  Anybody want to change their vote?

Added a new transfer character set: Latin/Cyrillic.  Added support for three
file character sets to go along with it: Latin/Cyrillic itself (little used so
far), "Alternative Cyrillic" (popular among Soviet programmers and recently
adopted by IBM as Code Page 866), and KOI-8 (reportedly used on UNIX systems
in the USSR).  All of this depends on the symbol CYRILLIC being defined.  If
it is not, the translations work as before, and the program is no bigger.  At
first I thought I would need to change the logic of the program because it
would not be practical to translate between Cyrillic and Roman alphabets.  But
then I realized that KOI-8 is designed specifically to be rendered in Roman
characters, simply by chopping off its 8th bit (the Russian & Roman characters
match up phonetically for the most part).  So I completely sidestepped this
problem, and did the whole thing just by adding and updating a few tables; you
can still translate anything to anything.  If you #define CYRILLIC in
ckcxla.h, all the Cyrillic translations will be compiled in, at a cost of
about 1760 bytes to the program image.  Since this is so small, I'm leaving it
in by default for now.  ckcxla.h, ckuxla.h, ckuxla.c.

Added translation of AE/ae ligature to Ae/ae for tcs=Latin1, fcs=ASCII,
language=(any Scandinavian).

It seems that the code that was added to ckudia.c to notice when a Hayes-like
modem reports a different CONNECT speed than the dialing speed and changes
Kermit's speed automatically is not appropriate for speed-matching modems.
Reportedly, for example, a Hayes 9600bps modem will keep its DTE-side speed at
9600, no matter what speed it negotiates with the other modem.  BUT... it
still reports the negotiated speed, like "CONNECT 2400", even though it
doesn't change its DTE speed.  So we don't want our speed-changing code to
kick in at this point.  However, older modems (like Hayes 2400) *do* change
their DTE speeds when dropping down from the dialing speed.  So... A command
is required to let the user tell Kermit whether to believe the CONNECT <speed>
message or not.  This has been added as an optional trailing field to the SET
MODEM <name> command:

  SET MODEM <name> [ { CHANGES-SPEED, MATCHES-SPEED } ]

The default is CHANGES-SPEED, for compatibility with earlier releases and most
existing modems, meaning Kermit should believe and act on the CONNECT <speed>
message.  If MATCHES-SPEED is selected, Kermit will not change its speed, even
if the message implies it should.  ckudia.c, ckuus3.c.  SHOW COMMUNICATIONS
shows the current setting.  Presently this mechanism applies only to Hayes, US
Robotics, and HST Courier modems.

Added a new feature, sort of an analog to the initialization file.  Upon exit,
if a macro called "on_exit" is defined, Kermit executes it just before
terminating itself.  This macro can, of course, be defined in your
initialization file.  ckuusx.c.

Added SET FILE BYTESIZE command to go along with SET { COMMAND, TERMINAL }
BYTESIZE.  Default is 8.  ckuus3.c.

Changed SHOW MACROS to only show macros.  Added SHOW ARGUMENTS, SHOW
VARIABLES, SHOW ARRAYS, SHOW GLOBALS, SHOW FUNCTIONS.

Added variable \v(system) and \v(platform).  The former is (presently) "UNIX"
or "VMS" or "unknown", determined via #ifdefs in ckuus5.c, function vnlook.
Mac, Amiga, etc, developers, please let me know the symbols I can use to add
to this list.  \v(platform) is simply a copy of the string ckxsys, like "SUNOS
4.1" or "NeXT Mach 1.0", etc.  These variables are handy for writing
transportable command files & macros.

Added variable \v(filespec), to contain the file specification from the most
recent SEND or GET command.  Peter Mauzey's suggestion.

Added variable \v(ndate) - date in numerical format, e.g. 1991/09/22, suitable
for lexical comparison, sorting, etc.  Depends on ztime returning English
3-char abbreviations for months, might not work on "localized" systems.

Changed \fvalue() to \v(return).  It makes more sense as a variable.  ckuus4.c.

Removed \fmodulus(n,m).  It's available as \feval(n % m).

Changed \fsubstring(string,start,length) to return rest of string if length
argument omitted, and to return whole string if both length and start are
omitted.

Changed ASK and ASKQ to allow the prompt to be specified in braces to prevent
trailing spaces from being deleted.  Ditto for SET PROMPT.  Made better help
messages.

Changed CLEAR command to work in remote as well as local mode, and to set the
SUCCESS flag appropriately.  ckuusr.c.  Changed ttflui() to clear file
descriptor 0 if called in remote mode.  ckutio.c.

Changed code that reads lines from command files to trim trailing whitespace
between last nonblank char and line terminator.  This removes the confusion
that occured when a continued line has whitespace after the hyphen.  ckuus5.c.

Added SET TRANSMIT EOF <string> to allow TRANSMIT to automatically send the
specified string (like \4 = Ctrl-D) on end of file.

Changed meaning of command-line option -w to mean "write over files", rather
than "don't write over files" because the default filename collision action is
now to back up a file when a new file arrives with the same name.  ckuusy.c.

Installed change from Andy Fyfe to allow ATT7300/3B1 internal modem to dial
either pulse or tone.  Previously it only did tone dialing.  ckutio.c.
Increased dial time for this modem from 25 to 30 seconds.  ckudia.c.

Added CKVKER.MMS to the distribution, from Piet Plomp, Groningen University,
Netherlands.  This is a "makefile" for VAX/VMS that uses MMS (if you have it;
I think it's part of CMS, the Code Management System, a "layered product").
This is an alternative to the three DCL files CKVKER.COM, CKVMAK.COM and
CKVCDT.COM.

Added minor fixes & rename() routine to CKVFIO.C, and fixes to fix bps/cps
confusion (and a few other things) in ckvtio.c (Wm Bader).

Installed changes from Peter Mauzey, agreed to by John Chmielewski (both of
AT&T), for AT&T DTDM dialing.  ckudia.c.

BUGS FIXED

Discovered that "kermit -r", "kermit -s" didn't work any more in BSD
implementations.  No characters could be read from the communication line.
The reason for this finally penetrated...  The tty needs to have the CBREAK
bit set.  I made this discovery last edit, but thought it was required only
for local mode.  Now I realize it's always required, but for remote mode it
was being set by the command parser in concb().  When the command parser is
not used (as in "kermit -r") it wasn't being set.  So now ttpkt() always sets
it.

Fixed a bug that caused C-Kermit to go into an infinite beeping loop when
reading a command file that contained certain control characters, like Ctrl-D.
ckucmd.c.

Fixed problem with CONNECT command telnet negotiations that surfaced when
connecting to a half-duplex system, transferring a file, and reconnecting.
Kermit would start the telnet negotiations all over again on the second and
subsequent CONNECTs, which for some reason known only to the VM/CMS telnet
server, caused the SGA and ECHO options to become messed up.  Now Kermit
remembers about this and only negotiates once per session.  This change also
fixes the problem in which connecting to a SET HOST host after giving a BYE
command to the server causes Kermit to disappear.  ckucon.c, ckuus3.c.

MIPS users reported that the process group test (comparing Kermit's process id
to the controlling terminal's process id) does not work.  I think this must be
a MIPS bug.  Every computer that allows this sort of thing (because it defines
the TIOCGPGRP ioctl) says these two pgids are equal when Kermit is running in
the foreground, except MIPS.  So I #ifdef'd this test out for MIPS.  ckutio.c.

Discovered that "output \b" no longer sends a BREAK signal, but just a "b".
This is because of a change I made a while back to let \ followed by any
non-special character (other than %, &, v, f, {, etc) simply quote that
character, but with the backslash removed.  There's no way to fix this,
because by the time the OUTPUT command gets the text, the backslash is already
gone.  So the notation has to change to "output \\b".  Sorry.

Fixed command parser to restore normal prompt if Ctrl-C typed while a special
prompt was being used, as in ASK or multiline GET.  Increased size of prompt
buffer to allow for fancy prompts.

Discovered a truly obscure bug.  In a command like this:

  IF = 1 \fexec(macro) ECHO FOO

the IF comparison will not work if the macro executes an IF command with
a different condition.  Temporarily patched this by saving and restoring the
IF condition-code around calls made by \fexec().  I say "patch" because what's
needed in the general case is yet another stack for such items.  ckuus4.c.

Changed IF DEFINED to succeed only if the variable is defined and has a
non-null value.  Previously it could succeed if the variable was defined but
had a null value, as in "asg \%a \%1, if def \%a xxx" (where \%1 was
undefined).

Fixed parsing of SET COUNT.  It did not allow comments.  Removed SET COUNT
ARGC, no longer necessary because now you can SET COUNT \v(argc).

Noticed that SHOW MACROS always returned a SUCCESS value of zero, which caused
any command file that contained this command to terminate immediately.  Fixed,
ckuus4.c.

Fixed a bad typo in ckcpro.w, in which "=" should have been "==" (thanks to
William Bader).  This one could have prevented servers from responding
properly to GET or REMOTE commands.  Several other possibly important lint
findings reported by William also corrected in various modules.

Fixed SHOW FILE to report FILE COLLISION setting correctly (Andy Fyfe).

In ckucmd.c, declared malloc() correctly and removed casts (Kristoffer).

Changed INPUT command to strip carriage returns when writing to UNIX session
log if SET SESSION-LOG TEXT is in effect (Jay Rouman).  ckuus4.c.

Fixed REINPUT.  For me, at least, it only worked when DEBUG was set on
(which made it pretty hard to debug the problem!).  Turns out to have been
an unterminated string.  Plus I forgot to free some malloc'd memory.  ckuus4.c.

Fixed popcmd() in ckucmd.c to not attempt to strcpy a string whose pointer
was null.  This was causing core dumps under certain (rare) conditions, like
when \fexec() functions recursed too deeply.

Removed the restriction that SET RETRIES value must be greater than number of
window slots.  This restriction was added in edit 138, for a good reason (see
138 notes).  But the change made in edit 155 makes it unnecessary.  So now
it's gone.  ckuus3.c, ckcfns.c.

TESTING...

Tried running a C-Kermit server as a UNIX login shell.  This can't be done
directly by putting "kermit -x" as the shell in /etc/passwd, because you
can't put command-line arguments in the passwd file.  But it works fine if
you use a shell script like this for the login shell:

  SHELL=/bin/sh
  export SHELL
  /usr/local/kermit -x

If you don't include the SHELL business, then the many operations done by the
Kermit server (like executing REMOTE commands) requiring a shell will use the
user's login shell, which is Kermit itself, with pretty strange results...

Edit 156 was run through lint and through gcc with all its picky options.
It was compiled and tested on the following systems:

  DECstation 5810, Ultrix 4.0 (make ds4)
  Encore Multimax 510, 4.3 BSD (make encore)
  IBM 4381, AIX 3.0 under VM/CMS (make aix370)
  IBM PS/2, AIX 3.0 (make ps2aix)
  MicroVAX II, Ultrix 2.0 (makd bsd)
  MicroVAX II, VMS 5.3 (@ckvker.com)
  NeXT, Mach 1.0 (make next)
  SUN 4/280, SUNOS 4.1, BSD environment (make sunos41)
  SUN 4/280, SUNOS 4.1, System V R3 environment (make sunos41s5)
  VAX-11/750, 4.3 BSD (make bsd43)

The VAX/VMS version is still a bit rocky, and will be improved in future
edits.

When I tried to run the version I had compiled with gcc, I had two unnerving
symptoms -- symptoms that other people have been reporting for some time:

  1. During local-mode operations (like sending REMOTE commands to a remote
     server), I get strange messages like "flush fails: IOCTL inappropriate
     for device".
  2. The program fails the foreground test, so there is no prompt.

I suspect that gcc must be using different include files, and we wind up
making some bad system calls.  If these things are happening to you, try using
your computer's regular cc and see if the problem goes away.

MORE TESTING NEEDED...

Piet Plomp reports that all IBM AIX systems, not just AIX/RT, use the
weird multi-lockfile convention.  This is undocumented in AIX manuals, but can
be verified by looking at what cu does.  AIX users, please do this:

  1. Get a directory listing of /etc/locks/.
  2. Start cu on a dialout port, escape to the local shell,
     and get another directory listing of /etc/locks/.
  3. Send me the two directory listings.

I have had reports that edit 155 does not build cleanly on Xenix/286.  Several
people are working on this, but if anyone else can offer tips, please do.

Still need someone with MINIX to try "make minix" and let me know the
results!

------------------------------

5A(155) Thu Aug 30 02:11:39 1990

Several major topics in this edit.

SLIDING WINDOW PROTOCOL

Thanks to a debug log sent in by Ted Medin (and thanks to his persistence in
trying to convince me there was a bad problem in the sliding window code), I
found a case where send-packet buffers were being deallocated prematurely, so
that any attempt to retransmit them would result in horrible errors.  Moved
the buffer deallocation, a few statements down (in the input() function), so
that a send buffer is not deallocated until it is rotated out of the window,
and also took pains to make sure that an ACK for a packet ahead of winlo
caused that packet to be marked as ACK'd, so that this ACK could be returned
when the packet number popped up to the top of the window.  ckcfn2.c.

A little more behavioral analysis...  What happens if I'm sending a file from
a PC to C-Kermit using, say, 7 window slots, and I remove the data wire for a
couple seconds?  (I'm sure you've often asked yourself this question.)  When
the wire is reconnected, C-Kermit gets a packet far ahead of the one it wants.
So it stores the packet away, but sends no response to the PC.  This results
in a lengthy timeout/retransmit recovery phase, for example (5 sec x 7 window
slots = 35 seconds).  Wouldn't it be better if the file receiver sent a NAK
for the expected packet if it got a packet ahead of the one it needed?  Yes,
but C-Kermit used to do this until I discovered that this strategy, applied
blindly, could result in many unnecessary retransmissions and even failure
because of too many retries.  So now the file receiver, upon receipt of a
packet ahead of the expected one, sends a NAK for the expected, but only if
that one had never been NAK'd before.  Testing shows that this clears up
deadlocks much faster than before without automatically causing a windowful
of retransmissions.

Discovered that C-Kermit did not handle rejection well (who does?).  The
problem was in the sxeof() routine -- it tried to allocate a send buffer after
one had already been allocated.  This same thing probably happened any time
there was an error and C-Kermit had to send an EOF packet with "D" data,
telling the receiver to discard.  Fixed in ckcfn2.c.

FLOW CONTROL DURING PACKET OPERATIONS

All these years, it has been a source of great annoyance that flow control did
not work in packet mode in BSD UNIX implementations.  But I found that 4.3BSD
(don't know about 4.2 or earlier) has a local modes word in which one can set
the LPASS8 bit, meaning to pass 8-bit data, which does not affect flow
control.  I added sections to the BSD sections of ttopen(), ttpkt(), and
ttres() conditionalized on the existence of LPASS8 to use it if it's
available.

Unfortunately, this had the unpleasant side effect of allowing quit and
interrupt signals to interfere with file transfer and even cause core dumps if
a QUIT character arrives.  So in ttpkt() I added "signal(SIGINT,SIG_IGN)", but
only for remote mode because we still want the real Ctrl-C trap active in
local mode, and changed connoi() to set SIGQUIT to SIG_IGN instead of SIG_DFL.

But that had another unpleasant side effect: Two Ctrl-C's could no longer be
used to interrupt a remote-mode Kermit in packet mode, because when you set
SIGINT to SIG_IGN, UNIX *really* ignores the interrupt character, and does not
pass it to the program when you type it.  To get around this, I added code to
ttopen() to read the interrupt character from the tchars structure, to ttpkt()
to set it to -1 during packet mode, and to ttres() to restore it.  Everything
worked fine in remote mode, but I could not transfer files at all in local
mode: the local C-Kermit's ttinl() function could not read even one character
from the communication line.  So I added one further change: for local mode
only, set the CBREAK bit.  I have no idea why this is necessary.

Testing the System V version, I found that ^C^C does not, and apparently never
did, interrupt a remote kermit out of packet mode.  So I added
"ttraw.c_cc[VINTR] = 0;" to ttpkt() in the Sys V case.  Now it works.

INTERRUPTS

Made CONNECT's lower fork ignore SIGINT and SIGQUIT interrupts.  This corrects
problem with ^\! (escape to local shell from connect mode) experienced on some
systems, in which Ctrl-C typed at escaped-to shell would invoke Kermit's
interrupt handler rather than the shell's own.  Thanks to Chuck Hedrick for
this one.  ckucon.c.

MODEM SIGNALS, HANGING UP, AND DIALING

Increased sleep from 1/2 sec to 1 sec before declaring DIAL succeeded, because
some systems "blink" DTR at this point, and connecting too soon could cause
an i/o error (from John Chmielewski, based on experience with AT&T systems
using the DTDM modem).  John also discovered that the "sleep(3)" that was
removed in edit 151 is necessary after all, because of what happens when one
DTDM dials another DTDM.

Also from John Chmielewski: In tthang(), 3B2 systems need the CLOCAL flag to
be OFF (unlike the Tandy 6000, which requires it to be ON).  So now there is
a special case for 3b2's within #ifdef u3b2..#endif ("u3b2", John says, is
defined by the 3b2 compiler).  There is probably a better way to do this...
ckutio.c.

Added additional bulletproofing to ckudia.c: if ttpkt() fails, it will try
to close and reopen the device and then try ttpkt() again - same trick as is
used in ckucon.c if ttvt() fails, which seemed to help CONNECT a lot.

MISCELLANEOUS

Re-enabled dynamic packet length recalculation, changed it from every 8th
packet to every packet.  Added code to kick it in not only on reception of a
corrupted packet, but also whenever a NAK is received or a timeout occurs.
Tested it over a horrible connection, seems to work well.  ckcfn2.c.

Fixed up local-mode file transfer message and interrupt characters, so now it
takes both upper and lower case characters, as well as the control versions:
A/a/Ctrl-A for status report.  Allow CR or LF as well as ^R/R/r to resend a
packet, ^X/X/x as well as ^F/F/f to cancel file, ^Z/Z/z as well as ^B/B/b to
cancel batch.

Added REMOTE SET FILE COLLISION command, both ends.  You can send this command
from C-Kermit to a remote server, and you can send this command to a C-Kermit
server, like from MS-DOS Kermit.

Changed "make sys5r3" to include -DDIRENT and -DHDBUUCP, since these are both
part of the System V R3 definition.  Hope this doesn't cause any trouble (it
probably will).  Removed "sys5r3hdb".

Moved the "set languages" table from ckuus3.c to ckuxla.c, since it is not
necessarily universal to all implementations of C-Kermit.

Added code to protocol module in <rdata>D case to close the file and keep or
discard it, depending on SET INCOMPLETE KEEP setting (the keep flag), if there
is an error writing data out to disk.  ckcpro.w.

Added code to reof() to not discard a file if the keep flag is set.  ckcfns.c.

Added ERROR command to send an error packet.  Handy when you've got a Kermit
on the other end of the connection in packet mode but in some unknown state,
like when you've Ctrl-C'd out of a file transfer from local-mode C-Kermit.

Changed SET COMMAND { 7, 8 } to SET COMMAND BYTESIZE { 7, 8 } to make it
have the same syntax as SET TERMINAL BYTESIZE.

Added more (invisible) command synonyms for VMS and UNIX users.  ckuus[r3].c.

Removed more unused code.

TESTING

Compiled it myself for the first time on a PS/2 with AIX 3.0.  Compiles fine,
seems to run OK in remote OK over a telnet connection, but I had no way of
testing dialout or local mode.

Fixed declaration of lklockf[] in ttlock() for RT AIX, from Piet Plomp
ckutio.c.  With this change, he says RT AIX lockfile stuff now works correctly.

Edit 154 tested successfully on AT&T 6300 with SET DIAL HANGUP OFF, at last.

Measured C-Kermit performance on a very heavily loaded long-distance TCP/IP
(SET HOST) connection from NYC to Long Beach, CA, where the round trip delay
varied between 1 and 10 seconds.  Running C-Kermit 154 on a SUN in Long Beach,
against C-Kermit 154 on a SUN in New York, gave the following results:

    Packet   Window  Throughput
    Length   Slots    (CPS)      Comments

      90       1       118       No problems
      90       7       156       No problems
    1000      20       556       No problems
    2000      20       117       Lots of timeouts and retransmissions
    1500      20       654       No problems
    1500      30       213       Lots of timeouts and retransmissions

So a good combination of packet length and window size boosts performance
by nearly 600%.  Sending too many characters at once overloads the telnet
server at the receiving system and it drops characters.  This is demonstrated
clearly by repeating the same experiment with a DECstation at Long Beach,
whose telnet server drops characters if they come in bursts of more than about
400 (these measurements were taken when the network was somewhat less loaded):

    Packet   Window  Throughput
    Length   Slots    (CPS)      Comments

      90       1       151       No problems
     200       1       165       No problems
     500       1         0       Total failure, no packets got through
      90       2       172       No problems
     120       2       238       No problems
     200       2       357       No problems
     300       2         0       Total failure
      90       3         0       Total failure

Improvements from sliding windows would probably be even greater on virtual
circuit networks, but so far none have been available for benchmarking.  For
comparison, using C-Kermit SET HOST connections over my own local Ethernet
between two SUN-4/280s looks like this:

    Packet   Window  Throughput
    Length   Slots    (CPS)      Comments

      90       1       5142
    1000       1      18000      18000 seems to be top speed.
    1000       4      18000
    4000       4      18000

Since there are no delays in this connection, windows don't help.  Kermit's
throughput could be much higher than ftp's if it didn't have to go through
the telnet server.  Future project: a TCP/IP Kermit server?

OUTSTANDING PROBLEMS

Always a few.  If you're telnetted (SET HOST) to another computer and you
get an i/o error, the local C-Kermit just disappears.  I can't figure this
one out.  Debug logs show that it happens inside the write() system call;
write() simply doesn't return.

If you telnet to a half duplex host, local echo is negotiated automatically
via telnet SGA.  OK so far.  Then if you escape back, transfer a file, and
reconnect, the local echo setting is lost.

------------------------------

5A(154) Thu Aug 23 15:09:49 1990

Can binary files containing 0xFF characters be transferred over TCP/IP telnet
SET HOST connections?  Yes.  (But don't ask me how!)

Tested with "make bsd" on DECstation 5810 with Ultrix 4.0.  Despite compiler
warnings about signal()-type, it worked.  Changed SIGTYP in ckcdeb.h from a
typedef to a #define.  Now you can add -DSIGTYP=void or -DSIGTYP=int to your
makefile entry, rather than having to edit ckcdeb.h.  Made a new make entry
"ds4" for DECstation with Ultrix 4.0 using this SIGTYP.  For a complete make
entry, still need to find out whether it has saved original setuid, and what
its uucp lockfile conventions are.

Peter Mauzey reports that the error-after-receiving-1K-of-file problem is
fixed in edit 153.

Added another CONNECT-mode escape: any backslash numeric code, like
\65 to send an A, \240 to send an 8-bit character, \xff to send a hex
character, etc.  To use it, type the escape character, then backslash followed
by the radix indicator and number, then carriage return.  If what you typed
translates into a legal number in the range 0 - 255, it will be sent,
otherwise Kermit will beep.

Fixed the file character count as reported by STATISTICS and in the
transaction log for files sent by C-Kermit.  Until now, this number was always
a little bit too big because it included not only the file's contents, but
also its name.

Found that I had busted string expansion in a seemingly innocent change a few
edits ago.  Statements like "for \%i \%j \%x 3" no longer worked.  Fixed it.

Upon program startup, the new variable \v(args) is set to the main program's
argc, i.e. the number of command line arguments including the program name,
and the array \&a[] is declared to be of that size and filled with the
arguments themselves.  So \&a[0] is the filespec of the Kermit program, etc.
You can display the program's argument count and vector like this:

  echo argc = \v(args)
  for \%i 0 \feval(\v(args)-1) 1 { echo argv(\%i) = \&a[\%i] }

Added a new command-line switch "=", which tells Kermit's command-line option
parser to ignore all following command line options.  This allows you to write
Kermit commands that process any old command-line arguments, and therefore
provides a way to extend Kermit's command-line argument syntax.  For example:

  kermit = arg1 arg2 "arg3 is a quoted bunch of args" arg4

In this case \&a[1] is "=", \&a[2] is "arg1", etc.

This would be a nice feature if Kermit's command parser could handle variables
that expand into multiple words.  Then you could do:

  kermit = "set parity mark" "send oofa.txt" "statistics"

and then within Kermit:

  for \%i 2 \feval(\v(args)-1) 1 \&a[\%i]

to execute each command.  Unfortunately, it would take major surgery on the
command parser to make this work.  I spent a day on it and gave up.

Got rid of all the disgusting nested #ifdef's at the top of ckufio.c and
ckutio.c that are used to define the system version string.  Moved them to a
common place, a new file, ckuver.h, and reorganized them to (a) make sense,
and (b) make it easy to add new ones.

Added code to trap() to close any files that were open because they were being
transferred, so now you can transfer another file after Ctrl-C'ing a
local-mode file transfer without Kermit complaining "Can't open file".

Added a specific makefile entry for IBM AIX 3.0 on RISC System/6000, based on
information from Ken Mizialko, IBM, Manassas, VA.  Apparently AIX 3.0 on the
RS/6000 is a lot different from AIX 3.0 on the 370 or the PS/2.  Also,
separated the makefile entries for AIX 3.0 PS/2 and 370.

Built program with -DNOICP again, found & corrected a few problems (ckucmd.c
NOICP case needed a couple more header files).

Ran the program through gcc with -Wpointer-arith -Wcast-qual -pedantic.  Not
a single valid complaint about any of the Kermit modules, but lots of
complaints about header files from /usr/include(/sys).

From Patrick Wolfe: in zkself(), use "exit(kill(getppid(),1))" to increase
the chances that a server that logs itself out given the BYE command will
also hang up the phone.


5A(153) Wed Aug 22 19:52:47 1990

CONTROL-C TRAP

Previously, Ctrl-C trapping was turned off during the INPUT command, because
it would cause a core dump.  Chuck Hedrick found the solution here was to
put an alarm(0) in the Ctrl-C trap to turn off the timer that was set by the
INPUT command.  Rather than do that, I added a new system dependent function,
ttimoff(), to turn off timer interrupts because we can't count on all C
compilers / libraries providing an alarm() function.  For now the call to
ttimoff is within #ifdef UNIX..#endif.  Everybody else should add this
function to their ck?tio.c modules so this fix can apply universally.

Finally, after all these years, I fixed the Ctrl-C trap to work during
local-mode file transfer.  Thanks to Howie Kaye of CUCCA for suggesting the
answer: The setjmp for Ctrl-C trapping was done inside the parser() function,
but when packet protocol is active we have returned from the parser, thereby
deallocating the environment from which setjmp was called.  Solution: move the
setjmp to top level in main().  This required a lot of code reorganization.
The Ctrl-C trapping business remains conditional within #ifndef
NOCCTRAP..#endif, in case your C compiler does not support setjmp/longjmp (or
calls them by different names).  Ctrl-C trapping now seems to work anywhere
while typing a command, during execution of a command, during file transfer,
and even during file transfer initiated from command-line options (like
"kermit -l /dev/ttyxx -cnr").  And, thanks to the previous change, during
INPUT.

Unfortunately, Ctrl-C trapping seems to work in UNIX only, not VMS.

USER INTERFACE

Added REMOTE DELETE status to SHOW SERVER.

Changed the main program to look at argv[1] (if any).  If it is the name of a
readable file, then do a TAKE command on it after executing the initialization
file (if any), and before executing any command-line options and/or entering
the interactive command parser.  So a command like this:

  kermit cmdfile -p e

results in the following actions:

  1. Execute commands from init file;
  2. Execute commands from cmdfile;
  3. Set parity to even;
  4. Issue C-Kermit> prompt for interactive commands.

Perhaps you're wondering what motivated this feature.  It is the ability of
the Unix shell (any Unix shell: sh, csh, or ksh) to read a line of the form:

  #!/dir/filespec

at the top of a "shell script", and execute the "shell" given in the filespec.
In this case, the shell is Kermit.  This lets you write a Kermit command file
or script program and execute it directly without having to run Kermit first,
kind of like clicking on a Macintosh data file and having the Mac start up the
appropriate application automatically.  The filespec has to be a full
pathname, as in:

  #!/bin/local/kermit

As luck would have it, this first line is ignored by Kermit when it reads the
file because "#" is a comment introducer.  To make a Kermit command file work
in this way, you have to set the execute permission bit with "chmod +x".

I don't see any way to make a VMS DCL command procedure invoke Kermit like
this.  Do you?

MODEM SIGNALS, HANGUP, ETC

Found a possible bug in tthang(), in the BSD case where the "close(open())"
magic was being done to clear an error condition: priv_opn(ttnmsv) was being
called, instead of do_open(), and it was being called without the required
second argument, which would result in garbage modes being set.  Replaced the
erroneous priv_opn() call with do_open().  Thanks, lint.

Jay Rouman found that tthang() stopped working for him on his Tandy 6000
System V based Xenix in edit 151, with its new trick of setting c_cflag to 0.
He tried all combinations of bits and discovered that setting CLOCAL to 0
prevents hangup from working, but the others don't seem to hurt.  So now the
famous statement which originally said:

    ttcur.c_cflag &= ~CBAUD;		/* Change the speed to zero.  */

and then in edit 151 said:

    ttcur.c_cflag = 0;			/* Change all flags to zero.  */

now says:

    ttcur.c_cflag = CLOCAL;		/* Change all but CLOCAL to zero.  */

I also noticed that when the remote system drops carrier, the local system's
tty driver drops DTR, so that when you connect back to the remote system, it
won't talk to you.  So I added a call to tthang() in CONNECT, right after it
gets the "Communications disconnect" error.  This seems to do the trick
nicely.  Now subsequent CONNECTs after a disconnect almost always work.  It
might be better, however, to add an explicit "turn on DTR" function to
ckutio.c, at the cost of all the non-UNIX versions having to add it too.

OTHER

New CKVFIO.C for VMS from Terry Kennedy.  Fixes some minor problems.  A couple
fixes made to ck[cu]*.c files for VMS's benefit that Terry had given me for
edit 151, but which I missed.

Fixed -DNOICP (no interactive command parser) not to exclude the debug()
and tlog() routines, which are used even if there is no interactive command
parser.  Rearranged some other routines that were also affected.

Added SET CASE { ON, OFF }.  Controls whether alphabetic case is significant
in string comparisons including INPUT, IF EQUAL, IF LLT, etc etc.  It's just
a synonym for SET INPUT CASE { OBSERVE, IGNORE }.

Removed all explicit casts to (void), since they seem to upset so many
compilers.  Let's hope that their removal won't upset even more of them.  If
so, we'll have to add a typedef {void, int} VOID bit to ckcdeb.h.

Fixed up ckwart.c.  Broke up the long string that has been causing so much
grief to assorted compilers.  Changed "trans" to "transx" and "Trans" to
"trans".  Reformatted the source code to be consistent with the rest of Kermit
(not good for diffs, sorry!).

Fixed STATISTICS command to show speed and efficiency if known.  It used to
do this before, but somehow the speed variable was getting set back to zero.
Now the STATISTICS command calls ttgspd() to read the current speed.

Dozens, maybe hundreds, of lints -- removal of unused variables, functions,
etc, some mismatched types.  Nothing dramatic, except as noted above.  Maybe
some of these will cure a few problems.

TESTING...

Built, tested, works fine on the following systems.  All my testing is done
either in remote mode, or (on the SUN) in local mode through a null modem
cable that goes into another port on the same SUN, or with SET HOST.  I don't
have access to any dialout modems.  So "works fine" does not necessarily mean
it works in local mode with a modem.

 Encore Multimax 510, UMAX 4.3
 IBM 3083, AIX/370 (VM guest)
 MicroVAX-II with Ultrix 2.0
 MicroVAX-II with VMS 5.1
 NeXT with Mach OS 1.0
 SUN-4/280 in BSD environment
 SUN in Sys V environment
 VAX/750 with 4.3BSD

Note: AIX/370 is the first system I've encountered where pids are not ints.
On this system, pid_t is typedef'd as long.

System V CONNECT-mode behavior is much improved (at least on SUN).  Both
HANGUP (^\H) and logging out from the remote (causing it to drop carrier)
result "Communications disconnect" and popping back to prompt.

DIFFS

I fixed my diff-making procedure to be consistent with Larry Wall's patch
program, and ran the diffs through patch myself to make sure they worked.  The
new diff file is cku153.dif, which is a concatenation of all the diff files
for UNIX C-Kermit.  All diffs are now context diffs.  Normally there would
also be a ckv153.dif for the VAX/VMS-specific differences (in the CKV*.*
files), but all the differences this time around are confined to the CKVFIO.C
file, and the diff for that is bigger than the file itself.  The differences
between 151 and 152 remain available in cku152.dif.

LINGERING (MAYBE NEW) PROBLEMS

According to Terry Kennedy, the business where spack backs up the data pointer
to write the packet header into the packet buffer is still writing over random
memory, despite the fixes I thought I made in edit 151.  The solution for now
is to have arrays of "padding" allocated just before the packet buffer, whose
names are alphabetically guaranteed to sort before these buffers (VMS sorts
its variables).  ckcfn3.c (see bigsbuf, bigsbt, bigrbuf, bigrbt);

This one discovered by Patrick Wolfe.  SET HOST to another host, login, run
Kermit there in server mode, escape back, do stuff, then send BYE.  Subsequent
CONNECT gets some characters, as if Kermit exited to the shell, then an i/o
error, and then local Kermit disappears, poof!  On Patrick's system, a zombie
fork was left behind (probably Kermit's lower CONNECT fork).  On my SUN, there
were no zombies, but Kermit disappeared nonetheless.  Could it have something
to do with notifying the parent process using SIGUSR1?

Peter Mauzey reports that on the 3B2/300, dialing out and getting a file from
a remote server, the transfer consistently fails after the first 1K, i.e.
after zoutdump() writes out its first buffer.  The debug log shows that
zoutdump's write operation succeeded, and tracing through the code & debug log
does not show any obvious way the code could fail if zoutdump succeeded.  My
only suspicion so far is a compiler error in the evaluation of the zmchout()
macro (called from decode() in ckcfns.c, defined in ckcker.h).  Peter says
this did not happen in edit 149, but started happening in 150.  Added
additional debugging statements to decode() to see what zmchout is doing, plus
a few "& 0xFF"'s to undo any possible sign extension, and some extra parens in
the macro suggested by Paul Placeway.

Rob Weiner reported an "Internal error number 18", which means that rpack()
was called, but could not allocate a receive buffer, and "resend error NPS",
meaning No Packet to Send, i.e. resend() was told to retransmit a packet that
had not been built yet.  Added debugging statements.  If you can make this
happen reproducibly, send me a debug.log.

------------------------------

5A(152) Mon Aug 20 13:23:27 1990

Fixed various problems found & diagnosed by Chuck Hedrick of Rutgers
University:

Made ckufio.c do a better job of defining the maximum name length for a file,
and also added a definition for the maximum path length.  The latter is used
in declaring the "scratch" array in fgen (the wildcard expander).  The change
in edit 150 was a disaster for short-filename systems, because it shortened
the scratch array from 100 to 14, but this array is supposed to hold the
entire pathname, not just the filename.  Now it should be at least 255, and
maybe a lot bigger depending on the system's definition of MAXPATHLEN or
related variables.  Also changed scratch[] from an automatic to a static
array, because of its possible large size.  ckufio.c.

Added max file name and path length info to SHOW FILE display.

In ckutio.c, priv_opn didn't declare its arguments, resulting in garbage modes
on 16-bit systems.

And from Patrick Wolfe of Kuck & Assoc's:

Typo in "make clean" fixed.

Typo in command-line help message fixed (";" -> ",").

A variable was referenced in SHOW VERSIONS that should have been ifdef'd
(you'd notice this if you compiled the program with -DNOCSETS).

------------------------------

5A(151) Sun Aug 19 02:20:55 1990

VMS-RELATED CHANGES:

Changes to system-independent files for VMS, from Terry Kennedy:

 . Fix filename completion for VMS files.  ckucmd.c.
 . Make TYPE command to output a CRLF first.  ckuus4.c.
 . Fix program return code for VMS.  ckuus5.c
 . Fix DIRECTORY command (VMS wasn't doing it at all).  ckuusr.c

Plus a brand-new CKVFIO.C module from Terry, which does full RMS i/o for
both sending and receiving files.  See CKVKER.UPD for details on Terry's work
on the VMS version.

SET FILE command.  After much discussion with Terry Kennedy about how to
support RMS files in VMS, it was decided that many of the fancy SET FILE
commands were unnecessary -- and dangerous -- and so they have been removed by
enclosing them within #ifdef COMMENT..#endif: SET FILE FORMAT, SET FILE
ORGANIZATION, and SET FILE CARRIAGE-CONTROL plus all their suboptions. The
remaining item is SET FILE RECORD-LENGTH, which is now #ifdef'd only for VMS.

A new SET FILE TYPE option was added for VMS only: SET FILE TYPE IMAGE.  It
tells VMS to do naked block i/o on the file, bypassing all RMS record-oriented
services, like SET FILE TYPE BLOCK in Bliss Kermit-32.  New symbols for the
values for SET FILE TYPE are defined in ckcfil.h.  The file type is passed to
the file open routines in the zattr structure, so all the work necessary to
support it is confined to the system-dependent modules.  This command is only
parsed, there is no supporting action yet in CKVFIO.C.

Also, SET FILE TYPE LABELED was added for VMS, to allow a file to be
transferred along with lengthy information about its characteristics.  See
description in Info-Kermit V12 #3.  Presently same status as SET FILE TYPE
IMAGE (parsed, but not executed, supporting code to be added to CKVFIO.C).

The CKVTIO.C module has not been touched yet, so there are still some rough
spots in CONNECT mode and packet i/o for VMS.  In particular, if you try to
send sliding windows into the VAX, you're likely to get buffer overruns
failures.  This area will be attacked by Terry, most likely in edit 152.
Anyone who's an expert on VMS terminal i/o, and how to control it from C, is
urged to contact Terry directly: TERRY@SPCVXA.BITNET.

PACKET-PROTOCOL RELATED CHANGES

Changed zminchar (the macro that reads a character from a file) to return
a value of -2 if there was an i/o error reading the file.  This is
conditionalized on the existence of the stdio.h ferror macro.  ckufio.c.

Changed getpkt() to set the cxseen flag if it gets a -2 return from zminchar.
This should cause Kermit to send an EOF packet right away, with a D in the
data field, telling the receiver to Discard the file.  ckcfns.c.

There was a problem in spack(), when the pointer is backed up (up to 7
positions) behind the data to deposit the packet header, with other program
variables being written over.  This bit of trickery is intended to relieve the
program of copying the data into the packet -- it just builds the packet
around the data that's already there.  There should be no problem with this,
because the data pointer is allocated 7 positions into the packet buffer.
But... I discovered that the data pointer was set without the extra 7
positions by any code that called the encstr() function.  Fixed it in about 5
places, and I expect that will make the problem go away.  The fix is really
ugly.  (The symptom, which only showed up in VMS, was that the variable
bigsbufsiz was being changed to some huge number.)  ckcfns.c, ckcfn2.c,
ckcpro.w. 

Added calls to ttflui() (flush input buffer) for SEND, GET, MAIL, FINISH, BYE,
and REMOTE commands when executed in local mode.  When these commands are
issued, the local Kermit is initiating the operation and so there could not
possibly be anything of use waiting in the input buffer.  The flush operation
clears out any piled up NAKs from a server or receiver, preventing unnecessary
retransmissions.

COMMAND PARSER, USER INTERFACE, AND NEW COMMANDS

Added ! connect-mode escape to "push" to a local shell.  ckucon.c.

Changed file transfer message to:
  X to cancel file,  R to resend current packet
  Z to cancel batch, A for status report
Old Ctrl-F, Ctrl-B, etc, still work, but are not reported in the message.
This is for compatibility with MS-DOS Kermit.  Still need to find a way to
make this interruptible by Ctrl-C (without core dumps!).

Fixed cmfld() to beep if ESC typed at beginning of a field for which no
default was supplied.

Fixed xxesc() to treat a backslash followed by anything other than a digit, d,
x, o, or brace ({) as a quote.  The backslash is removed and the next
character is taken literally, as you would expect.  For example, "echo \;xxx"
now prints ";xxx".  ckucmd.c.

Added SET COMMAND { 7, 8 }.  Normally, C-Kermit's command parser strips the
8th bit off any command characters the user types.  SET COMMAND 8 will inhibit
this action to allow international characters to be entered in Kermit commands
(for example, in filenames, ECHO strings, etc).  ckuusr.h, ckuus3.c.

Added helpful error messages to many (all?) places where user could terminate
a command prematurely.  Previously, many commands (like ASK, ASSIGN, DO,
DISABLE, SET COUNT, SET ESCAPE, etc) gave no error message at all when this
happened.

Added ENABLE/DISABLE DELETE.  Thanks to Bo Kullmar for noticing the oversight.

Separated DISABLE/ENABLE FINISH and BYE; now FINISH and BYE can be enabled
and disabled individually, as requested by Bo.

Checked whether C-Kermit's command parser responds correctly to Xon/Xoff from
the controlling terminal.  It does, in both UNIX and VMS.

Added a new command, SET BACKGROUND { ON, OFF }.  This is to let the user
manually override C-Kermit's decision that it is in the background.  This is
necessary because Kermit considers itself in the background if its stdio is
redirected, like if you do "kermit < cmdfile > logfile" -- you don't want a
lot of prompts showing up.  However, if you do "kermit | vt100", where vt100
is a terminal emulation filter on a workstation, you want to be able to have
an interactive session with prompts showing up, etc.  Since Kermit can't tell
WHY its stdio was redirected, it can't decide what to do on its own.  Hence
the new command.  Probably useful only in UNIX.  Also available on the command
line as "-z".  ckuus[r235y].c.

Added SET and SHOW DEFAULT for VMS (simply synonyms for CD/CWD and PWD).

Fixed problem with completion of filenames of 99 chars or longer causing
coredumps.  Problem was in fgen() in ckufio.c -- a temporary buffer called
scratch[] was declared with 100 bytes.  Changed its size to MAXNAMLEN+1.

Fixed problem with parsing of LOG command.  LOG <anything> X<DEL> would
make the cursor jump back to the prompt instead of deleting the single
character X.  ckuusr.c.

Changed ARGC (and \v(argc)) to be the number of macro arguments plus one,
rather than just the number of args, to be consistent with MS-DOS Kermit 3.0
(and C itself).

Added SET FILE COLLISION NO-SUPERSEDE as an invisible synonym for SET FILE
COLLISION DISCARD, for MS-DOS Kermit compatibility.

C-Kermit has always relied upon the shell to expand wildcards given on the
command line (as in "kermit -s oofa.*").  But the VMS "shell" (DCL) doesn't do
this.  A simple 3-line change to ckuus4.c lets C-Kermit expand command-line
wild filenames itself, provided there is only one of them.  Tested on Unix:
"kermit -s oofa.txt, kermit -s oofa.*, kermit -s oofa.\*" all work OK.

Considered adding SET DOUBLE <char> to cause the specified character to be
doubled when a packet is output, for use with Arpanet TACs, Honeywell
mainframes, etc.  Added the parsing code.  But then decided not to do it after
all because it would slow down packet formation and transmission by a large
factor.  As it stands now, the variable "dblchar" contains the character that
is to be doubled on transmission.  Implementation could be done in two places:
(1) in the system-independent code (in the encode() function for the data
field AND in spack() for the control fields), by adding a statement like this
after each character that is deposited in the packet buffer:

    if (data[i-1] == dblchar) data[i++] = dblchar;

(dozens of them!) or (2) in the system-dependent ttol() function.  Option 2 is
particularly awful because it would require the packet to be recopied before
transmission.  A lot of effort went into version 5A to eliminate unnecessary
copying of packets.  So if anybody REALLY NEEDS this function, it should be
added using method (1).

SUPPORT FOR DIFFERENT UNIX SYSTEMS

Turned on TCP/IP support for HP-UX Sys V R3 - based versions ("make
hpuxs5r3"), based on info from Jim Barbour.  ckcmai.c and makefile.

Fixed a couple things for MIPS compilation, thanks to Peter Jones for the
info.  ckutio.c.

Changed Masscomp/Concurrent BSD-based RTU implementations to include
<fcntl.h> after all, at Farrell Woods' suggestion.  If this causes problems,
let me know.  Also, fixed the make entries for these versions to specify
"LIBS = -lndir" rather than "LIBS = lndir".  Also added "-DNETCONN" for
"make rtubsd"; Farrell says it works.

Added yet another new directory-related CFLAG: -DSDIRENT.  This means to use
<sys/dirent.h> for directory-related operations.  -DDIRENT means <dirent.h>.
Apparently necessary for Amdahl Sys V R2.6b.  ckufio.c, ckutio.c, ckuins.doc.

Added "make sys3nv" entry to makefile, for those who do "make sys3" and
get lots of "Illegal pointer combination" warnings: "nv" means "no void";
this entry just includes "-Dvoid=int" in the CFLAGS.

COMMUNICATION LINES AND MODEM SIGNALS

In edit 150, I removed the call to tthang() from ttclos(), figuring that
when the device is closed, DTR is dropped.  I was wrong, some systems don't
do this.  I put the call back, but this time after the call to ttres() rather
than before it, because ttres() gets horrible errors if called on a
modem-controlled line that is not presenting carrier.

John Chmielewski of AT&T found that he could make tthang() work on his
recalcitrant 3B2/400 system by setting not only the line speed (CBAUD) to zero
in ttcur.c_cflag, but all of the cflags to zero.  Kristoffer thinks this may
be a dangerous change, and we should investigate each flag separately (CREAD,
HUPCL, CLOCAL, etc).  Kristoffer also suspects that uugetty may be a culprit
here, by altering the device flags out from under Kermit.  In any case, this
change is worth a try.  If tthang() works for everybody and there are no ill
side effects, we can put a detailed investigation on the back burner for a
while.  So please test: the HANGUP command, the Ctrl-\H CONNECT-mode escape,
the DIAL command with SET DIAL HANGUP ON, and the EXIT (or QUIT) command.

Removed "sleep(3)" for AT&T DTDM modem at Peter Mauzey's request -- he
says it's not really necessary, and the 3B2 connects a lot faster without it.

Added code for bizarre UUCP lockfile conventions of IBM RT PC AIX 2.2.1 --
it has not one, but two, lockfiles.  From Piet Plomp, ICCE, Netherlands.

Changed ckcmai.c to call ttopen(), if the local flag is nonzero, as one of the
first things it does, so in case the default mode (dfloc) and device (dftty)
were defined in a system-dependent module (e.g. ckutio.c), the device would be
usable immediately.  A default terminal device can be specified in the
makefile entry as -DDFLOC=\\\"/dev/ttyxx\\\".  This change was made for the
benefit of the Macintosh and Amiga versions.  There's a slight pitfall here
for UNIX, namely that there is currently no mechanism for specifying a default
modem type at program startup time, so if the the default device is connected
to a modem, the initial open could hang.  The workaround, for now, would be to
start Kermit with "-l /dev/tty" on the command line, then "set modem" and "set
line".  In general, it's probably best to build the program in the normal way
for UNIX, and put any necessary "set" commands in the .kermrc file.

Changed the DIAL command to wait for carrier if modem type is UNKNOWN (Dan
Shullman's suggestion from 5 years ago).  But I don't have any way to test it.
Anyone?  ckudia.c.

Users of BSD-based systems were complaining that HANGUP (or ^\H) followed by
another CONNECT gets i/o error.  To cure this, I attacked the BSD section of
tthang(), adding a "close(open(ttnmsv));" and then a call to ttvt() to restore
the modes.  Cured the problem on my SUN just fine.

A related problem: What if the modem drops carrier before C-Kermit hangs up?
In this case, C-Kermit gets a "communications disconnect" and pops back to the
C-Kermit prompt.  The next CONNECT gives "Sorry, can't condition communication
line" as a result of a failure return from ttvt().  I fixed this one too, but
I'm not happy about how.  First, I observed that if I gave a HANGUP command
before reconnecting, everything worked OK.  So (I reasoned), a call to
tthang() at the place where the error occured would do the same thing.  It
didn't.  After much unsuccessful experimentation with moving the tthang() call
around, sleep()ing before &/or after it, etc, I changed the CONNECT code to
hang up, close, and reopen the device if it gets an error from ttvt().  This
works, but you will get a burst of garbage at first when you reconnect.  Oddly
enough, I also tried flushing the input the input buffer at this point, but
that made the whole business stop working again.

I tested the program in the System V environment and found it had the same
problem.  Although reconnecting after HANGUP and ^\H worked OK, reconnecting
after logout didn't.  The change to the CONNECT code fixed this for System V
too.  No changes were necessary to tthang() for System V in this area.  That
is, if tthang() works in System V at all, it works well enough to let you
reconnect to a line that has been hung up.  But you might see some garbage at
first.

Some people complained of DIAL complaining that it can't hang up the tty
line when DIAL HANGUP is ON.  Added code to ckdial() to close and reopen
the line if tthang() returns a failure code.  ckudia.c.

COMPILER-RELATED CHANGES

Removed all references to "pid_t".  Let's just use ints (don't fix it if it
ain't broke -- that'll teach me to read SVID!).

Changed names of all translation functions (like xl1toas) to remove "to" so
they will be unique in 6 characters (for PDP-11 C compiler).  ckuxla.c.

Changed names of variables wslotsr and wslotsn to wslotr and wslotn to be
unique within 6.  ckuu*.c, ckcfn*.c.

Changed cmflgsav to be cmfsav to be unique within 6.  ckucmd.c.

Changed mixed-case variable and function names to lowercase.  ckudia.c.

Removed many unreferenced variables.

Added -O to "make sunos4" and "make sunos41".  On SUN, saves about 64K in
the program image file.

PROGRAM SIZE

C-Kermit has become to large to build on certain systems.  Even when it can
be built successfully, it can take a long time to load into memory because of
its size (on my SUN-4/280, edit 151 takes 416K on disk!).

Added -DNODIAL to remove DIAL command.  Results in 8K reduction on SUN.
Here are the effects of various size reductions on the SUN (where programs
are always saved in multiples of 8K):

  -DNOHELP   32K
  -DNODEBUG  32K
  -DNOTLOG    0K
  -DNODIAL    8K
  -UNETCONN   8K

All of the above combined gives a total savings of 88K on the SUN.

Addition of the -O (optimize) compilation switch gives another 24K reduction,
and the -s (strip) linker switch removes another 56K, bringing the total size
down to 247K.  Now, lessee how much smaller we can make it...

  -DNOSCRIPT removes (UUCP-style) SCRIPT command.  8K on SUN.
  -DNOCSETS completely removes international character set support.  16K.
  -DNOCMDL removes the command-line interface ("kermit -s foo").  8K.
  -DNOICP removes the entire Interactive Command Parser.  128K.

Isolating the interactive command parser was a pretty big job.  It required
the creation of two new modules: ckuusx.c (containing functions and variables
common to both the interactive and command-line interfaces) and ckuusy.c (the
command-line interface itself).

After all this, the SUN executable is 104K.  With everything removed BUT
the command parser, it's 224K (an overall reduction of 128K).

Added an entry for MINIX to the makefile.  It includes all of the -DNOxxx
switches except -DNOCMDL, so the result will fit in 64K+64K.  Totally
untested.  Read the notes in the makefile (search for "minix:").

MISC

Updated help commands, documentation.  ckuker.mss, .doc, .ps, ckuus2.c.

------------------------------

5A(150) Mon Jun 25 11:38:14 1990 - Sun Jul 22 19:24:22 1990

NEW COMMANDS

Added WHILE command.  The syntax is:

  WHILE <cond> { command [, command [, command ... ] ] ] }

where <cond> is any condition accepted by the IF command, for example:

  WHILE not exist foo.bar { pause 1 }

WHILE commands can be nested in any combination with other WHILE commands,
IF commands, or FOR loops.

Added -m option to command line, to select modem type.  ckuus4.c, ckuus2.c.
Thanks to William Bader, Software Consulting Services, Nazareth, PA, for the
suggestion and the code.

Added -v option to command line, to select window size ("v" for "vindow").
Now the only letters left are o, u, and z.  ckuus4.c.  ckuus2.c (help
message).  ckuker.nr and ckuker.mss (documentation for both -m and -v).

Added the built-in function \fcharacter().  It takes a numeric argument, and
returns the corresponding character, for example \fchar(65) is 'A',
\fchar(161) is inverted exclamation mark (in Latin-1).  If you give a negative
number or a number larger than 255, only the low-order 8 bits are used.  Now
you can use Kermit to display special characters on your terminal by giving
the character codes, for example:

  for \%i 160 255 1 { echo \flpad(\%i). [\fchar(\%i)] }

Code in ckuus4.c (just a few lines).  Documentation in ckuker.mss, ckuker.nr.

Added IF BACKGROUND command, true if Kermit (thinks it) is running in the
background.  This lets you have Kermit command files that will work both as
TAKE files and also with "kermit < file":

  DEFINE FATAL ECHO \%1\13, IF BACKGROUND EXIT 1, ELSE STOP
  INPUT 10 login:
  IF FAILURE FATAL {no login prompt}

Commands like STOP and END have no effect when Kermit's commands are being
redirected or piped from standard input, because Kermit just goes on to the
next command, as if it were in interactive command mode.  IF BACKGROUND works
fine in Unix, but depends on the system-dependent module setting the variable
backgrd to zero if running in the foreground and nonzero if running in the
background (see discussion of conint() below).  Not sure if this will be of
any use in VAX/VMS, Amiga DOS, Macintosh, etc.  ckuusr.c.

Filled in the SHOW MODEM and WAIT commands (see below, section on modem
signals).


BACKGROUND OPERATION FIXED (?)

Several important C-Kermit features relating to background operation in Unix
seem to have been broken for quite some time.  For example:

  kermit < foo.cmd &

did not work in the BSD universe if foo.cmd contained a SET LINE command and
then attempted to do file transfer or DIAL/INPUT/OUTPUT/SCRIPT over the device.
This was because ttopen() was being called incorrectly, and was incorrectly
deciding that it was running in remote mode, when it was really running in
local mode.  Furthermore, ttopen's default assumption (taken in the absence of
any reliable tests) was remote, when it should have been local.

Second, some screen messages were appearing during execution of a
redirected-stdin command file in the background.  These are now conditional on
the program's not running in the background.

The following command file, for logging in to a Unix system and sending a file
to it, was executed successfully in the background using "kermit < cmdfile &":

  define fatal echo \%1\13, if background exit 1, else stop
  if background set input echo off
  log transactions
  set line /dev/ttyh8
  pause 2
  output \13
  script login:--login:--login: myuserid ssword: mypassword ~w15$--$--$
  if fail fatal {script failed}
  output kermit -x\13
  input 10 reconnect.
  if fail fatal {failed to start kermit server}
  send test.file
  bye
  echo done.
  if background exit 0	

The same command file works when TAKEn in interactive mode, or when invoked
via -y on the command line.  I think this is the kind of thing that people
have been asking for.  By the way, note (once again) that a redirected-stdin
"command file" cannot have GOTOs in it.  GOTOs work by rewinding the command
file, and stdin cannot be rewound!  This is one reason why the SCRIPT command
remains useful.


PACKET PROTOCOL

Raised the maximum packet size from 4096 to 9024 (the absolute maximum), and
initial packet buffer allocation from 6000 to 9050, for the -DDYNAMIC case.
Reason: Why Not? -- If you really want 9K packets, now you can have them.
Tested sending a file with 9024-character packets.  Worked fine (fast too, but
only because there were no retransmissions).  ckcker.h.

If C-Kermit was sending a file using a window size greater than one, and the
file transfer was interrupted (e.g. by typing 'X' to MS-DOS Kermit), C-Kermit
would fail to send a B packet, and the file transfer would hang until the
receiver timed out.  This is because sdata() in ckcfn2.c sends data packets
ahead of the current packet number.  The protocol module in ckcpro.w is
unaware of anything to do with packet numbers, and so blithely proceeds to
<sseof> state if the interruption flag had been set, but now the two Kermits'
packet numbers are out of sync.  The same thing would happen when the end of
file is reached, but in that case, the sdata() function sets a "drain" flag to
allow the protocol module to "catch up" (see the comments in sdata(), if you
care).  The fix was to move the test for file interruption from ckcpro.w to
sdata() in ckcfns.c; sdata() now sets the drain flag when a file is
interrupted, just like it does when the end of file is reached.

Fixed resend() to log the packet number correctly in the packet log, and to
indicate resent packets with 'S' rather than 's'.  Also, made its error
messages a little more informative (for me, at least -- a weird error code,
plus the packet number and packet index of the offending packet).  This is in
response to persistent reports from Ted Medin that downloads from C-Kermit to
MS-DOS Kermit with window size of 7 fail because "resend error number 12"
(which means that the pointer from the sequence number table into the packet
buffer has been invalidated, which should not happen at all, and probably
happens only because freesbuf() has been called when it shouldn't).  ckcfn3.c.

Looked through C-Kermit to see where freesbuf() was being called, and found
at least one place (in the input() function) where it was being called
incorrectly.  While I was looking at input() I also fixed a few other things.
For one thing, I realized that the situation where ACKs arrive out of order
was not fully handled, so I added code to take care of it.

There are still a couple other possible problem areas, in which C-Kermit might
be a little too strict -- canceling the file transfer with an E packet if
something happens that isn't supposed to.  Joe Doupnik suggests that some of
these situations should be silently tolerated.  If we continue to get reports
of failing windowed transfers, then I can try loosening up a bit in these
remaining areas.

Tried these changes against MS-DOS Kermit 3.02 with 7 window slots, both
sending and receiving, and introducing errors and retransmissions any way
I could think of -- seems pretty solid, but then so did previous versions.


AUTOMATIC PARITY DETECTION

C-Kermit (UNIX version only) now automatically detects and adjusts to the
parity on the other Kermit's packets if (a) C-Kermit's parity is initially
NONE, and (b) the other Kermit's packets have EVEN, ODD, or MARK parity.

ttinl(), the system-dependent packet reading function, was changed to accept
an additional argument, the packet start character.  Now ttinl() can do
complete packet framing, and extraneous interpacket junk (or intentional
padding) is no longer stored in Kermit's incoming packet buffers.  ckutio.c.
rpack() was changed to take advantage of this, and no longer has to search the
buffer for the start-of-packet character.  ckcfn2.c.

Part of ttinl()'s job is to strip parity bits if the user has given a "set
parity" command (for parity other than none).  rpack() assumes that ttinl() is
returning a true packet with no parity bits.  If the user forgets (or does not
know) to "set parity even" (or whatever), then ttinl() will not strip the
parity bits, and rpack() will diagnose a bad checksum, and the transfer will
fail.

Now that ttinl() knows where the start of the packet is, it can check the
packet control fields (which never contain 8-bit data) to determine the
prevailing parity.  This is done only if the parity is set to none, in which
case, ttinl() calls a new function, parchk().  parchk() sees if the packet has
parity, and if so, what kind.  It returns the parity which it has sensed to
ttinl(), which in turn sets the global variable ttprty, which is used by all
the other functions in ckutio.c.  In order for the parity to be changed from
none to even, odd, or mark, ALL of the packet control fields must have the
SAME kind of non-NONE parity, which effectively rules out spurious parity
changing because of line noise.

If C-Kermit is receiving a file, it will see the parity on the S-packet, and
will enable 8th-bit quoting by setting '&' in the EBQ field its reply.  This
ensures that 8-bit data will go through correctly even if the user failed to
set parity on both Kermits (and parity is being added by something between
them).

If C-Kermit is sending a file with parity = none to another Kermit in RECEIVE
mode, then the first packet C-Kermit receives will be the S-packet reply.  By
this time, it is too late to negotiate 8th-bit prefixing if the receiving
Kermit did not request it.  If the file contains no 8-bit data, it will be
transferred correctly.  Otherwise, the checksum will be wrong and Kermit will
catch the error (just as it has always done).

If C-Kermit is sending a file with parity = none to a server, then the first
packet it will receive will be a NAK or the reply to an I packet, in which
case 8th-bit prefixing can be successfully negotiated in the following
S-packet exchange.

Meanwhile back in ckcfn2.c, if rpack(), the system-independent part of the
packet reader (the one that checks the checksum, etc), after calling ttinl(),
notices that the global variable ttprty changed, then it changes Kermit's
parity variable (the one associated with SET PARITY) accordingly, and then
things work OK in the protocol too.  And once the parity has been changed, the
check is no longer made (because parity is no longer NONE), so efficiency is
not badly compromised.

This mechanism kicks in only when Kermit's parity is set to NONE.  If the user
has already SET PARITY to something else, Kermit assumes she knows what
she's doing.

Any additional overhead caused by the parity detection feature seems to be
more than offset by the performance boost that comes from removing the
start-of-packet searching loop from rpack().  In one benchmark, MS-DOS Kermit
3.02 sending a 36K file to C-Kermit using 2000-byte packets and one window,
the efficiency was 83% with edit 149, and 86% with edit 150.

The ttinl() functions for VAX/VMS and other non-Unix versions of C-Kermit
should be changed to accept the packet start character as a fifth argument,
and to return the first argument pointing to the start-of-packet character.

All of the new parity-sensing code is selected by defining the symbol PARSENSE
(parity sense).  I added -DPARSENSE to ckcdeb.h within #ifdef UNIX
conditionals, so all Unix-based versions of Kermit will get it automatically
next time they are recompiled, and non-Unix versions will not.  Non-Unix
versions should define this symbol when they have changed their version of
ttinl() accordingly.

If parity was changed automatically, a message appears in the STATUS display.

Updated ckasys.doc to describe the new features of ttinl().  Thanks to
Christine Gianone for the parity-sensing idea.  (A similar feature has been
added to the MS-DOS Kermit 3.02 beta test as of 15 July 90.)


HANGING UP, DTR, AND GETTY -

Changed -DNEWUUCP to -DACUCNTRL to be more descriptive.

Changed acucntrl("enable",flfnam) to acucntrl("enable",ttname) in ttclos().
All these years it had been called with the lockfile name instead of the tty
device name, which only worked (if it ever did) because acucntrl apparently
contains a hack that scans the second argument for the first '/'.  This change
only affects those who build the program with -DACUCNTRL.  ckutio.c.

Looked up termio(BA_DEV) in SVID for R3.  Found out that there are ioctl's for
controlling modem signals.  I wonder how many systems actually implement
them...  So I added code to tthang() within #ifdef's for TIOCMBIS, TIOCMBIC,
and TIOCM_DTR to turn DTR off and on again.  This code will be used
automatically on System V systems that define these symbols.  However, even if
the symbols are defined, the ioctl might fail; if it does, the close/open path
described below is still taken.  Btw, this code was tested, and worked
correctly, on the SUN-4 with SUNOS 4.1 in both BSD and Sys V R3 environments.
ckutio.c.

Then, in a fit of disgust, I ripped the guts out of the System III/V case in
tthang().  Now it simply (a) gets the modes, (b) sets the speed to zero, (c)
sleeps for about 300 msec, (d) does the close(priv_open(...)) magic, (e)
restores the modes, and (e) returns.  If this doesn't work for you, then add
-DCLSOPN to your makefile CFLAGS, and then step (d) is replaced by the more
drastic (and dangerous) close(ttyfd) followed by priv_open(...); the danger is
here that getty can seize the line during the short time it is closed.  I
don't know if all (or any) gettys honor the lockfile.  Let's hope the second
method won't be necessary.

So, here's how to test the new hangup code on System-V based Unix:

  1. Build it with no special switches.
  2. LOG DEBUG.
  3. Try a HANGUP or DIAL command.
  4. Did it work?  Save all tthang lines from debug log (grep tthang debug.log)
  6. Build it again, but this time with -DCLSOPN.
  7. Try HANGUP or DIAL.
  8. Did it work?  Save all tthang lines from debug log.

Please send me the tthang lines from both debug logs, showing which is which,
and saying which method(s) worked (if any).  Hopefully, either the non-CLSOPN
or else the CLSOPN case will work all the time, and then we can remove the one
that doesn't.

Note: None of this tthang() business applies to BSD, HP-UX, or ATT7300, which
have their own specific hangup methods.  If the edit 150 code STILL does not
work, then another alternative is to do modem-dependent hangup operations if
ttmdm is not 0, like for Hayes: sleep, +++, sleep, ATH0.  Not hard, but it
would mean moving modem-related definitions out of ckudia.c to a common header
file.

Also, while perusing SVID R3, I found the TIOCMGET ioctl documented.  Used the
information there to fill in the ttgmdm() function, so now SHOW MODEM actually
shows you the modem signals, but only if your system supports the TIOCMGET
ioctl and the symbols for each modem line, and the ioctl does not fail.  Also,
I added the modem signal display to SHOW COMMUNICATIONS.  Tested OK on SUN-4
in both System V and BSD environments.

Also added code to ttgmdm() for HPUX.  This is all guesswork, since I don't
have a man page.  HPUX users please test this!

Now that ttgmdm() is filled in, I also filled in the WAIT command, so that
users can give commands like "WAIT 10 CD" (wait 10 seconds for carrier),
"WAIT 4 CD DSR" (wait 4 seconds for carrier and dataset ready), or WAIT 5
(just wait 5 seconds, equivalent to PAUSE 5).  ckuusr.c

Discovered that the function ttwmdm() (wait for modem signals) is not
necessary, since it just calls ttgmdm() in a loop, which is what the
user-level code in ckuus5.c does, so I removed it from ckutio.c.  Every little
bit helps...

Removed the call to tthang() from ttclos().  There is no need for ttclos() to
hang up the phone, because closing the file descriptor will drop DTR just
fine.  Doing a hangup in ttclos() can cause the BSD version of ttres() to fail
because the modes can't be restored by stty() after the device has been hung
up when the hangup causes the other end to stop sending carrier.

On the SUN-4, the BSD-based version will sense carrier drop if I log out from
the remote UNIX and will drop back to the command prompt with the
"Communications Disconnect" message.  The Sys V version does not do this.
Haven't figured out why yet -- could it be that O_NDELAY has been set somehow?
Both versions will drop back to the command prompt with "Communications
Disconnect" if I hang up (Ctrl-\ h) during a session.


THE CASE OF THE DISAPPEARING PROMPT -

Many System V users complained that the C-Kermit> prompt disappeared after any
file transfer operation in edit 149.  This one was subtle.  In edit 149, I
went to a lot of trouble to fix Kermit to be Ctrl-C proof if the user gives
DISABLE BYE/FINISH.  Part of this was changing connoi() (the "console no
interrupts" function) to use SIG_IGN rather than SIG_DFL for SIGINT, and this
did, indeed, make the program Ctrl-C proof while connoi() was in effect.
However, when conint() was called again to restore the regular Ctrl-C traps,
etc, its test for whether the program was running in the background (System V
only) is if SIGINT is set to SIG_IGN, so of course it would go into promptless
"background mode" after any protocol operation because connoi had indeed just
set it to SIG_IGN.  Solution #1: write my own sig_ign() function (note
lowercase), and use it in connoi() in place of SIG_IGN.  Tested ok on SUN-4 in
Sys V R3 environment.  ckutio.c.

While testing the aforementioned changes, I noticed that if I did "wermit &"
and then fg'd it, the prompt would not appear until after I did a protocol
operation, because conint() was never called again until then.  So I put a
call to conint() in the main interactive parsing loop in function parser().
Works fine and seems to do no harm -- Ctrl-C still works right, etc.
ckuus5.c.

I also noticed that if I started the System V version of wermit under the ksh
or csh with "wermit &" to background it, that it would not notice that it was
in the background, whereas "wermit &" under the Bourne shell (&) worked fine.
This is because csh and ksh apparently do not set a background process's
SIGINT to SIG_IGN, but rather leave it as SIG_DFL.

Solution #2: Since the System V method of checking background status is so
likely to fail, it is much better to use the "BSD" method, namely comparing
Kermit's process group with the controlling terminal's process group.  This
depends on the presence of getpgrp() and ioctl(1, TIOCGPGRP, ...).  getpgrp()
is defined for both Sys V R2 (int) and Sys V R3 (pid_t).  TIOCGPGRP is listed
in SVID for R3.  Thus I think it is safe to use the process-group test on any
system where TIOCGPGRP is defined.  I made this change in conint().  Tested ok
on SUNOS 4.1 in System V and BSD environments.  ckutio.c.

Also, while I was rummaging around in connoi(), I noticed that the "bgset"
flag was not used at all, so I removed it.  I wonder what it was for...
ckutio.c.


SHELL AND SYSTEM() -

Removed second, unused, vestigial argument from zshcmd().

Many testers have complained about the use of the user's preferred shell for
running commands like DIRECTORY, SPACE, etc.  This was not done because I
thought it was the right way to do it, but because doing it any other way
would have required adding a new system-dependent function that would have to
be implemented for all C-Kermit variants -- VAX/VMS, Macintosh, Amiga, etc etc
etc -- just because in Unix we sometimes want to use the user's login shell,
and other times want to use /bin/sh (a subtle distinction to users of other
operating systems!).  Well, the outcry has been so overwhelming that I went
ahead and added the new function after all: zsyscmd().  For Unix, it's defined
in ckufio.c.  It does approximately what system() does, except of course it
turns off privileges before execl'ing the command.

In ttopen(), I replaced the call to system() with zsyscmd().  As Kristoffer
pointed out, the arrangement in edit 149 posed a gaping security loophole (I
won't go into detail).  The only bad thing that can happen now is that users
won't see a directory listing of the lockfile in case the requested device is
in use and the lock directory and/or file is read-protected against them.

Some testers have been reporting problems when running C-Kermit in server mode
and sending REMOTE commands to it (REMOTE SPACE, REMOTE HOST sum filename,
etc).  Symptoms include hung server, unwanted appearance of shell prompt, etc.
I hope these problems are fixed now, because of several of the changes in 150.
There is apparently at least still one cause for hung servers: if the program
is built with -DDYNAMIC on the Tandy 6000, the server can hang.  If built with
static allocation for packet buffers, the server won't hang.


VAX/VMS

Thanks to some changes sent in by William Bader, I was able (after adding
zsyscmd() to ckvfio.c, exactly the same as zshcmd() for VMS) to successfully
compile C-Kermit 5A for the first time on my MicroVAX with VMS 5.0 and VAX C
2.something (even though I still get linker errors about "system" and "rename"
multiply defined).  As Mark Buda pointed out when he sent in his last batch of
changes on June 6th, the VMS support is far from ready, the CONNECT code
needs to be worked over, and the RMS file support is not done.

When edit 150 is executed on my VMS 5.0 system, many parts of it actually work:

 - Transfer of text files works in both directions with 1 window slot, using
   either short or long packets (I tested up to 1K packets), except that the
   last record of received files is not saved in the file (and if you send
   another file, then the last record of the previous file becomes the first
   record of the next file, and so on).

 - Character set translation works fine (e.g. sending CP850 German text from
   a PC to a Latin-1 file on the VAX).

 - Basic server mode works: GET, SEND, FINISH, BYE.

 - !, PUSH, and RUN seem to work OK (spawning DCL fork).

 - TAKE, DEFINE, macros, scripts, arithmetic, etc, all work.

 - OPEN WRITE, WRITE, CLOSE WRITE work.

But, as you might expect, there are some rough spots: 

 - If you send a file to VMS Kermit that has the same name as an existing
   file, VMS Kermit refuses to accept it: "Can't transform filename".  This
   happens with the default SET FILE COLLISION BACKUP.  SET FILE COLLISION
   OVERWRITE works just fine, and creates a new generation.  I changed
   ckcmai.c to make this the default for VMS.

 - Sliding windows doesn't work when receiving files, VMS gets data overruns
   ("ttinl: sys$qiow(iosb) %SYSTEM-W-DATAOVERUN").  Sliding windows works fine
   for sending files.

 - The file size attribute is not sent.

 - The server crashes if you send it any REMOTE command that requires
   spawning a fork, like REMOTE DIRECTORY, REMOTE SPACE, etc.

 - Incompletely received files are kept, rather than deleted.

 - REMOTE commands sent to the VMS server seem to crash the program.

 - DIRECTORY doesn't work at all.

 - CD doesn't work at all, even though PWD works ok.

 - The TYPE command does not send CRLFs, only linefeeds, so text file lines
   come out in stairstep form.

 - Speed is reported in cps rather than bps, and percent efficiency
   calculations (STATUS command) are wrong by a factor of 10.

 - Filename completion works, but the display is wrong.  For example, if you
   have a file OOFA.TXT and you type OOF<ESC>, Kermit will fill in
   SK1:[DIRECTORYNAME]OOFA.TXT;1 after the "OOF".  But it still finds the file
   and uses it correctly.

 - OPEN READ, READ, CLOSE READ don't work.

 - Exiting from the program always gives an error message %SYSTEM-F-ABORT.

I didn't test any local-mode operations (SET LINE, DIAL, HANGUP, etc) -- I
don't have an outgoing line from the VAX.


OTHER

Fixed a bug in the command parser.  A command like this:

  IF < \%a 3 ECHO Foo

would produce unexpected results if the variable \%a wasn't defined: the
cursor would shoot back to the prompt as soon as the space after the variable
name was typed.  This was fixed by giving undefined variables when used in
this numeric context the value of zero.

Fixed a bug in GOTO, in which a GOTO could fail if it was issued from a macro
which was invoked before other macros had been defined or deleted, thus
changing the position of macros in the macro table.  Fixed GOTO to work
independently of whether the macro table had changed.

Alistair Gorman in New Zealand reported that file transfer failed on a SUN-4
in local mode.  Examination of the logs he sent showed that he was using even
parity on both ends, so it shouldn't have failed.  Of course, I had tested
this many times locally, also on a SUN-4, and it worked fine, but for the past
month all my local-mode testing had been through SET HOST rather than SET LINE
because my my dialout port cable needed fixing.  So I fixed the cable and
tested this complaint.  Sure enough, it fails.  The symptom is that a
local-mode C-Kermit built in the BSD universe (at least on a SUN) fails to
input ANY CHARACTERS AT ALL while in packet mode when its parity is not NONE.
At first I suspected the new parity sensing code, but Alistair's problem
occurred in edit 149, before that code was installed.  To make a long story
short, the problem was in ttpkt(), where it puts the BSD ttyfd in cooked
rather than raw mode if parity is not NONE (in order that Xon/Xoff can work).
For some unfathomable reason, this works fine in remote mode, and not at all
in local mode.  So I changed ttpkt() to do this only in remote mode.  Symptom
cured, but disease still lurking beneath the surface.  ckutio.c.

Found one place that the new Ctrl-C trap added in edit 149 does not work:
during protocol operations while in local mode, where typing Ctrl-C invariably
causes a memory-fault core dump in Unix, both BSD and Sys V.  Why?  Probably
some other function has executed a setjmp or something and screwed up the
stack or registers.  I don't see an easy way to make Ctrl-C work here (can
you?), so instead, I changed ckcpro.w to call connoi() (console no interrupts)
whenever it starts a protocol operation, rather than only when it does so in
remote mode.

Fixed text-mode (new default) session logging.  Problem was that CONNECT-mode
port input was done in two places, and I only put the text-mode conversion in
one of them.  Not done in the most efficient possible way, can be speeded up
if necessary at the cost of some more memory.  ckucon.c.

Changed default filespec for directory command in UNIX to be "." rather than
"*".  The latter (*) caused listings to be recursive, the former (.) confines
them to the current directory.  If you want a recursive listing, include the
"*" explicitly, as in "directory *".  Note, any directory command that
contains a "*" will be recursive, like "directory x*".  I suppose I could
change "ls -l" to "ls -ld", but I'm not sure if that would be universally
portable.  ckuusr.c.

Changed BSD version of SPACMD to remove "quota".  This is not available on
some systems, and on most others it does nothing anyway.

Change znewn() to validate its data & lengths, added some parens to cut down
on headaches for certain optimizers.  Corrected the problem in which this
function ate into the end of the filename as it added digits to the generation
number.  Until now, C-Kermit has always done: oofa, oofa~1, oofa~2, ...,
oofa~9, oof~10, oof~11, ..., oof~99, oo~100, etc.  Now it leaves the name
intact when it goes to 10, 100, etc.

Fixed a problem in the automatic speed recognition in the Hayes modem section
of the DIAL command.  In "cptr = (*s == c) ? s : NULL;", the c was really
supposed to be 'C' (the first letter of CONNECT).  Thanks to William Bader for
finding "c may be used before set" when running this module through lint, and
also for several other probably less important lint-bits that were also fixed.

Fixed dumpsbuf() to actually show the send-packet buffer in the debug log.
ckcfn3.c.

From Steve Walton: Changed external declaration of parser() in main() from
char to int.  ckcmai.c.  Supplied missing argument to doexit() in ckuusr.c.
Changed declaration of rpar() from char to CHAR in ckcpro.w.  Removed
reference to ttyfd in ckasys.doc (it was already removed from the code).

Added definition for TELOPT_TTYPE to ckucon.c if it was still not defined
after including <arpa/telnet.h>.  This is needed on SGI Iris, Ultrix 2.0,
and maybe some other 4.2-based systems.

Removed -i switch from CFLAGS for trs16, because it conflicts with -n in
LNKFLAGS.  Jay Rouman.  makefile.

Built and ran edit 150 successfully on SUN-4 with SUNOS 4.1 in both BSD and
ATT SVR3 environments, NeXT, and MicroVAX-II with Ultrix 2.0.

------------------------------

5A(149) Sun Jun 24 21:42:09 1990

The description of changes since edit 148 is quite long (about 500 lines)
and is divided into major sections.  I feel like I should put a table of
contents here...

PACKET LENGTHS AND BUFFERS

Changed the packet buffers from static to dynamic allocation, but only
if you put -DDYNAMIC in your CFLAGS.  Here's how it works:

The following symbols are now defined in ckcker.h in such a way that you
can override them by defining them in CFLAGS:

  MAXSP = Maximum send-packet length = 2048.
  MAXRP = Maximum receive-packet length = 2048 for Unix, 1920 for VMS.
  SBSIZ = Total allocation for send-packet buffers (default = 3008)
  RBSIZ = Total allocation for receive-packet buffers (default = 3008)

If you do nothing to your makefile entry, you will get the defaults shown
for these four quantities, and the packet buffers will be ordinary arrays
(6K worth) in your program save image.  This is exactly how C-Kermit 5A has
been configured since the beginning.

Still using static allocation, you can reduce (or increase) the size of the
program image by changing the values of any or all of these symbols in CFLAGS,
for example:

  make foo "CFLAGS = -DBSD4 -DSBSIZ=2000 -DRBSIZ=1247"

  make foo "CFLAGS = -DSVR3 -DMAXSP=500 -DMAXRP=250 -DSBSIZ=2000 -DRBSIZ=1247"

If you include -DDYNAMIC, then the packet buffers will be allocated
dynamically using malloc().  If malloc() fails to allocate buffers of the
requested size, it will try progressively smaller sizes until it succeeds or
the size becomes too small.  See the new function inibufs() in ckcfn3.c.  With
dynamic allocation, the default definitions are:

  MAXSP = 4096 for Unix, 2048 for VMS.
  MAXRP = 4096 for Unix, 1920 for VMS.
  SBSIZ = 6000
  RBSIZ = 6000

So by including just the -DDYNAMIC switch, you get 4K packets, rather than 2K.
Dynamic allocation has been tested on a SUN-4 using 4K maximum packet lengths
and up to 10K buffers, with various combinations of actual packet sizes and
window sizes, and it works fine.  For a direct connection with no delays,
there is no special performance advantage in using 4K packets instead of 2K or
even 1K, but when delays are involved, the longer the packets and the bigger
the window size, the better the performance (see "How Efficient Is Kermit?" in
Kermit News #4).

By the way, these tests were performed SUN-to-SUN over Ethernet, using SET
HOST.  On a serial connection, such long packets might overrun the Unix
kernel's buffers.  If this seems to be happening to you, try SET PARITY EVEN
on both ends to see if it improves matters (this lets Xon/Xoff work during
packet mode).

NEW COMMANDS

Added "SET BUFFER x y" command, to allow users to change the send and receive
buffer sizes from whatever was selected at compile time.  Executes only if the
program was built with -DDYNAMIC, otherwise just prints a message "?Sorry, not
available".  SHOW PROTOCOL now displays the buffer sizes.  I was able to give
numbers as big as five million (yes, SET BUFFERS 5000000 5000000) successfully
on the SUN.  On smaller and/or 16-bit systems, the upper limit is obviously
much smaller.  If you give this command and nothing seems to be happening for
a long time, type Ctrl-C to get the prompt back -- apparently, malloc() can
sometimes become quite preoccupied with itself and never return.

Jay Rouman wanted to have an option to write the session log with CR's
stripped, so I added a command SET SESSION-LOG { TEXT, BINARY }.  TEXT is the
new default, and strips carriage returns, NULs, XONs, and XOFFs.  BINARY
records all incoming characters in the session log.  ckuus3.c, ckucon.c.
Updated manual and man page.


MAKEFILE-RELATED CHANGES

"make ps2aix" tested successfully, changed "?" to "+" in makefile.

Added makefile entry for SUN OS 4.1, which has switched to Honey DanBer UUCP.
"make sunos41" and (for the System V environment) "make sunos4s5h".

Added -DDYNAMIC to "make sunos4" and "make sunos41".  Add this to your
makefile entry too and see if it works.  If so, let me know, and I'll add
it to the master copy of the makefile (except for non-virtual memory systems?).

Made -DDEBUG and -DTLOG the default, and removed these from all makefile
entries.  To build Kermit without debugging or transaction logging, include
-DNODEBUG and/or -DNOTLOG in makefile CFLAGS; this was done for all entries
that previously omitted -DDEBUG or -DTLOG.  ckcdeb.h, makefile.

Cleaned up the #ifdefs in ckutio.c and ckufio.c that determine whether
<sys/file.h> is included.  Added -DNOFILEH to the makefile entries, and simply
included <sys/file.h> unless NOFILEH was defined.  Added a couple special
cases because RTU, CIE, FT18, and BSD41 need to have <sys/file.h> in one of
these modules, but must not have it in the other.  I don't know why.  Does
anyone?  Anyway, from now on, new makefile entries can simply include
-DNOFILEH in CFLAGS if including <sys/file.h> causes trouble, rather than
having to modify the source.  More detail about this in ckuins.doc.

Added many new variations to try for HP-UX and Masscomp RTU.  Hopefully the
number of these can be reduced after testing.


MODEM SIGNALS AND HANGUP

Supplied missing } in ckudia.c, ATT6300 case.

Restored the close() and open() to the ATT7300-specific part of tthang().
Removing it broke everything.  Andy Fyfe.

Kristoffer pointed out that it's a bad idea to call ttclos() from tthang(),
because ttclos() calls tthang()!  So I replaced the call to ttclos() in
tthang() with calls to ttunlck(), ttres(), and close(), along with error
messages so we can see where it gets stuck.  Also, put a 3-second time limit
on the the call to ttopen() so that it won't get stuck waiting for carrier in
case of SET CARRIER ON.  Also, put all references to O_NDELAY within #ifdef
O_NDELAY conditionals.  Added one more close(priv_opn()) to tthang(), just in
case this will make the ioctl and fcntl flags take root before trying the
final big sequence of total close and massive reopen.

I also considered adding code to support O_NONBLOCK for POSIX, but that would
further multiply the number of possibilities and combinations.  As you might
expect, the behavior of O_NONBLOCK is not quite the same as O_NDELAY.  Nobody
has asked for this yet, so I didn't do it.

   All designers of Unix operating systems and "portable Unix" standards
   should be forced to read C-Kermit's tthang() function...  BSD and HP-UX
   are the only ones that even come close to doing it right, i.e. giving
   the programmer direct access to the modem signals, rather than hiding
   them behind thirty-seven layers of undocumented magic and obfuscation.

In ckdial(), added calls to tthang() when the DIAL command times out.  Andy
Fyfe had reported that when he got the "Call did not complete" message, that
the phone line was not hung up, and just kept on ringing.  tthang() is invoked
here only if SET DIAL HANGUP ON (which is the default).  ckudia.c.  Also
reformatted this file a little bit to look more like the other modules.

Jim Barbour complained that upon escaping back from CONNECT, Kermit hung up
the line.  Inspection of the code showed that if you CONNECT and then use
Ctrl-\ h to hangup the phone, the flag "dohangup" was set to 1.  This flag was
examined any time the user escaped back, and so any Ctrl-\ c used subsequent
to any Ctrl-\ h would also hang up the phone.  Added an instruction to reset
dohangup to zero after hanging up to make sure this doesn't repeat.

At Kristoffer's suggestion, in the System-V section of tthang(), activated
O_NDELAY before attempting to set the speed to zero.  This is done in both the
first and second sections.  It probably doesn't hurt, and it should be undone
automatically in the subsequent restoral of modes.


LOCK FILES

In ttlock(), made sure the pid-string was null terminated before attempting
to read it with sscanf().  Also, added "Removing stale lockfile" message.

Changed ttlock() to return -2 if the device is truly locked (in use by another
legitimate process), -1 otherwise (access to lock directory denied, etc).
Changed ttopen() to have the following return codes:

    0 on success
   -5 if device is in use
   -4 if access to device is denied
   -3 if access to lock directory denied
   -2 upon timeout waiting for device to open
   -1 on other error

Changed SET LINE in ckuus3.c to print an appropriate message for each of these
return codes.

For Unix C-Kermit, additional messages are printed by ttlock or ttopen:

   -5 "ls -l" listing of lockfile to show user and time
   -4 message stating reason
   -3 message stating reason (directory does not exist or permission denied)

In the -5 case, we use priv_on(), system(), priv_off() rather than zshcmd() in
order to make sure we can give them the directory listing.  And then we even
try to show them the pid of the process that wrote the lock.

In the -3 case when the directory does not exist, ttlock prints "UUCP not
installed or Kermit misconfigured".  This raises the interesting question:
what does the user do about it?  This happened to me when the SUN-4 I work on
was upgraded from 4.0 to 4.1, and UUCP was not installed.  This completely
prevented me from using Kermit to dial out.  This made me think of the many
users of Unix workstations who do not use uucp, tip, or cu, or even know what
they are.  These people should not be forced to install uucp just in order to
run Kermit.  For this reason, I added a new CFLAGS option: -DNOUUCP.  This is
a reversal of previous "policy".

Why the reversal?  Because (a) anybody can circumvent UUCP lockfile "security"
if they want to without Kermit's help, and (b) part the "spirit of Kermit" is
that users should not have to depend on proprietary packages or privileged
system administrators in order to install or run it.  The only people who
would deliberately use -DNOUUCP for evil purposes could accomplish the same
effect by changing the (freely available) C-Kermit source code, or running an
older version of C-Kermit, or even by writing their own simple little i/o
program.

The explanation of UUCP lockfiles in ckuins.doc has been rewritten to take all
this into account.


SETUID

Added another function to ckutio.c priv package -- real_uid().  This returns
the real uid of the process, which is simply ckutio's static int realuid.
There were several places in ckufio.c that called getuid(), but if these had
been swapped by the priv package on a BSD system without the saved original
setuid feature, then getuid() would return the wrong real uid!  So the
getuid() calls in ckufio.c have been replaced with calls to real_uid().  These
were all in the tilde-expansion code, and would only occur when the user was
referring to herself, as in "send ~/oofa".

I did not replace the call to popen() zxcmd() with yet another a hand-coded
fork(), exec(), etc etc.  If somebody else wants to do this, be my guest.  The
reason why it's needed is that before feeding the command to popen(), we have
to turn off privileges.  But then, for some Unix versions, we can never turn
them back on again, which will be confusing.  This only affects Kermit
programs that are running setuid on versions of Unix that do not save the
original set-user-id, and only after the user uses the OPEN !WRITE or OPEN
!APPEND commands.

Replaced several remaining calls to system() -- in ongetty(), offgetty(), and
acucntrl() in ckutio.c -- with calls to zshcmd().


FORKS

Changed zshcmd() in ckufio.c to check for fork() failure, so it doesn't go
into a loop waiting for a nonexistent fork.

I also removed the output redirection feature from zshcmd(), so now the second
argument to this function is ignored.  Actually this happened a couple edits
ago, because it was interfering with (believe it or not) some work on X.25
network support.  There are other ways to do the same thing (OPEN !READ, READ,
OUTPUT, etc).

People have been reporting very strange behavior since I replaced all calls to
system() by calls to zshcmd() a couple edits ago.  The major difference is
that zshcmd() uses the user's preferred shell, whereas system() always uses
/bin/sh.  Before the change, zshcmd() was used by the "!" (RUN, PUSH) command,
and system() was used execute miscellaneous commands like DIRECTORY (ls -l) and
SPACE (df .), and some protocol-related functions like mailing and printing of
incoming files.  Recall, this change was made so that the processes invoked
by system() would not inherit any privileges from Kermit if Kermit was running
setuid, and still the main process would not have to lose its privileges
permanently.

Several people have reported that issuing commands like SPACE and DIR, which
previously used system(), result in having the shell's prompt show up in
screen listings.  One user reported this happens only in local mode, but not
in remote mode.  I cannot repeat this locally on SUNOS, AIX, or anywhere else
I tried.  The only reason I can guess for this happening is that when an
argument is given, the user's shell is run with -c and the given argument.  If
the user's shell does not happen to understand the -c option, it might issue a
prompt.  sh, csh, and ksh respond uniformly to -c: they don't prompt, they do
the single command, then exit.

What about an interactive shell, with no command line arguments?  In this case
we use the "-i" option, to force interactive mode.  This only happens if the
string pointer to zshcmd is NULL or points to an empty string.  All three
shells (sh, csh, ksh) accept and treat the -i option uniformly.

Many C-Kermit testers have suggested that /bin/sh should be used, rather than
the user's preferred shell, when there are commands, i.e. when the shell is
not to be run interactively.  The cost of not using the user's preferred shell
would be:

   a. Changing how the "!" works, because it has always used the user's
      preferred shell, whether it had arguments or not.

   b. Changing the calling conventions of zshcmd to include an argument to
      specify whether to use the user's preferred shell or the system's
      standard shell (which would make little sense outside of Unix, so why
      inflict it on C-Kermit programmers in other operating systems?).

   c. Adding yet another new system-dependent function that everybody else
      would have to implement (Mac, Amiga, OS/2, VMS, etc etc) but nobody
      would understand.  Groan.  Let's avoid this if we can.

Allister Gorman in New Zealand reported that on his SUN-4, if he invokes an
inferior shell with "!" and then exits from it, he finds himself back in the
shell that invoked Kermit in the first place, with Kermit placed in the
background.  I can't reproduce this one either, not even on a SUN-4.  Maybe
it's the Coriolis effect?  He says that when this happens, Kermit can be fg'd
and continued ok, and that this does not happen if you give an argument to the
shell escape, e.g. "! more file".

Maybe the reason I can't reproduce any of these problems is that I already did
something by accident to fix them.  If they recur, please let me know.


TERMINAL INTERRUPTS

DISABLE FINISH is supposed to let you start a Kermit server that can't be
taken out of server mode by its client: BYE and FINISH commands are simply
ignored.  This is to let you make "kermit -x" be a login shell on a certain
tty, e.g. for dialup Kermit service.

The trick is to make a remote Kermit server with FINISH disabled also ignore
keyboard interrupts (SIGINT, etc).  I tried unsuccessfully to do this before,
but now I think I have it.  First of all, connoi() was setting SIGINT to
SIG_DFL; I changed this to SIG_IGN (ckutio.c).  Second, ttinl() was calling
ttres() when it read two Ctrl-C's in a row; I removed that call (ckutio.c).
Third, proto() was calling conint() instead of connoi(); that's fixed too
(ckcpro.w).  Now it seems like Ctrl-C works fine to interrupt a remote Kermit
in packet mode, and a remote server with FINISH disabled is immune to Ctrl-C's.

Changed the Ctrl-C (sigint) trap in the interactive command parser to return
to the prompt, rather than exit the program by using setjmp and longjmp.
Works at the prompt, works at any point while typing a command, seems to work
ok during execution of (most) commands, interrupts deeply nested take files or
macros OK, works before and after file transfer.  If this feature causes you
problems, add -DNOCCTRAP to CFLAGS in your makefile entry.  FURTHER TESTING
NEEDED!

So far, it causes one problem for me: if I type Ctrl-C while an INPUT command
is in progress (on the SUN-4 at least), I get a core dump.  I think this is
because doinput() calls ttinc() and coninc() with timeout parameters, and when
the alarm goes off inside of these ckutio.c functions, the stack gets screwed
up because of a longjmp within a longjmp???  It seems to be a delayed effect,
because the longjmps within ckutio.c work fine repeatedly, and the Ctrl-C
returns control to the right place, and lots of parser code gets executed
correctly, and then then the program core dumps when the parser calls
ckmkey2().  I can't figure out how to fix this, can you?  ckuus5.c.

As a temporary, but completely unsatisfying, solution to this problem, I
inserted a call connoi() at the beginning of doinput() and to conint() at the
end, meaning that INPUT can't be interrupted with Ctrl-C.  In remote mode
(e.g. when you're testing it with your own terminal) it can't be interrupted
at all.  In local mode, you can interrupt it by typing two carriage returns at
your terminal.  ckuus4.c.


LONG FILENAMES AND WILDCARD EXPANSION

Attempted to "modernize" the directory reading functions of ckufio.c, and
to make them more easily selectable from the makefile via CFLAGS.  This is
a long story...
  
When C-Kermit is given a "*" or "?" in a filename in an interactive command
like SEND, or in server mode when the other Kermit gives a GET command, Kermit
expands the given file specification into a list of all files that match by
reading the directory.  There have been increasing reports that Kermit fails
to do this correctly, and similar reports that it fails to find files that
have long names.  Here are some tests to make sure that Kermit is reading the
directory correctly:

   1. Make a new directory and cd to it.
   2. Create files with the following names (contents don't matter):
        aa, ab, ac, ad, ae, afilewithaveryverylongname.
   3. Start Kermit.
   4. Type SEND ?.  Do you see all the filenames?
   5. Type SEND a<ESC>.  Does it beep?  (It should.)
   6. Type SEND af<ESC>.  Was the long filename completed?

If your answer to any of the questions was no, then you need to change the way
Kermit is built for your file system.  First, a little background...

Back in simpler times, there was only one way to read a directory, which was
used in original Bell Labs Unix, Unix Versions 6 & 7, AT&T System III and V,
and their derivatives (BSD 2.8, 4.0, 4.1, etc):

  #include <sys/dir.h>
  int fd;
  struct direct dir_entry;
  struct direct *dirbuf = &dir_entry;
  fd = open(directoryname); read(fd,dirbuf,sizeof dir_entry); close(fd);

In this model, we read the actual directory entry.  Unix file and directory
names have a maximum length of 14 characters.  Most of Kermit's filename
problems on System-V based systems occur because it is using this model, but
the underlying system has adopted a different one which probably allows for
longer filenames.

In BSD 4.2 (and 2.9), Berkeley changed their file system to allow long file
and directory names, and (perhaps more important) for a variety of directory
structures.  BSD 4.2 supplied new directory-related system calls to hide the
details of the underlying directory structure from the program:

  #include <sys/dir.h>
  DIR *fd, *opendir();
  struct direct *dirbuf;
  fd = opendir(directoryname); dirbuf = readdir(fd); closedir(fd);

For many years, these were the only two ways to read a directory.  This made
Kermit's job easy.  For AT&T-based Unixes (UXIII), Kermit used the first
method, and for Berkeley-based the second (ANYBSD).

But soon, the System-V Unixes became envious of BSD's longer names, and so
vendors like Masscomp and Silicon Graphics began to add long filenames,
creating AT&T Unixes with Berkeley file systems.  Usually, access to the long
filenames is given by means of an alternative header file and/or library, like
<sys/ndir.h>, -lbsd, -lx, -I/usr/include/bsd, etc.

And then, in an apparent effort to provide a single interface to the various
styles of file system, and to allow for remote file systems like RFS and NFS,
AT&T (???) decided in System V Release 2 (or 3?) (see SVID Issue 2 and SVID
3rd Ed) that all directory references should use new portable system (or
library) calls that do not require the programmer to know the format of the
directory entry itself, and to go through a new header file, <dirent.h>, and
that <sys/dir.h> would become obsolete.  POSIX took this one step further, and
does not even allow for the existence of <sys/dir.h> (see IEEE Std 1003.1).
(Historical note: reportedly, the <dirent.h> approach is the result of work by
Doug Gwyn of BRL contributed to the public domain.)

In any case, we now have a WIDE VARIETY of ways in which to read directories.
The variables seem to be:

  1. The directory header file:  <sys/dir.h>, <dir.h>, <ndir.h>, <sys/ndir.h>,
     "/usr/lib/bsd/ndir.h", <dirent.h>, ...

  2. Whether to use open()/read()/close() or opendir()/readdir()/closedir().

  3. If using opendir()/readdir()/closedir(), how to declare them (struct
     direct or struct dirent).

So here's the new arrangement for C-Kermit.  First we have system-specific
#ifdefs at the top of ckufio.c (and ckutio.c) to decide which header file to
include: if some special symbol like NDIR or XNDIR is defined, we use the
associated file, like <sys/ndir.h>.  Otherwise, if DIRENT is defined, we use
<dirent.h>.  In all other cases we use <sys/dir.h>.

  NOTE: Why do we even bother with this in ckutio.c???  Because we want
  to find out if MAXNAMLEN is defined, and thereby automatically determine 
  whether we have a pre-4.2 version of Berkeley UNIX.  At this point, it
  might be safe to remove this "intelligence" from ckutio.c, and rely on
  makefile CFLAGS.

The actual directory reading is confined to the traverse() function in
ckufio.c.  Here we define a symbol LONGFN if BSD42 or BSD29 are defined.  For
other systems that are not compiled with BSD42 or BSD29 defined, you can add
-DLONGFN to CFLAGS in the makefile entry to enable BSD-style directory reading
(making sure that you have included the appropriate header file for this).

Then we take care of the declarations.  For DIRENT, we use the well-defined
standard declarations for opendir(), etc.  When DIRENT is not defined, we
have two cases: the old BSD case, which we select if LONGFN is defined, and
the old Bell/AT&T case, which we select otherwise.

Both the DIRENT and the LONGFN-non-DIRENT cases use opendir(), etc, rather
than open().  In these cases we define the symbol OPENDIR.

Finally, we handle the actual opening, reading, and closing of the directory.
This is much simplified.  If OPENDIR is defined, we use opendir(), readdir(),
and closedir(), otherwise we use open(), read(), and close().

So here are the new guidelines for constructing a makefile entry:

1. If your system has /usr/include/dirent.h, then you should add
   -DDIRENT to your makefile entry!  Otherwise:

2. If you have a System-V based system that uses long filenames, or has in
   any other way a non-vanilla-original Unix directory format:

   a. Read your system manuals about directory (long filename?) support.
   b. If the relevant header file is not <sys/dir.h>, include one of the
      following switches:

        Header file     CFLAGS switch
         <ndir.h>        -DNDIR   
         <sys/ndir.h>    -DXNDIR  
         other...        You'll have to invent a new one.

   c. Add any special libraries (like "LIBS = -lbsd") to your makefile entry.

   d. Add -DLONGFN to CFLAGS in your makefile entry.

3. Otherwise, do nothing.  Kermit should pick the right options automatically.

Thanks to Bo Kullmar for many of the basic ideas here, and to Andy Fyfe and
David MacKenzie and others for much useful information.  I think/hope a lot of
problems will be solved by adding -DDIRENT to makefile entries...

Tested this stuff on SUNOS 4.1 and IBM AIX/370 (both with -DDIRENT), works
fine.  Tested without -DDIRENT on on SUNOS 4.1 System V environment, and it
compiles & loads ok, but can't find long files; tested with -DDIRENT in the
same environment, and it can find long files.  Tested on Encore 4.3BSD without
-DDIRENT, also works fine.  Still needs testing on Xenix, AT&T systems that
don't have <dirent.h>, etc, and on the special-case systems like RTU and Iris,
and most of all, on HP-UX; there are now several makefile entries for HP-UX:

  hpux:     <dir.h>, open(), read(), close().  Pre-6.2 versions of HP-UX?
  hpuxlf:   <ndir.h>, opendir(), readdir(), etc (BSD style)
  hpuxde:   <dirent.h>, opendir(), etc. (POSIX style)
  hpuxs5r3: Like hpuxde, but also uses Sys V R3 signal() type (void, not int)

All four may be necessary.  Reportedly, hpuxlf is needed for the Series 300.
It's not clear if these are strictly related to the release number of HP-UX,
or if long filename support is an "unbundled option" that may be present on
some HP-UX systems and absent on others.  Feedback needed.


MISCELLANEOUS

Ted Medin sent packet logs showing C-Kermit failing to send files to MS-DOS
Kermit with window size 7.  MS-DOS Kermit got a checksum error, sent a NAK,
and C-Kermit claimed the NAK was not in the current window and gave up.  I
looked at the code for hours, comparing it with the logs, and could not find
any way this could happen (even though it did).  Found one case in input()
where a variable, x, could be used before being set, which could have resulted
in a spurious termination of a file transfer (but probably not with a "NAK out
of window" message) and fixed that.  ckcfn2.c.

Fixed two calls to logpkt() in ckcfn2.c, which had quotes misplaced around the
arguments, causing a core dump if these calls were ever executed.  Changed
calling convention to logpkt so caller specifies whether it is a sent (s) or a
received (r) packet.  In the previous edit, all logged packets were marked
with 's-'.

Changed all declarations of ttname[] and filname[] to be char rather than
CHAR, to avoid complaints from compilers about incompatible pointer types in
strcpy(), etc.  Many modules.  In other strcpy()'s, put explicit casts on
literal strings to avoid complaints.  Many other minor lintish corrections.

In the lower fork of the CONNECT command, in which it sends a signal to its
parent, asking to be killed, and then pause()'ing, changed these pause()'s
to "for (;;) pause();" in case some harmless signal causes pause() to return
unexpectedly.  Currently this code is used only in telnet connections.

------------------------------

5A(148) Fri Jun 15 16:45:14 1990

Bo Kullmar found some problems with zoutdump() in ckufio.c.  I made the test
for success more stringent, namely that write() must write exactly the number
of characters it is told to write.  Previously if, for some reason (like a
disk filling up) it wrote less than asked, it would still reset the buffer
count and pointer, which would lead to gaps in the output file.  To compound
the situation, a set of parentheses was missing!  In addition, Bo says that
using ferror() to determine if there was an error did not work in Sys V R2 and
earlier.  (Actually, it never did, and could never, work with write() -- it
was left there as an artifact from an earlier release when frwrite() was used
instead of write().)

Bo also said that when collecting logs, in particular the debug log, that
disk-full errors were not handled correctly.  So I made sure that zchout,
zsout, zsoutl, and zsoutx all caught and returned errors, and made all calls
to them check the return code.  In ckcfn2, I collapsed a lot of redundant code
into a new logpkt() function.  Added checks to all zsout*()'s in dump[rs]buf()
for the debug log in ckcfn3.c.  Added checks to all zsout*()'s and zchout()'s
for session logging in ckucon.c, and ckuscr.c.  Added checks to all zsout*()'s
in debug() and tlog() in ckuus3.c.  etc etc...

While I was at it, I removed the debug() calls from ttinc() and ttoc(), since
they tended to make the debug log HUGE during CONNECT.

Jay Rouman said that on the Tandy 6000, CONNECT mode is a lot slower in 147
than in 146 & earlier edits.  I guess it wasn't such a great idea to get read
of the block-mode reads after all.  I fixed it so that the block reads are
executed on all non-network systems (no -DNETCONN), and on network systems
except during a telnet session.

Andy Fyfe noticed that removing the -DUXIII from the Unix PC make entry
caused problems in ckutio.c, because there are some #ifdefs before ckcdeb.h
is included.  I moved the #include to before the #ifdefs & compiled for BSD
and ATT.  Seems OK.

------------------------------

5A(147) Thu Jun 14 23:48:05 1990

Some of you might wonder why I write such verbose notes about each edit.  It's
because if I have to describe what I've done, I usually realize that what I'm
trying to describe is a crock, and so I wind up doing it over again.  I think
this must have happened with each of the major topics listed below in this
edit...

FILE SYSTEM

Learned from Bertil Stenstroem at Stockholm University Computer Centre (QZ) in
Sweden that HP-UX 7.0 is a System V Unix with a BSD file system, that uses
<ndir.h> rather than <sys/dir.h>.  Added a makefile entry "make hpux7" that
includes the -DNDIR and -DBSD4FILE options, and changed the code in ckufio.c
to do the right thing (I hope) if -DNDIR is included.  I thought I did this
before, but the code was missing.  The hpux7 entry assumes a basis of System V
R2 or earlier.  If it's really System V R3 or later, then we need to change it
to include -DSVR3.

Bjorn Carlsson, also of QZ, pointed out that BSD4FILE was not implemented
correctly.  Originally, it applied to the whole ckufio.c file, turning a
normally AT&T version into a BSD version not just for the file system, but
also for anything else that happened to be in ckufio.c, causing all sorts of
problems, like trying to use nonexistent things like seteuid, struct timeb,
etc.  So I changed ckufio.c to only make BSD4FILE effective around the
directory-traversing functions splitpath(), fgen(), traverse(), addresult(),
iswild(), and match().

Needs testing on HPUX 7.0 (make hpux7) and Silicon Graphics Iris (make iris).
This might possibly be the solution to the problems on the MIPS machines too.
Corrections from Sweden (as always) are welcome and expected!  Anywhere else
too...

COMPILATION SWITCHES

Decided that it was dumb to require makefile entries to contain compilation
switches to denote features or systems that could always be inferred from
other compilation switches, for example SVR3 and UXIII.  So I added the
following inferences to ckcdeb.h, since all C-Kermit files that might need
these version dependent symbols #include "ckcdeb.h":

  SUNS4S5 => SVR3
  ( SVR3, AUX, XENIX, ATT7300, ATT6300, HPUX, ISIII ) => UXIII
  ( BSD41, BSD43, SUNOS4 ) => BSD4

I also added the following two rules.  ANYBSD is a useful symbol, but
previously was defined only in cku[tf]io.c.  UNIX is new, it means any
version of UNIX.

  ( BSD4, BSD29 ) => ANYBSD
  ( ANYBSD, UXIII ) => UNIX

These symbols should allow us to remove a lot of duplicated #ifdef code.
The new rules are all of the form:

  #ifdef XXX
  #ifndef YYY
  #define YYY
  #endif /* YYY */
  #endif /* XXX */

so that no harm should be done if the redundant switch is left in the makefile
entry.  In the case of UNIX, it is not redefined if it is already defined by
the compiler.  Of course, this could be done more elegantly with macros, but
that would not be portable.  Meanwhile, I removed all the inferable switches
from the makefile.  Tested OK on the SUN.

MODEM SIGNALS

At Kristoffer's suggestion, changed the call to carrctl() in ttvt() to omit
the term "&& flow == CONNECT".  The idea is that we're always connecting (or
simulating a connect when dialing or running INPUT and OUTPUT commands) when
we call ttvt(), but when ttvt() was called with a "real" flow parameter,
rather than CONNECT or DIALING, the call to carrctl() was incorrect.
Note for the future: the overloading of the flow parameter with states like
DIALING and CONNECT was a bad idea.  The modem/line state should be separated
into a distinct parameter.

This one was my idea...  I rewrote tthang() (again!) for AT&T-based Unixes.
Now, for all UXIII versions except HP-UX (which provides system calls to
lower and raise DTR explicitly), the new tthang() does the following:

  1. save speed, flags, etc.
  2. set speed to zero.
  3. restore speed (etc) using ioctl and flags with fcntl.
  4. read speed using ioctl.
  5. if it's the same as the original speed in (1), done, return 0.
  6. close the device and open it again.
  7. restore speed using ioctl and flags using fcntl.
  8. read speed again using ioctl.
  9. if it's the same as the original speed in (1), return 0.
 10. "major reset": ttclos(), ttopen(), ttvt() or ttpkt().
 11. read speed yet again using ioctl.
 12. if it's the same as the original speed in (1), done, return 0.
 13. nothing worked, return -1.

I kept the previous version of tthang() in ckutio.c, within #ifdef OLDTTHANG
conditionals (the new version is in the #else part).  I compiled under both
the BSD and AT&T environments on the SUN-4, and ran it.  It works ok for me,
but then I have had a problem with hanging up.

-DCLOSEOPEN and -DCLSOPN2 are no longer used -- it's all done at runtime.

TESTING NEEDED!  If tthang() goes past step 5, diagnostic messages will appear
on your screen letting you know what's happening, so you'll know how far
Kermit had to go in order to hang up your device.  These are printed by a
macro, TTPRINT, which for now is defined as printf, but after the testing
period can be dummied out.  This part is untested because I can't make it
happen on any of my systems.

UUCP LOCKFILE

Corrected ttlock() to set haslock correctly to nonzero if a lockfile was
created, and to zero if it wasn't.  About 10 people noticed this mistake right
away.  Now lockfiles should no longer be left behind.  This depends on link()
returning 0 when successful and nonzero when it fails.  Let's hope all Unixes
and C's follow this convention.  All the ones I have access to do.  Also,
removed a diagnostic printf that was mistakenly left in.  ckutio.c.

Added display of the lockfile name to SHOW [ COMMUNICATIONS ] (for UNIX only,
first use of #ifdef UNIX).  ckuus4.c.

Changed ttopen() to return -3 if it can't create the lockfile, so that SET
LINE can print a more intelligent message if this happens.  Also, commented
out the "exclusive access" code based on TIOCEXCL from ttopen() and ttclose()
-- it never did anything except produce annoying error messages.  Like it or
not, we have to use lockfiles for exclusive access in Unix.  ckutio.c.

Added code to ttlock() to deal with stale lockfiles.  If it fails to create
the lockfile because a lockfile already exists, it reads the pid from the
lockfile and if the read is successful, it checks to see if their is still a
valid process with that id and if not, it removes the lockfile and creates its
own.  Suggested by Kristoffer.  Tested with integer pids, not tested with HDB
string pids.  Somebody please test this!  ckutio.c.

Kristoffer pointed out that if the lockfiles are protected against ordinary
users, then most likely the tty devices will be too.  Therefore, every open()
of a tty device should have priv_on/off() around it.  At his suggestion, added
a new routine, priv_opn(), for this purpose, and changed all tty-device
open() calls to priv_opn().  ckutio.c.

SETUID

At Kristoffer's suggestion (I should just abbreviate this, AKS...) I defined
a symbol SETREUID automatically for all versions based on BSD 4.2 and above.
Then I put the priv_off() "safety feature" mentioned in the previous edit
within SETREUID conditionals to prevent infinite loops of priv_off() and
priv_can() calling each other in the non-SETREUID case.  Also (AKS) simplified
the definition of switchuid and switchgid based on the new symbol SETREUID,
and changed ANYBSD in priv_can() to SETREUID.

Kristoffer also suggested that my "safety feature" was less than optimal,
because if it ever takes effect, that means that priv_on() will NEVER work.
Instead, priv_can() should be called only (a) from a created fork, so that it
only effects its own process rather than the main Kermit process, or (b) when
there is absolutely no other choice.  Here's how I handled this situation:

1. I installed calls to priv_can in any fork that Kermit creates.  That
includes the CONNECT fork in ckucon.c, and the zxcmd() and zshcmd() functions
in ckufio.c.

2. I created a new routine, priv_chk(), which calls priv_off() and then checks
to see if if the real uid is the priv'd id -- which will be the case if we are
using setre[ug]id() to swap real and effective uids -- and if so, to call
priv_can to permanently cancel privs.

3. I replaced all Unix calls to system() to calls to zshcmd() (which cancels
privs, but only in the child fork).  For non-Unix versions, I call priv_chk()
before calling system().  NOTE: Kristoffer suggests that zshcmd might need
some things done to it before it can be a totally adequate system()
replacement, but I don't know what those things are.  All the former system()
functions seem to work OK: SPACE, DIRECTORY, etc.

4. I called priv_chk() before calling popen().

xsystem() is a new macro that is used in ckuusr.c, where there were many calls
to system():  #define xsystem(cmd) zshcmd(cmd,0)

By taking this approach, I think I have isolated all the non-Unix Kermits from
having to know anything about the priv_*() functions.

TELNET (SET HOST)

At Jack Bryans' suggestion, in netopen(), changed:

    if (connect(ttyfd, (caddr_t)&saddr, sizeof(saddr)) < 0) {
to:
    if (connect(ttyfd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) {

because the former caused complaints from the compiler on the NeXT, and
because it seemed wrong judging from the man page on connect() and the
definition of sockaddr and sockaddr_in in the header files.  Also, a peek at
the telnet source shows that Jack's way agrees with telnet.  Jack compared the
changed binary with the unchanged one on the NeXT and they were identical.  I
did the same on the SUN, and they were also identical, and the resulting
program does SET HOST and CONNECT (telnet) just fine.  ckutio.c.

Added code to make sure that if the user somehow manages to type an IAC
character (0xFF) during a telnet connection, that Kermit sends two of them.
ckucon.c.

Put a lot of work into conect() to support telnet negotiation options.  Moved
the code that sends the initial option string from netopen() in ckutio.c to
ckucon.c.  Put all telnet-protocol-related functions into ckucon.c, and made
them all start with "tn_": tn_ini() (send initial options), tn_sopt() (send
options), tn_doop() (do options), tn_sttype() (send terminal type).

Determined that if the remote host refuses to "Suppress Go Ahead" (WONT SGA),
that Kermit should (a) turn on local echo (duplex = 1) and (b) transmit LF (or
perhaps CRLF) whenever the user types CR (it does not seem to be necessary to
actually deal with GA's at all).  Kermit now handles these negotiations (and
subnegotiations) just fine.  The structure of the CONNECT command is an upper
fork that reads keystrokes and sends them, and a lower fork reads port input
and prints it -- it's the lower fork that must handle the telnet negotiations,
but it's the upper fork that must must act on them, and the two forks don't
share memory so we can't simply set variables in response to telnet
negotiations.  The only portable way I could think of to have the lower fork
tell the upper fork to change its duplex is for the lower fork to kill itself
with a user-defined signal, SIGUSR2, sent to the parent (SIGUSR1 is already
used for communications disconnect).  When this happens, the parent fork
toggles the value of "duplex" and starts a new child fork with the new value.
It's not clear to me how to extend this mechanism to more than one parameter.

Tested all this against the 4.3BSD telnetd (full duplex) on both SUN and
Encore, 4.2BSD telnetd (full duplex) on a VAX, and the IBM TCP/IP VM Telnet
daemon on a 4381 mainframe (half duplex).  Seems to work OK in all cases.
Current strategy is: Kermit refuses to echo (WONT ECHO) unless it gets WONT
ECHO or WONT SUPPRESS SGA from the telnet server.

To see the telnet negotiations interpreted, SET DEBUG SESSION before
connecting.  What Kermit sends is in [square brackets], what Kermit receives
is in <angle brackets>.  The actual raw negotiation characters are recorded in
the session log if you LOG SESSION.

Fixed a bug, discovered by Marcello Frutig in Brazil (who is adding SunLink
X.25 support).  If your network connection drops (e.g. because you log out
from the remote host) and then you CONNECT again, the program bombs.  The fix
is to make conect() in ckucon.c close the device if there is an error, but
only if it's a network device.

One useful by-product of the telnet work is that ckutio.c now contains a new
variable that can be accessed by other modules: ttnproto (network protocol in
use on the currently selected network).  So far, the only valid network type
is TCP/IP (BSD Sockets), and the only valid protocol is Telnet, but symbols
for some others have been added.  This will let future code distinguish
between, say, CTERM and LAT on a DECnet connection.  Added mention of ttnproto
to ckasys.doc.

Another useful (re)discovery was that there was code in the CONNECT command
fork that reads blocks of data from the communication device in order to
reduce single-character read() system calls.  That code was removed, because
(a) ttinc() now does its own buffering using myread(), and (b) when this code
reads a chunk of data it misses any telnet negotiations that happened to be in
it.

Compiled the program without -DNETCONN just to make sure none of today's work
interfered with systems that don't include network support.  It compiled and
ran OK.  The non-network version is 8K smaller on the SUN.

MISCELLANEOUS

Changed the DIAL command to allow any dial string that was not null, for
example "dial /" (in case the modem accepts / as a redial command).  Suggested
by Peter Mauzey.  ckuusr.c.

Reduced the number of dots per line in local-mode file transfer display by one
to prevent wrapping (again).  Peter Mauzey.  ckuus3.c.

Put the ATT6300 "if (debug) { if (didWeGet(...) ... }" code within
#ifdef DEBUG to prevent compilation errors without -DDEBUG.  Also added
sleep(3) to the debug case to avoid a carrier-loss error, just like the
ANSWERED case, because the DTDM apparently blinks carrier after giving its
ANSWERED message.

Added -O back to "make ATT6300" CFLAGS in makefile entry.  Compiler
automatically ignores -O on a per-module basis if it runs out of space, etc.
Peter Mauzey.

------------------------------

5A(146) Sun Jun 10 14:48:53 1990

SETUID DAY:

Over the years, as C-Kermit has had more and more features added to it --
not just reading and creating transferred files, but reading command files,
starting forks, executing system commands, reading and writing files from
command level, etc etc -- it has become increasingly difficult to manage the
code in light of the fact that in Unix, the program must be run setuid'd to
uucp (or daemon, or similar) in order to access the uucp lockfile.  As
features were added, the setuid people would put code around each feature to
change to the real user id (uid) and/or group id (gid), access the desired
system resource (file, fork, etc), and then put the id back to the original
effective one.  Basically, the program ran in privileged mode all the time,
except for brief moments (like file opening) where privs were turned off.
There are fundamental problems with this approach:

  1. It doesn't work at all on most BSD systems (explained below).

  2. It requires EXTREMELY CAREFUL programming, remembering to put the
     id-switching code around every item in the entire program that could
     conceivably give the user access to normally inaccessible resources.

  3. id-switching methods are not portable among Unix implementations, so
     each instance of (2) was a spaghetti of #ifdef's.

Kristoffer Eriksson sensibly suggested that we reverse things so that Kermit
runs unprivileged all the time except for the two brief moments when it might
need privileges, namely the creation and deletion of the uucp lockfile.  He
contributed a compact and consistent package of functions that could be called
from anywhere to turn privileges on and off.  After some scrutiny and
modifications by various people (notably Dean Long) in the BSD world, this
package is ready to install.  Anybody who intends to run C-Kermit setuid or
setgid should read this whole story.

Added descriptions of the new functions -- priv_ini(), priv_on(), priv_off(),
and priv_can() -- to ckasys.doc.

Removed all setuid-related code from ckufio.c -- about 2K of text!

Removed all setuid code from ckutio.c, and installed Kristoffer's setuid
package.  Installed later changes from Kristoffer sent in e-mail of 31 May,
in which many confusing #ifdefs were replaced by a couple elegant macros.
To handle the case where Kermit is being built in the BSD environment, but
setre[ug]id() is not supplied, I added a -NOSETREU option for makefile use,
which, if elected, results in using setuid() and setgid() instead (there might
be some better way?)

Put a call to priv_ini() in sysinit(), and put calls to priv_on() and
priv_off() around lockfile manipulations in ttlock() and ttunlck().  Changed
the access() call that checks write access to lockfile in look4lk() to be
executed only if the program is not running setuid.  (But all this was changed
later, see below.)

Changed priv_off() to plug a loophole pointed out by Dean Long: if it turns
out that privileges were turned off by swapping the real and effective uids
(gids) using setre[ug]id() in BSD, then an opportunistic user could fork from
Kermit (like with ! or PUSH), swap the ids back again, and get privileges.  So
in priv_off(), after doing the id-setting calls, I check to see if the real
uid is the priv'd uid, and if so, I call priv_can() to cancel all privileges
permanently.  This way, we don't have to rely on users to build the program
with the right compile options.  Of course, this defeats the purpose of this
part of our general-purpose privilege handling package, but there's no choice.
This change should not interfere with System V or BSD saved-setuid operation.

There are no calls to priv_ini(), priv_on(), priv_off(), or priv_can() in any
module except ckutio.c.  The entire setuid business is now totally isolated to
this one system-dependent module.

The new code should work for all System V implementations, and for those BSD
implementations that support the saved-original-effective-user-id feature.  It
will NOT work for other BSD implementations, but then it never did, and no
code can!  This is because BSD does not allow a setuid program, once it has
changed its effective uid to be its real uid, to get the original effective
uid back unless the BSD implementation supports the saved-setuid feature in
the kernel.  (In fact, it would be possible to make things work right for BSD,
V7, or any other Unix version by creating a priv'd fork at startup time,
opening a pipe to it, then turning off privs in the main fork permanently, and
feeding commands to the priv'd fork when privs are required.  If anybody feels
motivated to try this approach, be my guest!  And then prove it's secure!)

The result is that a setuid'd Kermit should work just as it did before, but
with the following advantages:

  1. There is no longer any need to put uid-related system calls around
     ordinary file accesses or process creation.  The programmer can treat
     Kermit just as though it will never run setuid.

  2. Both user and group ids are supported consistently throughout.  Kermit
     can run setuid and/or setgid to uucp or any other user except root.
     Kermit will no longer create files that have the improper user or group
     id, and it will no longer give or deny improper file access to users who
     are running a setuid'd Kermit.

In BSD, the saved-setuid feature is available only when the setreuid() and
setregid() functions are available.  Unfortunately, there is no way to
determine automatically at compile-time whether this is so.  And to complicate
matters, the availability of setre[ug]id() does not guarantee the availability
of the saved-setuid feature (setre[ud]id() are necessary but not sufficient).

If the saved-setuid feature is available, you have to include -DSAVEDUID in
your makefile entry in order to have Kermit use it (BSD variations of Kermit
only, AT&T versions don't need this compiler option because they all have the
feature).  If you include this option, but your system does not have the
saved-setuid feature, then the safety feature of priv_off() should catch the
problem and compensate automatically.

Since there is no way to determine at compile time whether the setre[ug]id()
functions are available, or what they do, you might have to make several
passes.  To simplify matters, there is a small test program, ckuuid.c.  Get
that program, follow the instructions in the comments, and note the results.

Here's the drill for BSD (AT&T versions are built normally, as before).

  1. Build C-Kermit for your system in the normal way.

  2. If the linker complains about undefined symbols _setreuid or _setregid,
     add -DNOSETREU to your makefile entry and try again.  This makes Kermit
     use setuid() and setgid() instead.

  3. If your system has setreuid() and setregid(), you can tell whether it
     supports the saved-setuid feature by using the ckuuid test program on
     your system.  If it shows that the effective (priv'd) uid can be turned
     off and back on and off again, then you have this feature, and you should
     add -DSAVEDUID to your makefile entry.

SUNOS 4.x supports the saved-uid feature, so I added -DSAVEDUID to the sunos4
entry in the makefile.

Need I say... CAREFUL TESTING IS REQUIRED!

Wrote ckuins.doc, installation notes for C-Kermit 5A / Unix.  This is to
supplement what's in the makefile, and mainly explains some of the available
compile and link time options.

Updated ckuker.mss, .doc, and .ps (the user manual), ckaaaa.hlp (the road map
to the C-Kermit files), ckuker.bwr (the beware file), ckuker.ann (the draft
announcement).

Totally rewrote ttlock(), and removed Herm Fisher's old look4lk() function.
The new version is, I hope, much clearer and it removes some windows of
vulnerability that were pointed out by Warren Tucker, Dave Slate, and others.
The way ttlock used to work, it would (1) compute what the lockfile name
should be; (2) check to see if a file of that name already exists; (3) if not,
create the file; (4) write the pid into the file; (5) close the file.  This
left open the possibility that Kermit would find no lock in (2), but then some
other process creates the lock before Kermit could do (3), then in (4) Kermit
creates its own lock, destroying the other.  And creating the lockfile and
then writing the pid to it left open the possibility that another process
would see the just-created lock file, find no pid there, diagnose it as
invalid, and remove it before Kermit could write the pid.  Furthermore, the
old ttlock() and look4lk() were full of access() calls which were meaningless
when the program was setuid.  The new ttlock is a single function which (1)
computes the lockfile name and a unique temporary filename based on Kermit's
pid; (2) turns on privileges; (3) creates the temporary file in the lock
directory, failing if it can't (and, of course, turning off privs); (4) writes
its own pid into the lockfile in the appropriate format; (5) creates a link
from the real lockfile name to the temporary file - if a lockfile of this name
already exists, the link will fail; (6) unlinks the temporary file, leaving
the lockfile in place if (5) succeeded, and removing the temp file completely
if (5) failed; (7) turns off privileges; (8) if (5) failed, prints an
informative message showing the lockfile and its owner; (9) returns.  This
code was moderately tested on the Sun-4 and seems to work as it should.
Obviously, FURTHER TESTING IS NEEDED!

------------------------------

5A(145) Sat Jun 9 16:27:52 1990

Added support for AT&T Information Systems Network (ISN) dialing from John
Chmielewski of AT&T.  ckudia.c.

Checked a report from Dan Senderowicz that piping text into Kermit as commands
or running Kermit from redirected stdin didn't work.  I guess I must have
fixed this, because the examples he gave work now.

Bruce Wong of AT&T pointed out that "kermit -f" and "kermit -g" are not
allowed in remote mode.  I removed this restriction.  ckuus4.c.

Bo Kullmar pointed out that if the program was started with the -q (quiet)
option, then it left the terminal modes messed up upon exit.  It seems that
the exit code specifically did not restore the terminal if the quiet flag was
set, for reasons lost in antiquity.  I removed the test, let's see who
complains now.  ckuus4.c.

Marcello Frutig at the Catholic University of Rio de Janeiro noticed a bug
that has been in C-Kermit for years.  If C-Kermit sends an I-packet to a
Kermit server that does not understand I-packets (such as MTS Kermit), and
which responds with an E packet, C-Kermit does not recover as intended, but
rather keeps sending the I-packet.  I'm not sure what was wrong with 4F and
earlier, but the problem in 5A was that when input() goes to read the next
packet, which is packet 0 just like the previous packet, it sees packet 0
already in its receive buffer, and so returns it; packet 0 is, of course, the
error packet we just got.  Solution: (1) input() should not do "read ahead"
unless more than one window slot is in use (ckcfn2.c); (2) the protocol state
table for <ipkt>E has to delete the error packet buffer before going on to the
next state.  In theory, (1) should be sufficient, but then buffer allocation
gets messed up and we get an "internal error".

SET HOST <name> followed by SET LINE did not work.  Now fixed, and also
improved to restore any previously set modem type.  ckuus3.c.

Discovered something that should have been obvious: because SET FILE COLLISION
BACKUP is now the default, a file that arrives having the same name as an
existing file causes the existing file to be renamed to name~n.  But if the
existing file is a directory, the renaming fails (as it should).  Remember to
warn users about this in the documentation, or maybe change the program to do
something nicer.

Back in April, Bo Kullmar sent in a script program similar to this:

  def foo set host bar, if fail goto :bad, inp 10 ogin:, if fail go :bad, ...

He said it went into an infinite loop.  He's right.  If he hadn't included the
colon in the GOTO command label, it would have worked right.  Fixed GOTO
within a macro to find the label only if it occurs at the beginning of a line.
It already worked right for GOTOs and labels in TAKE files.

Fixed xxstring() to allow expansion of \%0..9 variables when they are global,
i.e. declared at top level.

The DISABLE command wasn't totally working -- many of the pieces had not been
filled in.  Filled them in.  However, I can't seem to totally prevent people
from Ctrl-C'ing out of the server.  It catches the first two Ctrl-C's OK,
but then wedges, then quits.  ckcpro.w.  

Added a new function to ckufio.c, which will have to be added to all other
ck?fio.c's: zstrip(name,&name2).  Given a file specification "name" in local
format, this function returns a pointer to the filename with all device and
directory portions stripped.

Changed openo() and openi() to check if the program is running in server mode
with CWD disabled, and if so, to call zstrip() on any filenames to see if a
pathname was included, and if so to fail to open the file.  ckcfn3.c.

Changed server to respond "Access denied" if a REMOTE DIRECTORY request comes
in which contains a pathname and CWD is disabled.  Ditto for REMOTE TYPE,
REMOTE DELETE.  Access is also denied to REMOTE SPACE if an argument is given.

Updated the manual, ckuker.mss, to reflect the new security features, and to
discuss SET LINE, SET CARRIER, and SET DIAL HANGUP a little better.

Finished following Kristoffer's advice given below in edit 144: make sure that
ttvt() is executed if ttcarr has changed since last time.  The change that was
made in 144 fixed some of Peter Mauzey's dialing problems, maybe this one will
finish the job.  ckutio.c.

Also in ttvt(), get rid of the statement that sets ttvt.sg_ispeed and ospeed
to the value returned previously by ttsspd(), which has just taken great pains
to handle 75/1200 split speed.  ckutio.c.

Added a Control-C interceptor to ttopen() so that an open() call hung because
the device doesn't have carrier can be interrupted from the keyboard.

------------------------------

5A(144) Tue Jun  5 12:45:48 1990

Backed off on making QUIT leave the line open.  Now once again, QUIT == EXIT.

Added #include <stdio.h> to ckcfns.c, ckcfn3.c, and ckuxla.c so that NULL will
be defined appropriately for given compiler and computer architecture.  It
turns out that defining NULL to be 0 on a 16-bit system where pointers are 32
bits results in garbage or core dumps when NULL is passed as an argument to
a procedure that expects a pointer.  If, after including <stdio.h>, NULL is
still undefined, then it is defined to be 0L, in hopes that the size of a
pointer is the same as the size of a long.  This may cause problems.  If it
does, we're going to have to define the NULL pointer for each implementation.

Fixed SHOW LANGUAGES and SET LANGUAGE ICELANDIC (problem reported by Andy Fyfe
and others).  A table entry for Icelandic was missing from the langs[]
structure in ckuxla.c.  Added variable nlangs to specify how many languages
are really in the table, rather than using the symbol MAXLANG in "set
language" parsing code in ckuus3.c.

Changed AT&T 7300 modem dial timeout from 20 to 25 seconds, and 7300 system ID
string to not have trailing newline, and SHOW PROTOCOL not to have a blank
line.  Andy Fyfe.  ckudia.c, ckutio.c, ckuus4.c.

Revised man page from Chuck Hedrick, ckuker.nr, containing much more material
than the first -- lists of commands, etc.  Changed some wording to make it
more general.  To view it, "nroff -man ckuker.nr".

Bo Kullmar discovered that that "kermit -e 2048" did not work but that
"kermit -e 2047" worked OK.  Off-by-one error, fixed in ckuus4.c.

Changed ttpkt() in ckutio based on the following complaint from Bo Kullmar and
the suggested solution from Kristoffer Eriksson:

> Since some version I can always talk to the modem on the dnix systems
> (both the 5.2 and the 5.3 system) and it does not matter what I do with
> "set carrier". I have reported this to Kristoffer but he could not repeat
> it on his dnix system.

Argh! The carrctl() call in ttvt() has been assuming that conect() would call
ttvt() with flow=CONNECT, so it would know when to enable carrier detection in
AUTO mode. But conect just calls it with the global flow variable, which I
don't think ever is set to CONNECT.

SET CARRIER ON works as it should if I set it before SET LINE. If I set it
afterwards, it doesn't take effect. That is probably caused by the check for
tvtflg in ttvt() which checks for changes in speed and flow, but doesn't
notice that ttcarr has changed. Should be fixed. (I said tvtflg would be
troublesome, didn't I?)

With SET CARRIER AUTO, I don't get carrier loss detection during CONNECT at
all (even with a modem type set, which is a prerequisite), which is caused as
explained above. Bo says that this worked at sime point in the past, but I've
check version 123 and there the code was the same, and in 121 carrctl() hadn't
been added yet.

Now, how do we solve this? A quick solution would be to make conect() use
CONNECT in the ttvt() call, but the use of the CONNECT/DIALING flow values
should rather be decreased in stead of increased, and we would loose control
of the flow control.

I've used identical calls to carrctl() in ttpkt() and ttvt() up to now, and
relied on the flow parameter to determine what to do in the AUTO mode. I
suppose this was wrong. The right way to do it is probably to set up CONNECT
mode when you're in ttvt() and non-CONNECT mode in ttpkt().  (That sounds very
reasonable.) Thus, in ttvt(), the term "&& flow == CONNECT" should simply be
dropped. Conversely, one can argue that the entire line that starts with "||
ttcarr == CAR_AUT ..." in ttpkt() should be dropped, too. I'm not entirely
sure about that, though. Just the bare existence of "flow == CONNECT" makes one
wonder what should be done in that mode. It is used in ckudia.c. It can be
interpreted either as "end the DIALING mode" or "prepare for ttvt() mode". I
suggest we try the former alternative, and drop that line. This can possibly
even help Peter Mauzey some, because ttpkt(CONNECT) is called after dialing
and enabling carrier detection so soon can possibly be part of the cause for
the premature disconnect that he is experiencing (or, at least it doesn't
exactly contribute to avoiding it).

Fixed the fix that was made to the XXDEL: case in docomd(), in which the
response from zchki was treated as a long rather than an int -- needed to
change the variable in another place (Bo Kullmar).  ckuusr.c.

Added some fixes to cmifi() so that a file whose name begins with tilde can
actually be found and opened if the user types esc or tab to complete it (this
never worked before, since tilde-expansion was first added in 4F).

New VMS support files arrived from Mark Buda.  Not finished yet, but he says
they should compile and link without complaint, and produce a running C-Kermit
for VMS that can dial, connect, etc, has a working command parser, but does
not yet transfer files correctly because the RMS-related aspects of ckvfio.c
are not yet completely filled in.  The new files are installed with the other
C-Kermit files as ckv*.*.  There were also a couple very minor changes
required in ckcfns.c, ckcfn3.c, and ckcfil.h.  I tried building the program
under VAXC 2.3-024 and VMS 5.0 (Mark has much newer C and VMS versions), but
it failed because my VMS system doesn't have a header file, STARLET.H, needed
by ckvfio.c.  Mark says this file is not necessary -- contains only
prototypes.  I commented out the #include and tried again.  This time it
failed on ckufio.c, objecting to many occurrences of "&((char *) 0)".  Didn't
know what to do about these, but managed to run the rest of the files thru the
compiler, which turned up a few more errors -- typos within #ifdef VMS
conditionals in ckuus5.c, which i fixed.  Sent results of today's compiler
runs to Mark.

SUNOS 4.1 was installed recently on watsun, and I was just looking through the
manual.  This new release of SUNOS is "8-bit clean", and even attempts to
support ISO 8859 Latin Alphabet 1 in various ways.  Sure enough, if I do "stty
pass8" to the Sun, and SET DISPLAY 8 on the PC, I can view 8-bit Latin-1 data
directly with cat, more, etc.  Tested some features of C-Kermit in this
environment:

 - TYPE displays 8-bit files correctly.

 - If you SET LINE or SET HOST, and SET TERMINAL BYTESIZE 8, and then CONNECT
   to another computer that can display 8-bit characters, C-Kermit displays
   them correctly.

 - TRANSMIT and LOG SESSION work right with 8-bit characters if you give the
   command SET TERMINAL BYTESIZE 8 first.

 - File transfer works right, but you have to tell C-Kermit to SET TRANSFER
   CHARACTER-SET LATIN1 first, so that the Kermit on the other end (e.g.
   MS-DOS Kermit) will know that incoming data is Latin-1 and will convert
   it properly if necessary.  This is most obvious when you run C-Kermit in
   server mode, and then send REMOTE TYPE commands to it for Latin-1 files.
   The default transfer character-set remains TRANSPARENT, for compatibility
   with previous releases.

Compiled this edit on the NeXT.  It complained about argument passing between
incompatible pointer types in ckcfn3.c (sprintf(&data[i+2],...).  No harm done
at runtime, but I made the complaints go away by casting the first argument to
(char *) -- the problem was that data[] is CHAR (= unsigned char).  The NeXT
also has a pointer complaint about this line in netopen() in ckutio.c:

    if (connect(ttyfd, (caddr_t)&saddr, sizeof(saddr)) < 0) {

but I have no idea how to make the complaint go away.  The code works fine at
runtime on the NeXT (and everywhere else), so who cares?

At Jack Bryans' suggestion, added "LIBS = -lsys_s" to the makefile entry for
the NeXT to request the shared library, saving over 80K in the executable
program.

Tried building the program on an IBM mainframe with AIX370.  The compiler
complained correctly about several variables in ckuus*.c defined but never
referenced.  Removed their definitions.  Many other lintish problems in other
modules were fixed too (but we can't fix the the "statement not reached"
warnings when compiling ckcpro.c).  Fatal compilation problems with SIGTYP and
getuid(), in ckufio.c.  Changed the definition of SIGTYP for AIX370 in
ckcdeb.h (again!), and put extern declarations of getuid() within #ifndef
AIX370 conditionals.  Changed the makefile entry because it was not including
the library file libbsd.a, which is needed for ftime().  Added a special
version herald for AIX/370.  Compiled OK except for the 4 unavoidable warnings
in ckcpro.c, and cursory testing of SET HOST, CONNECT, SEND, RECEIVE, etc,
was successful.

Compiled the program on a MicroVAX with Ultrix 2.0.  No problems at all.
Seems to run OK too.

------------------------------

5A(143) Mon Jun  4 17:38:59 1990

Rec'd many messages from Chuck Hedrick at Rutgers University.  One of them
included a new man page for version 5A, which gives an overview of how to use
C-Kermit on Unix in both remote and local mode, but without listing all the
commands and options (it refers the reader to the manual for that).  ckuker.nr.

Suggestions from Chuck:

  A method of exiting the program without hanging up the line.  Can't be
  done, because this leaves the lockfile hanging around, and so the line
  can't be assigned next time Kermit is run -- especially true if Kermit
  was running setuid.  Instead, use PUSH to start an inferior shell, or
  SUSPEND (or Z) to suspend the program if the computer system supports job
  control.  Also, if the program receives the SIGTSTP signal, it will be
  suspended.   

  Chuck wanted a "more" option for TYPE, but this would require tons of code
  to handle tab expansion, line wrap, checking termcap to find out the
  terminal's screen length, etc.  Easier to just let the user define a macro,
  "more" to be "run more \%1", which works fine.

Fixes from Chuck:

  "=" should be "==" in pktopn().  This is what was preventing the packet
  log from working.  (also noticed by Bo Kullmar.)  ckuus4.c.

  Debug log listed old, rather than new, parity value in ttpkt().  Changed
  to list new one.  ckutio.c.

  A (hopefully) never-used spack() call in ckcfn3.c had two of its arguments
  reversed (the one where it cops out by sending an empty attribute packet if
  the attributes came out to be too long for the current packet length).

  speed was declared external int rather than long in ckuusr.c.

  various type declaration mismatches among modules, typically int vs long,
  char vs int (speed, ttgspd(), zchki(), filcnt, ffc, tfc, rptn, kermrc).
  Many modules.

  tlog() sometimes called with 4th arg of type int, rather than long.  Made
  sure all were cast to long.  Changed all "0l" to "0L" for clarity.
  Corrected a couple occurrences "01" that were supposed to be "0l" (i.e. 0L).

  Several files which are supposed to be UNIX-independent (ckcfn*.c) included
  #ifndef NULL, #define NULL 0, #endif.  Since NULL is intended to be a
  pointer, which is normally the same length as a long, Chuck suggested that
  the #define should be changed to 0L.  I made this change, but also inserted
  an #include <stdio.h> first, to pick up the local compiler's preferred
  definition, so that the 0L definition will only kick in if <stdio.h> does
  not define NULL.  The problem was that 0 is an int, and on 16-bit systems,
  passing an int to a function that expects a pointer results in garbage or
  core dumps.

  atol() used in ckcfn3.c and ckuus4.c without being declared as long.

  Changes to makefile for Microport SV/AT 286 Sys V R2.

  Added description of SET DIAL HANGUP command to ckuker.mss.

From Andy Fyfe, a couple fixes to ckutio.c for ATT7300 (3B1) UNIX PC dialing.

From John Chmielewski, AT&T Lisle IL, add post-connect delay for AT&T DTDM.
ckudia.c.

Also from John Chmielewski, put #ifdef SETUID around access() call in
look4lk() rather than in ttlock().  ckutio.c.  This whole business will,
hopefully, become obsolete once the priv_on/off() code is installed.

Make tempfd global to ckutio.c, so that ttclos() can close it if it's open.

Supply a missing semicolon in tthang() in the extra open() that's inside
of #ifdef CLSOPN2 conditionals.  Only would have been noticed if -DCLSOPN2
was added to a makefile entry.  From Peter Mauzey.  ckutio.c.

From Kristoffer Eriksson: merge some redundant code in ttopen() into a new
function, do_open(), which also has the benefit of handling the case where the
symbol O_NDELAY is not defined.  ckutio.c.

Fixed a bad problem in which any REMOTE command sent to a C-Kermit server, and
then interrupted, could result in junk being sent the next time data was
requested from a server.  The problem was that zxcmd(), the function that
opens a fork (rather than a file) for file transfer i/o, did not reset the
buffer pointers and counts used by the zminchar/zmchout & related macros.
This bug has been in C-Kermit since early 4F, and nobody ever noticed it (???)

------------------------------

5A(142) Sat May 26 16:32:12 1990

Added BREAK and CONTINUE for FOR-loops.  Easy, just defined them as macros
inside the _FOR definitions that GOTO the appropriate place.  ckuus5.c.

Added fixes to cmofi() and cmifi() for tilde expansion from Bo Kullmar.
ckucmd.c.

Removed one last strchr() from ckutio.c (it was in netopen()).  Now there
should be no more strchr's or index's or rindex's.  No C library can be
depended upon to have any of these.  Thanks to Steve Jenkins at the Lancaster
U, UK.

Removed declarations of int big[sr]bufsiz from ckcfn3.c.  These variables are
not used in that module, and they were causing some C compilers to complain
(incorrectly) about name conflicts.  Thanks to Jay Rouman at U of Mich.

Removed atthang() function from ckutio.c, and added a few statements
particular to the ATT7300 (3B1) to the regular tthang() function, based on
info from Andy Fyfe.  Also, turned on myread() for the ATT7300 for the first
time; Andy says it works OK.  Needs wider testing!

In a final attempt to get the ATT systems working, I added a second open()/
close() sequence to tthang(), within #ifdef CLSOPN2 conditionals.  According
to some reports, HANGUP would only bring DTR up after dropping, if the device
was closed and then opened not once, but twice!  Also, reorganized tthang()
somewhat, so that things seem to happen in the most logical sequence.  Too
many little changes to describe here, but they are well commented in the
function itself.  I really, really hope this is the last go-round for tthang!
(dream on...)  ckutio.c.

Also, towards the same goal, added a new command SET DIAL HANGUP {OFF, ON}.
Default is ON, as before, but if you use OFF, then DIAL will not hang up the
line before dialing.  If we can't fix this problem, at least we can give the
user the means to work around it.  ckuus3.c, ckcmai.c, ckudia.c.

Another fix from Andy Fyfe: in ckuus5.c, initialize mrval[maclvl] (macro
return value) to NULL, rather than "" (the empty string), so that it won't
be freed erroneously, causing a core dump.  Also required making sure that
user-defined functions return "" rather than NULL in ckuus4.c.

Found that the function, rdebu(), that enters outbound Send-Init parameters
into the debug log was printing data from the wrong buffer.  I don't think
this was doing any harm other than printing misleading data in the log, but
who knows? ...  ckuus4.c.

Changed rcalcpsz(), the function that recalculates packet size based on the
number of errors, to take sliding windows into account (simply uncommented
some of Paul Placeway's code, and changed some variable names to agree with
the ones that are actually used).  ckcfn2.c.

Changed the CRC lookup tables, crcta[] and crctb[], to be of type LONG rather
than unsigned int, because some of the values were greater than 16 bits, and
on (at least) the ATT 6300, this caused incorrect CRC calculations and
prevented file transfers.  Also added a cast to LONG in the chk3() function.
Works on the SUN, but needs testing on the 6300 and other machines that really
do use 16-bit ints.  Watch out for sign extension!  LONG is typedef'd (in
ckcdeb.h) as "long" rather than "unsigned long" because some compilers don't
have unsigned long.  ckcfn2.c.

Changed the VERSION command to output the numeric version number as a long,
rather than an int, since it *is* a long (ATT 6300 again).  ckuusr.c.

There may still be crashes on the 6300 when it issues a REMOTE HOST or similar
command.  These have been traced to when it calls zopeno() from opent() after
receiving the first data packet.  There is nothing obviously wrong here.
Added a few debugging statements to help home in on the problem.

Bo Kullmar discovered that Kermit did not detect an error when it failed to
write out received data to a disk that had filled up, and just kept on
receiving, and creating empty files (you really need a floppy disk for this!).
The problem was in zoutdump(), which was not testing the return code from
write() properly.  Now fixed, I hope.  ckufio.c.

The DIAL command was changed to require the user to specify a dial string
(phone number).  Previously, the user could just type "dial" with no number,
and the program would try to dial nothing.  ckudia.c.

Changed the "Dialing" message to include the modem type.  ckudia.c.

Changed names of privilege_on() and privilege_off() to priv_on() and
priv_off(), to keep within the 8-character limit for function names. ckutio.c.

Changed SET LINE code to print an informative message telling the user what
to do if it times out waiting for carrier.  ckuus3.c.

OS/2 -- Chris Armstrong is leaving the country, and has done all he can for
the OS/2 version of C-Kermit.  All his work was based on C-Kermit 5A edits
in the Feb-March era, and he made some minor changes to the system-independent
code, which I have added in this edit.  However, I have no idea if the
resulting set of files will compile or run successfully any more, because a
lot of changes were also made on this end since Chris last took the 5A code,
in particular some of the calling conventions to the functions in the
ck*[tf]io.c modules.  We need another OS/2 person -- Thanks to Chris for all
his help up till now!  Chris's changes are listed in the file ckoker.upd.

Problems transferring files with very long packets.  This was caused by the
packet-receive timeout alarm going off before the packet was completely read.
When packets are very long and/or the transmission speed is low, it is
increasingly likely that the user has the timeout interval set to fewer
seconds than it would take to read a packet at that speed.  Code had been
added in many places to adjust for this possibility automatically, but there
were a few places where this adjustment was skipped.  Also, it the SET SERVER
TIMEOUT command interfered by overriding the adjusted timeout whenver server
mode was entered.  Many changes made to correct these problems.  A new
variable was added, pkttim, the number of seconds to wait for a packet during
a transaction, as opposed to srvtim, the number of secs to wait for a packet
while in server command wait.  The active timer, timint, is now set to one or
the other depending on what state Kermit is in.  Tested at 1200 bps, seems to
work ok now.  Further testing needed.  ckcpro.w, ckcmai.c, ckcfns.c, ckuus3.c,
ckuus4.c.

After looking through several people's debug logs, I decided it's a bad idea
to NAK all un-ACK'd packets when receiving, and to retransmit all un-ACK'd
packets when sending, whenever a timeout occurs.  input() has been changed to
only NAK or resend the packet at window-low (the oldest outstanding packet).
The old code has been left intact within #ifdef BULKNAKS conditionals in case
we need to revive it.  I tested this as best I could, but my primary testing
mechanism seems to have stopped working, namely the ability to turn my
t-switch away momentarily during file transfer.  When I do that now (because
of an upgrade in the SUN's OS, not because of anything in Kermit) Kermit gets
a HUP signal and shuts down.  Verified that when this happens, Kermit saves
the partially received file, which, I suppose, is good.  More testing needed.
ckcfn2.c.

Changed various modules not to record packets in the debug log.  Otherwise,
with long packets and/or windowing, the log gets huge mighty fast.  If you
want to record the packets, use a packet log.

More work on character sets.  Added a special translation from Latin-1 to
ASCII for Icelandic, provided by Fridrik Skulason, handling Thorn, Eth, and
AE.  Changed transliteration from Latin-1 into ASCII of U-diaeresis to be Ue
rather than Y (and ue rather than y) for the Scandinavian languages, by
consensus of many Swedes, Norwegians, Finns, and Danes.  Removed SET LANGUAGE
SWISS, because SWISS isn't a language, it's an NRC.  Or if Swiss really is a
language (Romansch), I don't know any special transliteration rules for it.
Needs testing.  ckcxla.h, ckuxla.c, ckuus3.c.

Began to look at adapting Kristoffer's uid-handling routines to Kermit.
Unfortunately, this method does not seem to work in the BSD environment.  I
wrote a little test program to see what happens on the SUN, which, by default,
acts like a BSD system as far as uid's are concerned, see ckuuid.c.
Then I chown'd the program to another user, cmg, and chmod'd the program u+s 
and g+s:

$ ls -lg uid
-rwsrws---  1 cmg      candf       24576 May 27 22:17 uid*

and then ran it with these results:

$ ./uid
at startup...
 getuid = 107, geteuid = 4505
 getgid = 301, getegid = 1327
initsuid returns 0
 getuid = 107, geteuid = 107
 getgid = 301, getegid = 301
priv_on returns 2
 getuid = 107, geteuid = 107
 getgid = 301, getegid = 301
priv_off returns 0
 getuid = 107, geteuid = 107
 getgid = 301, getegid = 301

So I can't get the priv'd ID back.  This seem to agree with what Ken Arnold
says in his article "Setuid Security Blankets" in the C Advisor section of
Unix Review, May 1990: "When UNIX checks permissions, it uses the effective
uid.  A running process can change its effective uid to be the same as its
real uid at any time.  However, under BSD this is a one-way trap door.  Having
done it once, you can't get back."  Anyway, I modified Kristoffer's routines
to use setre[ug]id() for BSD, apparently with no effect.  ckutio.c.

Fixed the implementation of FOR loops to only require one macro, rather than
two (one for ascending loops, a second one for descending).  Now the
comparison operator is passed by the FOR command as an argument to the
combined _forx macro.  Old code is within #ifdef TWOFORS conditionals, can be
removed if no problems surface.  ckuusr.c, ckuus5.c.

Added optional numeric trailing argument to EXIT and QUIT commands, which is
the program exit status code to be returned to the operating system.  The
default is GOOD_EXIT (OS-dependent, defined in ckcdeb.h).  Tested in UNIX,
works fine.  ckuusr.c.

Compiled this edit on the NeXT, which has one of the pickiest C compilers
around.  Only one warning (from netopen in ckutio.c, about incompatible
pointer types).  Works fine, including SET HOST (where the warning came from).

Compiled on the Encore with UMAX 5.0 using "make bsd43".  Fixed a typo in the
makefile (-DNETCONN-O should be -DNETCONN -O).  After that, no complaints,
runs fine.  

------------------------------

5A(141) Thu Apr 26 18:45:43 1990

Christine Gianone and I wrote a draft manual for version 5A: ckuker.mss
(Scribe source), ckuker.doc (plain ASCII), ckuker.ps (Postscript).  Comments
welcome.

In makefile, change "make clean" to not remove wermit.  Added entry for MIPS.

In ckuus2.c, remove spurious \'s from character strings.

In ttopen(), added fourth parameter, timeout, default 0.  If > 0, then open()
is timed, and ttopen() returns -2 if the timer expires.  Timer is set by the
command SET CARRIER ON [ n ] (in ckuus3.c), where n is the number of seconds
to wait for carrier when trying to open the communication line, and is
initialized to zero in ckcmai.c (variable cdtimo), and need not be specified
in the SET CARRIER ON command, in which case it defaults to zero.  In order to
avoid spurious error messages, removed call to perror if open() failed because
of timeout.  ckutio.c.

Changed all calls to ttopen() in ckcpro.w, ckudia.c, ckuscr.c, ckuus3.c, and
ckuus4.c to include new timeout parameter.  Updated ckasys.doc and ckuker.mss.

In tthang(), changed the order of restoring ioctl() and fcntl() in the
close/open case in a last-ditch attempt to make this code work for Peter M.
ckutio.c.

For BSD, change sleep(1) in ttres() and conres() to msleep(300) to cut down
on program recovery and exit time.  ckutio.c.

Set tvtflg=0 in ttkpkt right after calling carrctl(), to make sure that later
calls to ttvt() are not incorrectly skipped.

Found that the code added to openi() in ckcfn3.c that was added to prepare
for SSEND broke "kermit -s file".  Nobody noticed!  Removed the offending code.

Looked into the possibility of reinstating Paul Placeway's "encode-ahead"
trick from version 4F to boost performance in the common non-windowing case.
The trick is to have C-Kermit encode the next packet while waiting for the ACK
to the current packet.  It only makes sense to use this with 1 window slot.
The trick worked in 4F because the encoding buffer was copied into the packet
buffer when the packet was actually sent, so that resend() still had access to
it in case a NAK was received.  5A, however, encodes directly into the packet
buffer, so this trick can't work.  So all of Paul's "sdahead()" code was
removed from ckcfns.c, lest some unsuspecting person (like me again in a year)
be tempted to reactivate it (which I did try, and it caused horrible errors).
Ran some benchmarks sending long files from 4F (with encode-ahead) and 5A
(without) and found only about 1% difference anyway.  Later, we can try some
kind of trick to use the existing windowing code in non-windowing transfers
to allow packets to be encoded in advance while waiting for ACKs.

While I was at it, I measured Kermit against FTP between 2 SUN-4s.  Turns out
FTP is faster after all...  about 2.5 times.  But it's still fun to watch
C-Kermit transfer files at 167,000 bps.

Changed calling convention to conint() in ckutio to include a second argument,
namely a pointer to a function to call in order to suspend, for use with job
control.  Formerly, conint() had the function name hardwired into it, which
wouldn't have been so bad except the function was in ckuus5.c!  ckutio.c is
not supposed to depend on any code outside itself.  Also noticed in ckuus5.c
that trap() and stptrap() were not declared to be of type SIGTYP, which may
account for some of the pointer errors that some compilers have been
complaining about, and maybe even some misbehavior at runtime.  Moved
system-dependent contents of stptrap() from ckuus5.c to ckutio.c, into a new
routine called psuspend().

Fixed job control.  Ctrl-Z was not suspending Kermit.  Discovered that this
was because there was no #include <signal.h> directive in ckuus5.c, probably
because stptrap() had been moved there from some other module.  Added SUSPEND
command, and an invisible synonym for it, Z, which is found in many other UNIX
programs.  They simply call stptrap().

Added Kristoffer's suid-handling functions to ckutio.c.  Within #ifdef SKESUID
conditional, call init_suid() from within sysinit().  Didn't do anything else
with it yet, however.  Still need to adapt to Berkeley use, and then go
through all of the code in C-Kermit that does any kind of uid call and remove
it, and then add calls to privilege_on() and privilege_off() around the
lockfile garbage.  Should be easy enough, except I'm not sure what to do about
the code in look4lock() (and in the filename parsing functions in ckucmd.c,
anywhere else???) that calls access(), which doesn't work with uid switching.

Changed name of ckcxla.c to ckuxla.c, because other C-Kermit implementations
(like Macintosh, OS/2) will need a different set of translation tables and
functions.  Changed ckuxla.c not to use ident() as the identity function, but
rather NULL, and have all code in ckcfns.c (and for the TRANSLATE command) in
ckuus4.c avoid calling the translate function if the pointer to it is NULL.
Thanks to Kristoffer for the suggestion to use NULL rather than rely on the
address of the ident() function for this test.

For SET LANGUAGE DUTCH, added special translation for umlaut-y = ij.

Added SET TRANSFER CHARACTER-SET TRANSPARENT.  This means to do no
character translations in text mode, and it is now the default.  SET TRANSF
CHAR ASCII is different -- it means to translate from the current file
character set into plain 7-bit ASCII.  Diacritics are stripped, so that
a-umlaut becomes simply a, etc, unless a SET LANGUAGE command has been given
to activate special language-specific conversions.  SET TRANSF CHAR LATIN1
works as before.

Discovered a bug that has been in C-Kermit ever since the international
character set stuff was added, but nobody noticed it before.  If you SET
TRANSFER CHARACTER-SET LAT, SET FILE CHAR ASCII, SET LANG GERMAN (or any
language that has special translation tricks) and then receive a file with
accented characters, the program core dumps.  Why?  Because the Latin-1 to
ASCII translation function, xl1toas(), is designed for reading files and
sending, not receiving and writing them, and uses the zmstuff() macro to push
characters onto the disk file input stream.  Not good for writing files!
Wrote a second copy of xl1toas(), called zl1toas(), identical to xl1toas(),
except it pushes characters onto the input packet data field.  So now the cute
national-language-to-ASCII translations work in both directions.

At this point I have to call it quits for a while, even though there is still
much left to do -- taking the weekend off, and going on a business trip next
week.  So I will install this version now so Kristoffer, Bo, Warren, Peter,
Jay, Joe and everybody else can bang on it for a week, and I will send it to
Mark on tape tomorrow so the VMS work can begin at last!

------------------------------

5A(140) Wed Apr 18 21:29:29 1990

Some minor (but time-consuming) performance tuning.  Profiled the program
while receiving a big file and found that it was spending an inordinate amount
of time in the decode() function: about 27% of total elapsed time, which put
decode() at the top of the list, by far.  Did some fine tuning in decode():

 . Don't call the translation function if it happens to be ident() (ditto in
   encode());

 . Organize and group the if-conditions more intelligently, for example,
   change "if (rptflg) { if (a == rptq) ... }" into
   "if (a == rptq && rptflg) { ... }";

 . Group the text file-handling (end of record, character translation) all
   within a single "if (!binary) { ... }" statement.

This brings decode() down to under 7% consumption of elapsed time.  The list
is now headed by read(), ioctl(), and write(), with all others relatively
insignificant, and this is as it should be.  However, file transfer benchmarks
before and after this tuning show only a small (1-2%) gain in efficiency.

I ran some benchmarks to see how our performance is doing.  These are for a
36K Text file (with no repeated characters, so no compression) between an
unloaded SUN-4/280 with C-Kermit 5A(139) and an IBM PS/2 with a hard disk and
MS-DOS Kermit 3.01 at 9600 bps, no parity, block check 1.  The results are a
little disappointing but at least they demonstrate that file transfer is
pretty solid.  All transfers took place with no errors or retransmissions.

  Packet    Window Size............
  Length    1          2          4

     90     65  64     79  87     80  87   figures are percent efficiency:
    250     76  76     82  91     84  91
    500     79  80     87  91     84  93     file characters / sec x 10
    750     84  82     87  93                --------------------------
   1000     84  82     87  93                         baud rate
   1500     85  83
   2000     85  84
	    Up  Dn     Up  Dn     Up  Dn   (Upload, Download)

In this configuration, that's about the best we can do.  It's as good as older
releases of Kermit, and of course better when windows are used.  The SUN CPU
is not the bottleneck, because network transfers (using SET HOST on the SUN)
can clock up to about 17,000 characters per second.

Here's the same benchmark, but between two C-Kermits, both on SUN-4s (no PC):

  Packet    Window Size............
  Length    1          2          4

     90     73  73     89  89     89  89
    250     81  81     91  91     91  91
    500     97  87     93  93     91  91
    750     89  89     93  93
   1000     87  87     96  96
   1500     89  89     93  93
   2000     91  91
	    Up  Dn     Up  Dn     Up  Dn   (Upload, Download)

This is significantly better than the PC/C-Kermit test, especially at the
low end, and the 96 figure for 1000-byte packets in 2 windows is actually
exceeds to the theoretical maximum of 94.999999...%.

Tried the same benchmark on a half duplex connection to an IBM mainframe in
linemode using XON line turnaround handshake, mark parity.  Found that the
change made to ttpkt() in edit 128 broke this mode of operation.  It seems
that if you don't tell BSD UNIX to put the line in raw mode, then it ignores
received XON characters EVEN IF TANDEM IS NOT SET (grrrrr).  So I changed
ttkpt() to put the line in raw mode whenever parity is none as well as
whenever parity is not none and Xon/Xoff is not requested.  File transfer with
IBM mainframes works once again, at least in BSD.  The AT&T versions did not
change in this area, so they should still work (but testing is needed).  Also
found and removed a spurious setting of speed in ttpkt().

The results of the IBM mainframe linemode benchmark were comparatively poor,
except at the longer packet lengths (windows can't be used because the
connection is half duplex):

  Packet    
  Length    Window Size 1      

     90     40  52
    250     52  73
    500     58  81
    750     56  85
   1000     **  87
   1500     **  89
   1750     **  89
	    Up  Dn   (Upload, Download)

Additional discoveries...  "set line /dev/null" (and certain other devices)
would cause a core dump.  Added lines to ttopen() to refuse to accept devices
which, once opened, fail the isatty() test, and return an error code.  Seems
to work ok, and not interfere with i/o redirection like "kermit -k",
"cmd | kermit", etc.

Discovered that if you try to receive a file in local mode, but there is no
Kermit on the other end, that C-Kermit will just keep timing out and sending
NAKs forever, until eventually its buffer allocator gets confused and returns
a fatal error.  The problem was in nack() -- the code was incrementing the
wrong retry counter!  This fix may also have noticeable benefits in more
realistic circumstances.

In local mode, there was no way to interrupt a file transfer until it reached
the data phase, except by typing Ctrl-C which would exit the program
completely, dropping the connection -- inconvenient if dialed.  This has been
fixed by allowing the user to type 'c' or 'e' to cancel packet operations and
return to the prompt.

Started to add SSEND, SRECEIVE, and SGET commands to send from and receive/get
to a command rather than a file.  SSEND almost works but not quite.  See
openi() in ckcfn3.c, etc.  Just a matter of getting the word to openi through
various layers of calls in which this stuff is not passed as parameters.
(Later...) this is a bigger deal than it would appear.  Leave this for some
other time.

Tested ttgmdm() on the Encore, whose OS is supposed to be based on 4.3 BSD.
It has the symbol TIOCMGET defined in its <sys/ioctl.h>, but calling ioctl()
with this function on an open file descriptor for a terminal device just
returns the error "not a typewriter".

WHOOPS!  TIMER IN TTOPEN should be removed, or made user-selectable.  The
"hang forever waiting for carrier" behavior turns out to be desirable if you
want Kermit to wait for an incoming call!

All-day project: Added help text for recently added commands.  Clean up help
text and make it consistent.  Change hmsga() to do more-style prompting if
help text is longer than one screen.  Make all help messages go thru hmsg() or
hmsga() (except just a couple that need to do special things).  ckuus2.c.
Because this file grew so much from the new help text, I put all the help text
and subordinate functions within #ifndef NOHELP conditionals, so that the
built-in help feature can be compiled out (not recommended, but it works).
On the SUN-4, the savings is about 24K.

------------------------------

5A(139) Mon Apr 16 18:42:18 1990

C-Kermit should not NAK packet k just because packet k+1, k+2, ..., k+n-1
arrive, except if the timeout interval has expired on packet k.  Commented out
the code in the input() function in ckcfn2.c that sends a NAK for the packet
at window-low if higher numbered packets arrive.  Now NAKs are only sent if
a damaged packet arrives or if there is a timeout.

Found another place where the packet length is recalculated based on the
negotiated window size: in spar() in ckcfns.c.  Fixed this code to call
adjpkl() like all the other places do.

Added the XIF (Extended IF) command.  This is like the IF command in that it
works with the same set of conditions, but the object command can be a group
of commands rather than a single command.  The original IF command is
preserved for compatibility with MS-DOS Kermit.  The two commands are not
merged because the syntax of the object command is different.

The XIF command is implemented like the FOR command -- it's a macro, and since
macros execute on the stack, FOR and XIF commands can be nested and, in fact,
can contain each other in any combination.  The built-in macro that executes
the XIF command is called _xif, and its definition is simply:

  ass \%9 \fdef(_ify),ass _ify { \%1 },do _ify,ass _ify \fcont(\\%9)

The parser in ckuusr.c evaluates the condition and then accordingly selects
the THEN part or the else PART to be the macro argument (\%1).

Syntax of XIF:

  XIF <condition> { command-list } [ ELSE { command-list } ]

meaning that the word ELSE and the following command list are optional.  The
braces enclose a list of one or more comma-separated commands.  As with the
FOR command, "?" help is not available while typing in the object commands.

To illustrate the use of XIF, here's our familiar bubble sort, finally coded
more or less as one might do in a normal programming language:

    ass \%m \feval(\%n-1)
    for \%i 1 \%m 1 { -
	for \%j \%i \%c 1 { -
	    xif lgt \&a[\%i] \&a[\%j] { -
                ass \%t \&a[\%i], -
                ass \&a[\%i] \&a[\%j], -
                ass \&a[\%j] \%t -
            } -
	} -
    }

Here's a more useless example, showing how XIFs and ELSEs can be nested and
how each part can contain multiple statements:

  xif < \%i \%j {-
      echo \%i is less than \%j,-
      xif < \%i \%k {-
	  echo \%i is less than \%k,-
	  def \%a ONE-
      } else {-
	  echo \%i is not less than \%k,-
	  def \%a TWO-
      }-
  } else {-
      echo \%i is not less than \%j,-
      xif < \%j \%k {-
	  echo \%j is less than \%k,-
	  def \%a THREE-
      } else {-
	  echo \%j is not less than \%k,-
	  def \%a FOUR-
      }-
  }-
  echo \%a

The mechanism for adding grouping or looping commands is now pretty usable.
Should the need arise for a WHILE command (for example), it should be possible
to add it easily.

------------------------------

5A(138) Fri Apr 13 15:30:40 1990

Fixed a bug in which bad commands within the initialization file would cause
Kermit to go into a loop, postpone displaying its herald, and/or put the
terminal into weird-mode.  ckuus5.c.

Added code to ckuus3.c to ensure that the requested number of window slots
is never greater than or equal to the per-packet retry limit (SET RETRY,
SET WINDOW).  Imagine a connection with a delay time of n packets, in which
Kermit has its window size set to n.  Packet k does not arrive, so receiver
NAKs it.  But sender will not get this NAK for n-1 packet times, and so sends
the next n-1 packets.  The receiver cannot ACK these new packets, so it
responds to each new packet by sending another NAK for packet k, for a total
of n.  If n is greater than the retry limit, the sender will give up
unnecessarily.

Moved code that puts \flit() around all commands within a bracket-enclosed,
comma-separated list of commands to a function, litcmd(), in ckuus5.c, so that
it can also be used by XIF and any other commands we add later that operate
upon a group of statements.

Some computers that have popen() don't have a declaration for it in their
<stdio.h> files, for example the TRS 6000.  Added this in ckufio.c within 
#ifdef TRS16 (Jay Rouman).

Cleaned up the makefile a bit more.

Commented out all (2) invocations of ttclos() from ckudia.c.  There is no
reason why the DIAL command should close the line if dialing fails.  When it
does, the program becomes confused about what the current line is, what its
speed and other parameters are, etc.

------------------------------

5A(137) Wed Apr 11 22:15:56 1990

Fill in ttgmdm() for BSD 4.3 and SUNOS 4.0, which have the TIOCMGET ioctl
available.  Doesn't seem to work, though -- always says no modem signals are
on (at least on SUN).  Added SHOW MODEM command.

Yesterday's edit broke the Kermit server's response to REMOTE commands because
an internal reference to zxcmd() (whose argument list just changed) in
zopeni() in ckufio.c was missed.  ckcpro.w was calling zopeni(ZSYSFN,cmd) when
it should have been calling zxcmd(ZIFILE,cmd), and relied on a hack within
zopeni() to pass the request along to zxcmd(), and that call hadn't been
updated to include the file number.  From now on, let's only call zxcmd when
we want to read or write a command (pipe) instead of a real file!

Removed one last (?) stray strchr(), this one from chktok() in ckucmd.c.
Various other lint-inspired fixes in various modules, some of which might be
important, like some functions that were called without all their arguments,
including one strncmp() that was called without a length argument!

Found an extra sleep(1) in ttres() and removed it.  No wonder closing the
line was so slow in BSD!  (It's still slow, because there's still one sleep(1)
in ttres(), plus another one in conres().)

Added a 30-second timer around the open() call in ttopen(), to prevent Kermit
from hanging forever if SET LINE is done on a modem-controlled line that is
not presenting DCD.  I thought of passing the alarm interval as a parameter to
ttopen(), but why bother?  Another incomprehensible SET command, and calls to
ttopen() would have to be changed in dozens of places, and what difference
does it make anyway?  Under what circumstances should carrier be expected to
appear in 60 seconds rather than 30?

In ttlock() in ckutio.c, if the SETUID conditional is turned on and look4lk()
reports that we don't have write access to the lockfile directory, ignore this
warning and go ahead and try to create the lockfile anyway because the
access() call in look4lk() checks lockfile permission based on the read uid
and gid, not the effective uid and gid, and so if we are running setuid to
uucp in order to access the lock directory (for example) look4lk() will still
think we don't have access, which defeats the whole purpose.  So in this case,
skip the check and go on the create the lock file.  If it fails, we'll catch
it then.  Note, by default the SETUID conditional is not turned on.

A new bug has surfaced...  Every so often, the version herald will be
displayed for no reason at all, for example when Kermit goes back to its
prompt after receiving a file.  The reason is not obvious -- herald() is only
called from one place (in ckcmai.c), and it's not in a place that gets
executed more than once.  Check this tomorrow (or Monday)...

Whoops, I found (but did not yet fix) the problem...  If your .kermrc file
contains a bad command, the implicit TAKE on the file quits early, and the
herald is not printed until the next time you enter the command parser.
What's more, after this happens, your console terminal is left in some kind
of funny state.  Something to do with cmdini()? ...

The file ckasys.doc was written a couple days ago (and updated each day since),
which lists the calling conventions and semantics of each function and global
variable in the system-dependent modules.

------------------------------

5A(136) Tue Apr 10 06:19:09 1990

Remember all the craziness about \fliteral() in the description of the FOR
command in edit 134?  Forget all that.  A bit a magic was added to the parsing
of the FOR command to insert the \fliteral() in the right places, so the user
never needs to know about it.  The reasoning is that if you ever wanted to
use loop variables in the object command of a FOR you always had to put
\fliteral() around them in the object command anyway, like this:

  for \%i 1 3 1 { echo \fliteral(\%i) }
  for \%i 1 3 1 { for \%j \%i 3 1 { echo \flit(\flit(\%i \%j)) } }

...so let the program do it instead.  For other escaped quantities (variables
other than the loop variables, functions, etc), the presence or absence
\fliteral() does not make a difference.  So instead of making the user do this
the program does it automatically, and now:

  for \%i 1 3 1 { for \%j \%i 3 1 { echo \%i \%j } }

produces the expected results, namely:

  1 1
  1 2
  1 3
  2 2
  2 3
  3 3

And there are no more bizarre rules about leaving the \ off the interior loop
variable, or putting \fliteral() around other things.  The FOR command parser
in ckuusr.c now changes:

  for \%i x y z { xxx, yyy, zzz  }

into:

  for \%i x y z { \flit(xxx), \flit(yyy), \flit(zzz) }

And this works recursively, e.g. when xxx (and/or yyy, etc) is another FOR
command.  It turned out that there was no way to do this in the macro
definition itself.

Footnote material: If braces are omitted from around the object command, the
\flit() is not inserted.  Of course, without the braces, you can only have a
single-word object command (macro argument-grouping rules).  This lets you
defeat the insertion of \flit() (not that I can think of any reason why anyone
would want to do this), for example:

  def \%i hi there
  def \%x echo \%i
  for \%i 1 3 1 \%x

writes "hi there" three times.

Our horrible sorting example from edit 134, which looked like this:

  def swap ass \%t \&a[\%i], ass \&a[\%i] \&a[\%j], ass \&a[\%j] \%t
  for %i 1 \%m 1 { -
      for %j \flit(\%i) \%c 1 { -
	  if lgt \flit(\flit(\&a[\%i] \&a[\%j])) do swap -
      } -
  }

Now can be written as:

    def swap ass \%t \&a[\%i], ass \&a[\%i] \&a[\%j], ass \&a[\%j] \%t
    for %i 1 \%m 1 { -
	for %j \%i \%c 1 { -
	    if lgt \&a[\%i] \&a[\%j] swap -
	} -
    }

Note that the "swap" macro still cannot be replaced by the statements
themselves in the IF statement.  This is not because of any quoting or
evaluation problems, but because IF only works on single commands.  To get
around this, we need to change IF to allow grouped statements in the IF and
ELSE parts.  This is now possible using the same method that was used for FOR
loops.  The IF command will not be changed; it must remain as-is for
compatibility with MS-DOS Kermit.  But there could be a second, "extended IF"
command, maybe called XIF, which might look like:

  XIF ( condition ) { list of commands } ELSE { list of commands }

which means I can rip out all of the disgusting code that was needed for
the current ELSE command, and only allow ELSE to be used with XIF (???).

Moved the code that executes the ! and RUN commands from ckuusr.c to a new
function, zshcmd(), in ckufio.c.  This code is loaded with system-dependent
#ifdef's and did not belong in the user interface module.

Changed the calling convention for zxcmd(), the function which opens a pipe
instead of a file, to include a Kermit file number.  So now it is possible to
READ from a pipe or WRITE to a pipe, or even (in theory) to SEND from a pipe
or RECEIVE or GET to a pipe.

Added two new options to the OPEN command:

  OPEN !READ command 
  OPEN !WRITE command

These open a system command (via call to zxcmd) for reading and writing,
respectively.  Some pretty useful applications for OPEN !READ spring to mind,
like:

  open !read ls ck[cuw]*.{doc,bwr,upd}
  echo Enter SERVER mode to receive multiple sends...
  pause 2
  set tak error off
  :loop
  read \%f
  if fail goto done
  send \%f	
  goto loop
  :done
  finish

Suddenly all of the system shell's fancy wildcarding is available to us.
Define this code to be a macro, say SSEND, and then you can use it pretty much
the same as you would use regular SEND.  The above example is from the
C-Shell.  OPEN !WRITE may find some uses (writing text to sort or grep???) but
mainly it's there for symmetry.  It uses popen(), which is hopefully available
in all versions of UNIX.  If not, add -DNOPOPEN to the makefile entry for your
system.  Note: popen() uses sh (not csh or ksh) to run the command.

Added a new function ttwmdm() to ckutio.c, to allow the WAIT command to be
implemented, as in MS-DOS Kermit.  This function waits for any of the
specified DCE signals: DSR, CTS, and/or CD to appear on the currently selected
communication device.  Various return values are given.

Added a similar command, ttgmdm(), that returns the status of DSR, CTS, and CD
in a bit mask.  In the UNIX version, ttwmdm() or ttgmdm() merely return -2
for a network connection, or -3 (= not implemented) for a tty connection.
This function, if it could be made to work, could have many valuable
applications, as well as supporting the more mundane SHOW MODEM command, as in
MS-DOS Kermit.

------------------------------

5A(135) Mon Apr  9 22:34:21 1990

A couple minor glitches were fixed in ckucmd.c, ckutio.c, and maybe a couple
other places.  These are obvious to anyone who tried to compile the program in
a non-BSD environment: undefined variables, etc.

Also, I put the code back into tthang() that closes and reopens the line in
System-III/V non-HPUX implementations, but it's done a little more carefully
this time than it was before.  Without this code, it appears that vanilla
System V versions of UNIX do not bring DTR back up (hangup is supposed to drop
DTR for about half a second, not forever).  This code, however, has the
potential risk of losing some of the mode settings on the line, and so should
not be used if it isn't needed.  Therefore it is enclosed within #ifdef
CLOSEOPEN..#endif conditionals, and won't be activated unless you add
-DCLOSEOPEN to your makefile entry.  If the DIAL command doesn't work for you,
then you need this.  Otherwise, leave it out.

Finally, from today's mail...

  Date: Mon, 9 Apr 90 00:45:48 -0400
  From: djm@eng.umd.edu (David J. MacKenzie)
  To: fdc@watsun.cc.columbia.edu
  Subject: script language

  The script language is a welcome addition to C-Kermit, but is there a
  philosophy behind its design?  I don't have your Kermit book, and I don't
  have much of a background in timesharing OS's other than Unix, but the
  impression I get is that C-Kermit's script language is sort of a
  Frankenstein's monster language, with a piece from here, a piece from
  there, and not very coherent.

  Certainly from a Unix hacker's point of view, it's just what we don't need
  -- another unique language syntax and set of conventions.  I wish the
  C-Kermit script language had been designed to closely resemble some common
  existing language and set of conventions, like Quick Basic, Lisp, AWK, or
  the Korn shell.  It seems to have all sorts of weird ways to quote things,
  for example.  It reminds me a bit of Dan Lawrence's MicroEMACS script
  language, but more chaotic.  And what is the justification for supporting
  only single-character variable names?

A major goal of C-Kermit's script language is backwards compatibility with
MS-DOS Kermit: that is, MS-DOS Kermit scripts should be executable by C-Kermit
with very little conversion required.  There is a large body of MS-DOS Kermit
script programs, so why invent "another unique language syntax and set of
conventions"?  The MS-DOS Kermit language is unarguably restrictive
(single-character variable names, etc), but it is simple and consistent.
C-Kermit has sacrificed some of that simplicity in its new features, a fact
amply illustrated by the FOR-loop story below.  So...  see edit 136, which, I
hope, smooths out the terrain a bit in this new territory.

------------------------------

5A(134) Sun Apr  8 23:08:51 1990

Applied fixes from Bo Kullmar in Sweden for OPEN APPEND and SET FILE COLLISION
APPEND.  Turns out once again that my SUN compiler was too forgiving; code
that worked here caused core dumps elsewhere.  Fix was to make the fcb
structure be static and to pass it to functions by reference rather than by
value.

At Kristoffer's suggestion, added code to ttvt() to check not only the tvtflg,
but also compare the parameters it was called with against the last parameters
that it set before deciding whether to return right away or to actually
perform the requested functions.  This is all quite ugly, but at least the
logic is localized within ttvt() and related functions so that others can call
these functions repeatedly without having to keep track of whether they've
been called before.  ckutio.c.

Cleaned up tthang().  Don't know if this will alleviate the drop-DTR-forever
problems on DIAL at AT&T, but it can't hurt.  If Peter Mauzey still can't dial
then put back the close ( open() ) bit and try again.  That should do it for
ckutio.c (???).

Fixed SET DEBUG ON to actually open the debug log instead of core dumping, ha
ha.  ckuus3.c.  Changed dumpsbuf() and dumprbuf() in ckcfn3.c to only print
the first 72 characters of the packet, rather than the whole thing.  This had
been another source of core dumps when very long packets were being debugged.

Put #ifndef UXIII..#endif around split-speed support, since AT&T UNIX does
not and can not support it.

Added code from Warren Tucker to ckudia.c to better interpret CONNECT response
to dial command from Hayes modem.  It will now attempt to change Kermit's
speed to any speed that the modem reports in its CONNECT message.  Warren said
he might also add Telebit Traiblazer support, which would be pretty neat,
since the Trailblazer has a "Kermit spoof" built into it.  But you've got to
set register S111 to use it: values are 10 (Kermit with no parity), 11 (Kermit
with odd parity), 12 (K w/even), 13 (K w/mark), and 14 (K w/space).  Other
values are 0 (no protocol), 20 (Xmodem/Ymodem), 30 (UUCP "g"), and 255 (use
protocol specified by other modem).  Also S112 is used for the packet start
character - this must be changed if Ctrl-A (SOH) is not used.  See pp.4-31 and
4.32 of the Telebit Commands and Registers Reference Manual.  I'm putting
these notes here because Warren seems to be disconnected from e-mail at the
moment.

In doing edit 133, I saw that there was redundant code scattered all over
ckuus*.c that parses and otherwise validates variable names and array
references.  Consolidated these sections into a single compact function,
parsevar(), and replaced the code in DEFINE, ASSIGN, INCREMENT, DECREMENT,
READ, ASK, and ASKQ with calls to this function.

Converted the code used by the INCREMENT and DECREMENT commands into a
function that can also be called from elsewhere.  The new function, incvar(),
can be used to increment or decrement any variable or array member by any
number.  ckuus5.c.

Considered adding BEGIN..END blocks for use in IF..ELSE statements.  But given
the current structure of the command parser, in which IF..ELSE, GOTO, and so
forth work only by ugly kludges, decided against it.  Statement grouping can
be accomplished using macros, or by invoking TAKE files.  /dev/null.

Also considered adding a subroutine mechanism (as in Fortran) with CALL and
RETURN.  Decided against this because a subroutine is no different from a
macro: it's a procedure consisting of one or more statements, which can be
invoked with parameters, and which returns to the statement past the one that
invoked it, but does not return a value.  The coding complications would not
have been worth the negligible benefit.  /dev/null.

Added ASG as an invisible synonym for ASSIGN.  Because of the ASK command,
the minimum unique abbreviation for ASSIGN is ASS.  Now, if you prefer, you
can type ASG instead of ASS in your commands.  ckuusr.c.

Fixed problem in RETURN statement which was causing core dumps if a null
return value was given within a macro and debugging was turned on.

FOR LOOPS

(warning - the following is a long story, in which the conditions keep
changing, so don't believe anything you read till you get to the end.)

Then I spent three solid days trying to add a FOR-loop mechanism, but after
writing and rewriting hundreds of lines of code and adding many new K of
buffers and stacks, I concluded there was no way to make it work
satisfactorily given the current structure of the program and the command
parser.  What I did worked just fine so long as its object command was a
simple Kermit command, not a compound command like IF or IF..ELSE, not a macro
invocation, and not a TAKE command.  It could even be nested to great depths.
But without being able to execute a group of commands in the FOR loop, the
command was next to useless.  So I removed it (evidence of budding maturity).

Anyway, loops can be constructed using the current mechanisms: DEFINE, ASSIGN,
IF, GOTO, and arithmetic.  For example, to sort an array \&a[] of strings
having \%n elements, using the bubble sort algorithm, we would write something
like this in a typical programming language (that doesn't have \-variables):

  m = n - 1;                       /* outer loop limit */
  for (i = 1; i <= m; i++) {       /* outer loop */
      for (j = i; j <= n; j++) {   /* inner loop */
	  if (a[i] > a[j]) {       /* compare */
	      t = a[i];            /* exchange */
	      a[i] = a[j];
	      a[j] = t;
	  }
      }
  }

In the Kermit script language, it goes like this:

  ass \%m \feval(\%n-1)    ; Loop limit for outer loop
  def \%i 1                ; Outer loop.  Assign initial value to loop control.
  :itop                    ; Where to come back to when iterating.
  if > \%i \%m goto ibot   ; Completion test.
  def \%j \feval(\%i+1)    ; Inner loop, same deal.
  :jtop
  if > \%j  \%n goto jbot
    if not lgt \&a[\%i] \&a[\%j] goto skip  ; Compare elements i and j.
    ass \%t \&a[\%i]                        ; Out of order, so exchange them. 
    ass \&a[\%i] \&a[\%j]
    ass \&a[\%j] \%t
  :skip
  incr \%j                  ; Increment the inner loop control variable
  goto jtop                 ; and go back for next iteration, if any.
  :jbot                     ; Increment outer loop variable
  incr \%i                  ; and re-iterate.
  goto itop
  :ibot                     ; Come here when done.
  echo sort complete

This is definitely ugly compared to real FOR loops (it looks like compiler
output), but it gets the job done.  Not that you would want to sort any very
large files in a Kermit script anyway...  The overwhelming benefit is that
you can put any number and combination of commands inside the loop.

But notice how mechanical the elaboration of the FOR-loop is.  Maybe a Kermit
macro could be written that does the bookkeeping.  Here's a first attempt.
A macro called FOR is defined which accepts as arguments a variable name,
an initial value, a final value, an increment, and an object command.  It then
constructs a new macro from these arguments and executes it.  The reason a
secondary internal macro must be defined is so that variable names (rather
than their values) can be dealt with.

  def for assign xxx define \\\%1 \%2,-
  :top,-
  if > \\\%1 \%3 goto bot,-
  \%5,-
  incr \\\%1 \%4,-
  goto top,-
  :bot, return,-
  do xxx \%1 \%2 \%3 \%4 \%5

This first try did not work at all because the very first comma cut off the
interior ASSIGN command, and all the subsequent commands became part of the
FOR definition rather than the XXX definition.  So... ckuus5.c was changed
slightly to allow another kind of grouping, namely if a macro definition
starts with a curly bracket, then commas are treated as ordinary text rather
than command separators up until the matching closing curly bracket.  Now we
can write:

  def for assign xxx { define \\\%1 \%2,-
  :top,-
  if > \\\%1 \%3 goto bot,-
  \%5,-
  incr \\\%1 \%4,-
  goto top,-
  :bot, return },-
  do xxx \%1 \%2 \%3 \%4 \%5

And this works.  As an example of its use, the following statement echoes the
word "oofa" ten times:

  for %i 1 10 1 { echo oofa }

The brackets around "echo oofa" group these two words together as a single
macro argument.  To print the elements of an array \&a[] of size \%n, you
might expect to be able to write:

  for %i 1 10 1 { echo \&a[\%i] }

But this doesn't work because the array subscript gets evaluated too early;
it is turned into a constant (the null string if \%i has not been defined yet
elsewhere, otherwise whatever \%i's current definition is).  To postpone its
evaluation until the proper moment, put it in a macro definition:

  define xx echo \&a[\%i]
  for i 1 10 \%n xx

or use the \fliteral function:

  for %i 1 10 1 { echo \fliteral(\&a[\%i]) }

What about nested FOR-loops?  There remains one obstacle.  The FOR macro
defines another macro which is the "compilation" of the FOR statement, and
then executes the generated macro.  As you can see above, the name of this
interior macro is "xxx".  A FOR-loop within a FOR-loop will thus redefine the
exterior loop's xxx macro out from under it.  How do we create a new macro
that won't destroy the old one?  We must save and restore the old macro's
definition upon entry and exit.

For this we need two new built-in functions: \fdefinition(macro) and
\fcontents(variable).  The former returns the definition of the macro whose
name is given as the argument, the latter returns the definition of the given
variable.  Both results are unexpanded (i.e. variables, functions, and other
backslash codes are not interpreted).  Without these functions, the text of
the macro definition would be changed at the time it is saved and restored.
We just want the plain text.  Here is the new (and final?) version of the FOR
macro:

  def for if def _floop assign \%9 \fdefinition(_floop),-
  else define \%9,-
  assign _floop { define \\\%1 \%2,-
  :top,-
  if > \\\%1 \%3 goto bot,-
  \%5,-
  incr \\\%1 \%4,-
  goto top,-
  :bot, return },-
  do _floop \%1 \%2 \%3 \%4 { \%5 },-
  assign _floop \fcontents(\%9)

This one checks to see if a FOR-loop is already active.  If so, it fetches its
definition and stores it in its own local variable \%9 (an unused "macro
parameter").  Remember, \%0..9 are on the macro stack, so nested FOR loops do
not have to worry about writing over each other's \%0..9 variables, and labels
are also local to each macro invocation, so there is no confusion over having
":top" and ":bot" labels in each macro.

Let's use the new FOR macro to bubble-sort our array \&a[] of \%n strings
again:

  ; First define macros
  def compare if lgt \&a[\%i] \&a[\%j] do swap
  def sort do for %j \%i \%c 1 { compare }
  def swap ass \%t \&a[\%i], ass \&a[\%i] \&a[\%j], ass \&a[\%j] \%t

  ass \%m \feval(\%c-1)        ; Loop limit for outer loop
  for %i 1 \%m 1 { do sort }   ; Sort the array.

This works, good.  But after passing this hurdle, I realized that it would not
be "user friendly" to give users a FOR macro if they wanted FOR loops; it had
to be built into the program, and had to work like other commands.

So I restored the parsing of the FOR command to ckuusr.c, so now it looks like
a built-in command, "?" works on each field, etc.  The final FOR definition
listed above was added to C-Kermit's list of predefined macros under the
internal name of "_forg" (and another one called "_forl" for backwards
looping, see below).  This setup has the added benefit that the object command
can be a list of commands, almost like in C.  Example:

  for \%i 1 3 1 { echo foo, echo bar }

Variables or functions on the FOR command line, except for the loop control
variable (\%i in the example above) are evaluated before the loop begins.  So:

  def \%i xxx
  for \%i 1 3 1 { echo \%i }

will print 'xxx' three times, instead of '1', '2', '3', as you might expect.
To get the name of a variable or function rather than its value into a loop's
object command, use \fliteral(), as in:

  for \%i 2 10 2 { echo \flit(\%i) }

Within the loop, you can't use \fliteral() on the loop initial value, final
value, or increment, which means you can't refer to them by name within the
loop, so you can't change them from inside.  For example, if you do this:

  def \%x 10
  for \%i 1 \%x 1 { echo \flit(\%i), if = \flit(\%i) 2 assign \flit(\%x) 5 }

the loop will still print 1 to 10, rather than stopping at 5.  The assignment
of 5 to \%x will indeed occur, but the loop is not using this variable for the
loop limit, but rather its value at the time the loop started.  If you want to
escape from a loop early, use the RETURN command, as in:

  for \%i 1 10 1 { if > \flit(\%i) 5 return, else echo \flit(\%i) }

Nested FOR loops work, too:

  for %i 1 3 1 { for %j 1 3 1 { echo oofa! } }

This writes "oofa!" 3 x 3 = 9 times.  For readability, you can break the
command up into multiple hyphenated lines and indent, like in a structured
language:

  for %i 1 3 1 { -
      for %j 1 3 1 { -
          echo oofa! -
      } -
  }

Here's a more complicated example, illustrating that multiple statements can
be grouped at different levels.  This kind of thing will work only if you get
the braces, commas, and dashes just right.  (The commas are somewhat like
Algol semicolons -- they are command SEPARATORS, not terminators like C
semicolons.)

  for \%i 1 3 1 { -
      echo oofa,-
      for %j 1 2 1 { -
	  echo foo, -
	  echo foo again -
      },-
      echo bar -
  }

Notice that loop control variables are written without the "\" prefix.  The
"\" can be omitted in contexts where only variable names are allowed, and in
fact it is NECESSARY to omit the backslash on the inner loop variable, or else
the \%j would be evaluated and replaced by whatever the current value of \%j
is at the time the command is executed.  You can also use \fliteral() here:

  for \%i 1 3 1 { -
      for \fliteral(\%j) 1 3 1 { -
          echo oofa! -
      } -
  }

\fliteral() is also used to refer to loop variables inside the object command.
But in nested loops, one is not enough.  You need one \fliteral() for each
level of loop nesting:

  for %i 1 3 1 { -
      for %j 1 3 1 { -
          echo \flit(\flit(\%i:\%j)) -
      } -
  }

When you have more than one level of FOR-loop, it can be a little clearer to
define the loop's object command (or commands) as a macro:

  define print_loop_vars echo \%i:\%j:\%k
  for %i 1 3 1 { -
      for %j 1 3 1 { -
          for %k 1 3 1 { -
              print_loop_vars -
          } -
      } -
  }

As a practical example, let's reconstruct our sorting loop to use a nested FOR
loop (you might need special glasses to read it):

  def swap ass \%t \&a[\%i], ass \&a[\%i] \&a[\%j], ass \&a[\%j] \%t
  for %i 1 \%m 1 { -
      for %j \flit(\%i) \%c 1 { -
	  if lgt \flit(\flit(\&a[\%i] \&a[\%j])) do swap -
      } -
  }

Note that in order to make the inner loop variable's initial value become the
outer loop variable's current value, one level of "literalization" is needed,
whereas within the inner loop two levels are needed.  The "swap" function is
defined as a macro only to keep the the function minimally readable.

Finally, it should be mentioned that negative values are allowed in the loop
parameters, and so is backwards looping:

  for %i +5 -5 -1 { echo \flit(\%i) }

Kermit reverses the loop test automatically if the loop increment is negative.
Increments of zero are not allowed.

And the last addition to edit 134, two new functions: \fcount(filespec), which
returns the number of files that match the given file specification, and
\fnextfile(), which returns the next file name (it returns the null string if
(a) \fcount has not been called yet, (b) there are no more matching
filenames).  Here's an example of using these functions:

  def list if not def \%1 def \%1 *,-
  ass \%n \fcount(\%1),-
  if < \%n 0 goto bad,-
  declare \&a[\%n],-
  for %i 1 \%n 1 { \fliteral(assign \&a[\%i] \fnext()) },-
  echo matching files: \%n,-
  for %i 1 \%n 1 { \fliteral(echo \&a[\%i]) },-
  return,-
  :bad,-
  echo Too many files match!

This defines a LIST macro, which gives a directory listing of files that match
the given file specification, and stores each filename in an array element so
that the list could be sorted or otherwise manipulated.  The array is
allocated to be exactly the right size for the number of files.

This mechanism has some potentially useful applications.  For example, suppose
you wanted to send a mixed group of text and binary files in one command.  If
you had some way of telling a file's type from its name you could send each
file in the appropriate mode.  For instance, suppose all files that had ".exe"
in their names were binary and all others were text, and their names (\%n of
them) were stored in the array \&a[]:

  def text set file type text, send \%1
  def binary set file type binary, send \%1
  def typesend if > \findex(.exe,\%1) 0 binary \%1, else text \%1
  for \%i 1 \%n 1 { typesend \flit(\&a[\%i]) }

This example assumes that the other Kermit is in server mode, and is capable
of setting its receiving file mode based on C-Kermit's attribute packets.
With MS-DOS Kermit 3.0 (or another C-Kermit 5A, or Kermit-370) as the server,
this actually works.

Left as a trivial exercise for the reader: use a the same trick that made FOR
loops work to implement WHILE loops, DO..UNTIL loops, etc.

------------------------------

5A(133) Wed Apr  4 08:08:02 1990

ARRAYS.  Added the DECLARE command to ckuusr.c (you may also use DCL, which is
an invisible synonym for DECLARE).  This command is used to declare an array
of the form \&a[n], where a is a letter a-z (upper and lower case treated the
same, i.e. as lower) and n is the size of (number of elements in) the array
(any positive number).  Arrays are global and have one dimension, with
subscripts ranging from 0 to n (so really the array has n+1 elements).  Like
other Kermit variables, array element values are always strings.  Examples of
declarations:

  DECLARE \&A[20]    ; Declare array "a" with elements 0-20.
  dcl \&b[20]        ; Can use "dcl" instead of DECLARE (case doesn't matter)
  DECL \&C[\%B]      ; Can use variables, etc, for dimension.
  decl &e[100]       ; Can omit '\' in DECLARE statement (see below).

Array data structures are as follows:

  int a_dim[26];     /* declared dimensions (sizes) of the 26 arrays */
  char **a_ptr[26];  /* pointers to element-lists for each array */

These two structures are compiled into the program -- a total of 208
additional bytes on most machines (26 * ((sizeof int) + (sizeof char **))).
These arrays are initialized to all 0's and NULL's, respectively.  Any array
whose a_dim is zero or whose a_ptr is NULL has not been declared.  The indexes
of the a_dim and a_ptr arrays are 0 thru 25, corresponding to a-z.

Whenever an array is actually declared, an "element list" is dynamically
allocated (malloc'd).  This is an array of string pointers (char *) whose
length is equal to the declared size of the array plus one, that is
(sizeof(char *) * (n + 1)).  These are all initialized to NULL.  The address
of array x's element list is stored in a_ptr[x], and the size of array x is
stored in a_dim[x].

Whenever an array element is defined, space is malloc'd for it and the new
address is stored in the array's element list at the position corresponding
to the index given in the array reference.

Storage for an array element is reworked when the array element is redefined,
and storage is freed when the array element is defined to be the empty string.

Storage for an array can be freed by issuing a second DECLARE command for the
same array.  If the declared dimension is zero, the array and all its elements
are effectively "undeclared" and all storage deallocated:

   DECLARE \&A[0]

There are three kinds of array references.  The first occurs in the DECLARE
command, where any array name \&a-\&z can be given, regardless of whether the
array exists.  Second is any command that assigns a value to an array element,
like DEFINE, ASSIGN, READ, ASK, ASKQ, INCREMENT, DECREMENT, or IF DEFINED.
References in these commands require that the given array already be declared
and that the subscript be within bounds.  Both the first and second kind of
references allow the '\' to be omitted from the array reference.  Examples:

  DECLARE \&A[99]   ; These two
  DECLARE &A[99]    ; are the same

  IF DEF &A[99] INCR &A[99]

The third kind of array reference occurs in any other context, in which the
array reference is substituted by its value.  In this case, the '\' must be
present, and any reference to an undeclared array or an out-of-bounds element
is simply replaced by the null (empty) string.  Examples:

  ECHO Good \&t[\%a], \&n[\%x], how are you today\63

An array index can be any C-Kermit expression, including a numeric constant, a
variable or function that evaluates to a numeric string, or even another array
reference, nested to any reasonable level, for example:

  DCL \&D[\fmax(\%a,\&c[\x0f])]

There is no special mechanism for initializing arrays, but the READ command
does the trick nicely.  For example:

  def \%d 200
  dcl &a[\%d]		        ; Declare a 200-element array.
  set take error off            ; So EOF on READ won't stop the TAKE command.
  open read numbers.dat         ; Open the "numbers.dat" file for reading.
  def \%i 1                     ; Make our array 1-based.
  :loop                         ; Loop to read lines.
  read &a[\%i]                  ; Read a line into current array element.
  if fail goto inited           ; If EOF, done.
  incr \%i                      ; Otherwise, increment array index.
  if not > \%i \%d goto loop    ; If array not exceeded, go back for next line.
  echo Array overflow: \%d!     ; Too many lines, give message.
  dcl &a[0]                     ; Free the storage.
  goto fin                      ; Go clean up.
  :inited                       ; Array initialized successfully.
  echo Array initialized.       ; Give message.
  :fin                          ; Common exit.
  close read                    ; Close the READ file.
  set take error on             ; Put TAKE ERROR back on (if you want it).
  echo Done.

Exercises left for the reader: print the resulting array in reverse order,
or sort it (numerically, lexically), or convert it to upper case and OUTPUT
each line to a remote host, etc etc.

Other methods for initialization were considered.  Most natural would be
something like this:

  DCL &A[6] = null, foo, bar, baz, oofa, hello, goodbye

Unfortunately, the length of the initialization list is limited by the size
of Kermit's command buffer -- something we cannot keep expanding indefinitely!
Other methods (like READ and DATA statements as found in BASIC) are just too
complicated, and C-Kermit is too big already.

Coding for arrays involved:

1. Parse DECLARE command.  ckuusr.c.
2. Add new array handling functions to ckuus5.c: arraynam(), arrayval(),
   dclarray(), chkarray().
3. Add array references to parsing of DEFINE, ASSIGN, READ, ASK, ASKQ,
   INCREMENT, DECREMENT, IF DEFINFED.  ckuusr.c. 
4. Add array member definition to addmac() and deletion to delmac().  ckuus5.c.
5. Add array reference expansion to xxstring().  ckuus4.c.
6. Clean up & remove extraneous code in a lot of places.

OTHER CHANGES IN 5A(133)

In ttpkt() and ttres(), set tvtflg = 0 after successful changing of tty
mode bits so that subsequent calls to ttvt() will take effect!  (Thanks,
Kristoffer.)

Change #ifdef XENIX, #undef NGROUPS_MAX, #endif to #ifdef M_UNIX in ckutio.c
(Warren Tucker).

A while back I changed all index() calls to strchr() calls because some ATT
systems did not have index().  Now it seems that some BSD systems don't have
strchr().  To get around this without a pile of #ifdefs, I added a function
xindex() to ckufio.c, and windex() to ckuus5.c.  These two are identical, and
both do what index() -- a.k.a. strchr() -- does.

Removed the code that was added to ckutio.c:ttres() in edit 130 that would
have tried to do an ioctl() instead of stty() in BSD implementations if
TCSETAW was defined.  Wrong kind of struct (sgttyb vs termio).  (Thanks,
Kristoffer!)

Kristoffer's myread() code now seems to be pretty stable, so it has been
inserted into ckutio.c, and the external #include file ckumyr.c is retired.
makefile updated too.

------------------------------

5A(132) Tue Apr  3 18:23:46 1990

It turns out that some C compilers absolutely refuse to allow long constants
in case expressions.  So, once again, I changed ttsspd().  Now, you pass the
desired speed to it in characters per second rather than bits per second, so
that even 38400 is expressible in a 16-bit int.  Converted all calls to ttsspd
to pass cps instead of bps.  ckutio.c, ckuus*.c.  Note: it is not possible to
put the UNIX speed symbols (B75, B2400, B9600, etc) directly in the ckuus3.c
spdtab[] keyword table because this table is also used in VMS, OS/2, Amiga,
etc, which probably don't have these symbols defined.

In ckuus3.c, rearranged speed keyword table to be alphabetical so that ESC
recognition and abbreviation work correctly in all cases.  This makes the "?"
menu a little bit confusing, but that's how the command package works.  Also I
added 75/1200 to the list of permissible speeds, to support split-speed modems
still used in Britain, Scandinavia, and Europe.  However, the supporting code
in ckutio.c:ttsspd() only works for BSD (stty/gtty) implementations, not for
AT&T.  AT&T UNIX does not allow split speeds.

Finished porting the program to AIX/370 on an IBM mainframe.  Aside from
numerous lint-like changes required to keep the Metaware High C R2.1n compiler
from complaining, the major hurdle was that the loader could not find _ftime
and was trying to use the wrong dir.h material.  This was fixed by adding
"$LIBS = -lbsd" to the make entry to request the "BSD compatibility library",
libbsd.a.  The result was tested from a PC running MS-DOS Kermit 3.01, rsh'd
through a SUN to the IBM mainframe using even parity.  Up- and downloaded a
100K file using 2K packets.  Worked just fine, file dates set correctly, etc.
REMOTE commands work, telnet (SET HOST) works.

Fixed SET LINE code to restore all defaults (tty name, local/remote mode,
speed) upon failure.  ckuus3.c.

Filled in the chktok() function in ckucmd.c.  Previously, it didn't do
anything.

Added an optional third argument to \findex(), namely starting position in
the target string, where 1 (beginning of the string) is the default.  So now:

  def \%a abcxxxabcyyy
  \findex(abc,\%a)                              returns 1
  \findex(abc,\%a,1)                            returns 1
  \findex(abc,\%a,2)                            returns 7
  \findex(abc,\%a,\feval(\findex(abc,\%a)+1))   returns 7

Also made sure that \findex() returns 0 in all cases of error, or where the
search string can't be found in the target string.

CLS command reconsidered.  It seems like it is a bad idea to include this.
The implementation is highly system-dependent, and it opens the door to a
demand for more generalized screen control, which should not be done in the
way the CLS was done.  In BSD we can do system("clear") (pretty high
overhead!).  In AT&T System V (but not earlier) we can do system("tput
clear"), but not in System III.  In non-UNIX systems it's going to be even
more different.  So if we really want to achieve screen clearing without
another 20K of ifdef's in ckufio.c, we'll just have to require the user to
define a macro.  For example, for the VT100:

  define cls write screen \27[H\27[J

or for OS/2 (assuming it's like DOS):

  define cls run cls

For UNIX in general, a Kermit macro can be defined to read the termcap entry,
find the clear-screen sequence, and echo it.  Here is such a macro, which uses
many of the recently added features (especially the new \findex()):

def cls ass \%t \$(TERMCAP),-
 ass \%x \findex(:cl=,\%t),-
 incr \%x 4,-
 ass \%y \findex(:,\%t,\%x),-
 decr \%y \%x,-
 ass \%t \fsubstr(\%t,\%x,\%y),-
 def \%u,-
 def \%x 1,-
:strip,-
 ass \%c \fsubstr(\%t,\%x,1),-
 if not def \%c return,-
 if < \find(\%c,0123456789) 1 goto loop,-
 incr \%x,-
 goto strip,-
:loop,-
 ass \%c \fsub(\%t,\%x,1),-
 if not eq \%c \\ goto next,-
 incr \%x,-
 ass \%c \fsubstr(\%t,\%x,1),-
 if eq \%c E def \%c \27,-
:next,-
 ass \%u \%u\%c,-
 incr \%x,-
 if not > \%x \flen(\%t) goto loop,-
 write scr \%u,-
 define cls echo \%u

This looks pretty awful, but it shows that with patience, you can program just
about anything in C-Kermit macros!  Unfortunately, it's impossible to put
commentary in a macro definition, so it's doubly hard to follow what is going
on.  Briefly, we get the TERMCAP environment variable, find the part between
":cl=" and the next ":", which is the clear-screen definition, strip the
leading digits from it (which denote padding), and translate the remainder
into a string suitable for Kermit's ECHO command (in this case just converting
\E (escape) into \27).

Notice the use of ASSIGN vs DEFINE.  When a variable is being redefined in
terms of itself (that it, its name appears in both the left-hand and
right-hand side of the definition) you must use ASSIGN or else you'll get a
circular definition.

So now the CLS command is removed, and the CLRCMD definition is removed from
ckufio.c.

------------------------------

5A(131) Mon Apr  2 13:27:05 1990

Removed function chkspd() (check speed) from ckuus3.c, and replaced all calls
to it by calls to ttsspd().  These two functions had become redundant.
ttsspd() continues to actually set the speed, but now it also updates the
tttvt and ttraw structures with the new speed.  Added missing speeds (like 50,
75, 200) to the tables of legal speeds.  Needed special handling for 75, since
it is the only rate that's not a multiple of ten.

Removed test from ckuus3.c that forbids the use of "set file collision append".
Tested the result locally and it seems to work, but I don't understand how
this old code snuck back into the working version after it was removed before!

Changed code for READ command to allow for the text-file line termination
conventions of different operating system via the symbol NLCHAR as defined in
ckcdeb.h, more or less the same way that the encode() function does when
sending files.

Changed SET FILE COLLISION REPLACE to SET FILE COLLISION OVERWRITE at John
Chandler's suggestion.  The new name for this option is more explicit about
what it does.

Added variable \v(success), whose value is 0 or 1, depending on current
SUCCESS value.  ckuus4.c.

Added variable \v(line), current communication line or network host.  ckuusr.c.

Removed debugging code associated with \v(input).  Now this variable simply
expands to the null-terminated contents of the circular INPUT buffer.  Let the
nulls and wraparounds fall where they may!  Added code to make sure there is
always a null character at the end of the buffer.  ckuus4.c.

Made cmpop() return new depth after popping, and make dostop() call cmpop()
in a loop until parser is back at top level.  ckucmd.c, ckuus5.c.

Added new function zchkspa(name,bytes) to ckufio.c, and added code to gattr()
in ckcfn3.c to call it.  The intention is to check available disk space for an
incoming file whose attribute packet tells its length.  The function returns 0
if there is not enough space, 1 if there is enough space, and -1 upon any kind
of error.  The new gattr() code will reject the file if zchkspa() returns 0.
However, zchkspa() in ckufio.c is, for now at least, a dummy function that
always returns 1.  Contributions welcome.

Removed the END command.  The use of this word should be reserved for future
constructions like BEGIN..END.  Changed the RETURN command to allow its use in
both TAKE files and macros, but a return value can only be specified in a
macro (because that's the only construction supported by the \fexecute()
function).

Fixed a bug in the READ command.  Previously, it only worked if the backslash
was left off the variable name.  Now both "READ %A" and "READ \%A" work.

Added two new IF conditions for string comparisons:

 IF LGT s1 s2 command -- lexically greater than.
 IF LLT s1 s2 command -- lexically less than.

We already had IF EQUAL for lexically equal.  All three of these treat
alphabetic case according to SET INPUT CASE { IGNORE, OBSERVE }, with the
default action being to ignore case.

Added changes to the makefile, pluse ckufio.c and ckutio.c, to support the two
varieties of RTU 4.x (which apparently have ndir.h in two different places).

------------------------------

5A(130) Fri Mar 30 02:13:12 1990

Another new feature: The ability to read and write to local files with Kermit
commands.  Here are the new commands:

OPEN { READ, WRITE, APPEND } filename
  Opens the named file in the given mode.

READ variable
  Reads the next line from the OPEN READ file into the named variable.
  If a line is read successfully, SUCCESS is set.  Otherwise (like upon end 
  of file), FAILURE is set.  Once you have the line stored in a variable,
  you can do anything you like to it using Kermit's string functions.  One
  useful application would be to have a file of phone numbers that you want
  to call.

WRITE FILE text
  It was already possible to write to the various logs using this command.
  WRITE FILE now lets you write the given text into the OPEN WRITE or OPEN
  APPEND file.

CLOSE { READ, WRITE }
  The READ and WRITE options were added to the CLOSE command.
  If you get an end of file while READing, the READ file is closed
  automatically, but it does no harm to close it after it is already closed.

A READ and a WRITE file may be open at the same time, but not WRITE and
APPEND, which is just a special kind of WRITE.  Here's an example of READ and
WRITE, which copies the input file, uppercasing it and adding line numbers:

  set take error off             ; So EOF doesn't bomb out the file.
  open read foo                  ; Open input file "foo".
  open write bar                 ; Open output file "bar".
  def \%c 0                      ; Make a line counter.
  :loop                          ; Loop to read all lines.
  read %a                        ; Read one line into variable \%a.
  if fail goto done              ; Catch EOF this way.
  increment \%c                  ; Count the line.
  write file \%c. \fupp(\%a)\10  ; Format the text and write it out.
  goto loop                      ; Go back and get more.
  :done
  close read                     ; Finished,
  close write                    ; close the files.
  echo end of file               ; Print a message.

The READ command required the addition of a new function to ckufio.c: zsinl(),
which calls upon zchin() to build a line in the caller's space (without adding
this function, READ would have needed to be called for each character in the
file!).  Turns out that zchin() had some problems, so these were fixed too.

Added new functions, \flpad(string,length,char) & \frpad(string,length,char),
like in SNOBOL, used for printing variable-length data in nicely lined-up
columns.  Example:

def \%n 1                      ; print orders of magnitude
:loop                          ; aligned by decimal point
echo \flpad(\%n,8).0           ; note that trailing arguments can be omitted
ass \%n \feval(\%n * 10)       ; next order of magnitude
if < \flen(\%n) 9 goto loop    ; from one to ten million

Back to the old "why does it take so long to exit?" topic...  I added code
to use ioctl(ttyfd, TCSETAW, ...) in ttres() for BSD, but only if TCSETAW is
defined, otherwise to use the old sleep(1)+stty() method.  Unfortunately,
this code will probably never be executed because TCSETAW is defined in
termio.h, which most BSD systems do not have, and which therefore we cannot
risk putting an #include for in ckutio.c.  Too bad.

Added some #ifdef's to ckutio.c from John Dunlap to differentiate between
HP-UX on the 9000 model 500 and the other models (300 and 800).  Apparently
the 500's don't have <sys/bsdtty.h> or TIOCGPGRP but the others do (???).
Worked from non-context diffs, so may have done it wrong.

------------------------------

5A(129) Wed Mar 28 11:16:23 1990

Because int is a 16-bit quantity in some C implementations, and because speed
is not allowed to go up to 38400 or higher, which is too big for a 16-bit
number, changed the speed variable and the ttgspd() function from int to long.
This required changes all over the program, and has implications for all the
other versions too: Mac, Amiga, OS/2, etc etc.

Changed statistics report to use ints and longs rather than floats, because
some computers might not have floating point support.  ckuus4.c.

Fixed the problem with commas in functions that have multiple arguments.
Previously, such a function worked only once.  Now they work all the time.
ckuus4.c.

Began to add user-defined functions.  Until now, we had macros which could
perform arbitrary actions but return no value, variables which return a value
but do no actions, and built-in functions that do specific actions and return
a value, but no way for the user to define a valued function that performs
actions not available in the built-in functions.

The mechanism chosen for this is the addition of a RETURN statement that can
be used within a macro.  The RETURN statement is just like END or POP, except
it also takes an optional argument, which becomes the return value of the
macro.  The RETURN argument can be any valid Kermit expression: a character,
a line of text, a complicated function call.

The RETURN value can be accessed in two ways: (1) via the \fval() function (no
arguments), which is replaced by the value of the function most recently
called from the current level, and (2) somewhat more useful (but also more
cryptic), the \Fexecute() function.  This function takes a macro invocation as
its argument, and returns the macro's return value, if any.  Thus, \Fexecute
turns any macro into a callable function.

With this mechanism, it is possible to write functions to perform most any
operation.  For example, here is a recursive function, "sum", to add all the
numbers from 1 to the function's argument (e.g. "sum 6" = 21):

  def sum if = \%1 1 return 1,-
    else return \feval(\%1 + \fexecute(sum \feval(\%1 - 1)))

Recursion is possible because macro arguments and return values are stacked.
Kermit presently limits the depth of recursion to a rather small number.  You
can alleviate the typing by using macro definitions:

  def xx echo \fexec(sum \%1)

Now to see the sum of all the numbers from 1 to 5, just type "xx 5".  Also
notice that you don't have to spell out the whole name of the function.

Here's another example, handy for asking yes/no questions and
parsing the user's responses (which can be Y, N, y, n, Yes, No, YES, NO,
OK, etc), and keeps asking them till they give a valid response:

  def yesno :loop, ask \%a \%1\63,-
    if not def \%a goto loop,-
    ass \%a \flower(\%a),-
    if equal \%a ok return YES,-
    if equal y \fsubstr(\%a,1,1) return YES,-
    if equal \fsubstr(\%a,1,1) n return NO,-
    echo Please answer Yes or No, goto loop

This one could be invoked within an IF statement, like this:

  if equal YES \fexec(yesno {Want to play}) goto play
  echo So serious!
  stop

[ *** This note entered much later (Sept 90):
  No it can't!  The parser breaks on the first space in the function
  call.  You have to do this:

  if equal YES \fexec(yesno {Want to play}) goto play
  echo So serious!
  stop
*** (end of this note) ]

A macro function definition itself can contain any Kermit commands, but only
"non-action" commands will actually be executed when the macro is invoked
inside the \Fexec() function (the action commands are SEND, RECEIVE, CONNECT,
SERVER, GET, REMOTE, FINISH, BYE, MAIL, etc -- anything that invokes Kermit
protocol; these commands are ignored) (maybe later this restriction will be
lifted).  If the executed macro fails or does not include a RETURN statement,
then the \fexec() function is replaced by the null string.

Addition of \fexec() required that the command package become reentrant, since
it will normally be in the middle of parsing one command when called upon to
parse a whole series of other commands via \fexe(), and then must return to
where it left off in the original command, and this process can be nested.
Reentrancy was achieved in the cheapest possible way: two new functions were
added, cmpush() and cmpop(), which simply save and restore all of the command
package's global variables and buffers in memory which is malloc'd and free'd.

------------------------------

5A(128) Tue Mar 27 10:00:10 1990

Fix DNIX entries in the makefil (again).

Moved file renaming code from ckcfns.c to a new function in ckufio.c:
zrename(old,new).  There is no portable way to rename a file.  The zrename()
function will have to be added to all ck*fio.c modules.

Added the RENAME command.  This simply changes the name of an existing file
(not a file group).  Creation date and other attributes are not changed.
ckuusr.c.

Added code to CONNECT command to output SO and SI if user types an 8-bit
character while transmitting in the 7-bit environment.  This code is within
#ifdef SOSI conditionals, and presently not enabled.  Untested.

Made a tiny but important change to ttpkt() in ckutio.c for BSD versions of
UNIX (stty/gtty).  Previously, Kermit always used rawmode for packets.  Now,
rawmode is used only if parity is NONE.  This allows Xon/Xoff flow control to
actually work, but only if the user asks for parity (which also means she also
gets 8th-bit quoting).  I don't know if Xon/Xoff ever did work for AT&T
versions.  If not, the AT&T section of ttpkt() needs a similar change.

Fixed INPUT command.  Took hours to track down the problem.  It was that we
forgot to change the variable that is returned by ttinc() in the timed
myread() case from ch to n.

Replaced all references to index() by strchr().  HP-UX and maybe some other
systems do not have index() defined.  Index is just a synonym for strchr().

Changed RS definition in ckcasc.h to XRS, because RS is used for something else
in HP-UX.  RS is not used in Kermit anyway.

Added "extern errno;" to ckucmd.c.  Some pure BSD systems require this because
this statement is not in <errno.h>.  Having it twice doesn't hurt anything.

Fixed references to HZ in msleep() for Tandy 16/6000.

Made default carrier state be "auto", rather than "on".  Defined symbols for
carrier states in ckcdeb.h, and replace numeric references to them throughout
the program by the new symbols.

Fixed zoutdump() to define the variable x correctly before using it as its
return code!  ckufio.c.

Added \Frepeat(string,number) function.  Handy for writing banners, etc,
as in "echo +\Frepeat(-+,39)".

Commas that separate function arguments were interfering with the expansion of
macros, because the commas were converted to CRs.  Changed it so that commas
within parens are accepted literally.  So now you can give commands like
"echo \fmod(\%a,\fmax(\%b,3))".  Also fixed SHOW MACROS to ignore commas
within parens.

------------------------------

5A(127) Mon Mar 26 10:24:17 1990

Put #ifdef NETCONN around new '-j' material.

Added window size, packet length, transmission speed to Ctrl-A status report.
Added transmission speed to STATUS efficiency report.

Added built-in functions.  These are of the form \Fname(args).  The F may be
upper or lower case.  The name may be abbreviated (it's a keyword).  The
args are strings, numbers, variables, or anything else that Kermit can
evaluate.  The function is replaced by its value.  If it fails, the value is
is null (the empty string).  The functions are:

String functions that return a string:
 \Fliteral(arg1)    - Copies its argument literally, without any evaluation.
 \Fsubstr(arg1,arg2,arg3) - Substring of arg1 starting at arg2, length arg3.
 \Flower(arg1)      - Converts arg1 to lowercase.
 \Fupper(arg1)      - Converts arg1 to uppercase.
 \Freverse(arg1)    - Reverses the string argument.

String functions that return a number:
 \Flength(arg1)     - Returns the length of the string arg1.
 \Findex(arg1,arg2) - Returns the position of string arg2 in string arg1.

Integer arithmetic functions:
 \Fmax(arg1,arg2)   - Returns the maximum of its two numeric arguments.
 \Fmin(arg1,arg2)   - Returns the minimum of its two numeric arguments.
 \Fmod(arg1,arg2)   - Returns numeric modulus of arg1 and arg2.
 \Feval(arg1)       - Evaluates the enclosed arithmetic expression.

The latter two categories return a decimal numeric string, or else the null
string if they are given bad arguments or if they fail in any other way.  The
arguments are also numeric decimal strings, like "123", "-234", "+345".  They
cannot be backslash codes like \7 or \x7f unless the backslash codes evaluate
to ASCII digits.  For example \Feval(\o61 + \d49) is legal and returns "3".

\Feval was adapted from a short program written by Howie Kaye of CUCCA.  It
only adds about 4K to Kermit (as compiled on the SUN).  \Feval supports the
following operators:

  Operator  Fix   Precedence   Operation          Example

   (   )              1         Group             ( \%a + 3 ) * (\%1-5)
     !      Post      2         Factorial         \%x! - (\%x-2)!

     ~      Pre       3         Logical NOT       ~\%n
     -      Pre       3         Negative          -\%n

     ^      In        4         Raise to power    2^\%p

     *      In        5         Multiply          \%c * 5
     /      In        5         Divide            \%c / 5
     %      In        5         Modulus           \%c % 5
     &      In        5         Logical AND       \%c & 5

     +      In        6         Add               \%t + \%u
     -      In        6         Subtract          27 - \%x
     |      In        6         Logical OR        \%z | 4
     #      In        6         Exclusive OR      \%z # 4
     @      In        6         Greatest Common   \%z @ 30
                                Divisor

The operands of the expression can be numeric strings or variables, or
functions that evaluate to numeric strings.  The precedence is the normal,
intuitive algebraic (or programming) precedence, and can be altered by the
use of parentheses, which have higher precedence than any other operator.
Spaces may be used to separate operators from operands, but they are not
required.

------------------------------

5A(126) Sun Mar 25 13:11:22 1990

Add makefile entry for DIAB DNIX 5.3 (like sys5r3hdb, but without -i).
Various other changes to the makefile.

From Kristoffer: support in ckutio.c for SET CARRIER { AUTO, OFF, ON }.
Works only for System V, does nothing in BSD.  ON means require carrier during
CONNECT (but not during DIAL), OFF means ignore carrier at all times, AUTO
means choose ON or OFF automatically depending on whether the line has modem
control.  On Xenix, this command must be given before SET LINE, but on other
System V systems it also seems to work after SET LINE.  Added support for this
in ckuus3.c (SET) and ckuus4.c (SHOW).

Fix STATISTICS command to show efficiency as a floating point number instead
of truncating it to a multiple of 10 percent.

Fix SET PROMPT to strip enclosing doublequotes, as in SET PROMPT "HP=Kermit> ".
This lets you add trailing spaces to the prompt.

Allow speed 38400 to be specified.  Use at your own risk!

Replaced myread() and friends with a new version from Kristoffer.  Also
applied many edits to ckutio.c, sent in by Kristoffer several days ago.

Added support for HST Courier modem to ckudia.c, from Tye McQueen at the USU
Math Dept.  Untested.  ckudia.c.

Added setuid support, also from Tye McQueen, to ckufio.c so that files are
opened under user's real uid, in case the program is running setuid to uucp or
some other uid.  This code has been included within #ifdef SETUID conditionals
and is untested, not even compiled.  See ckuker.bwr for additional comments.

Added another contribution from Tye: an option to the SHELL ("!") command to
pipe its output to the remote system, invoked like this: "!>command", rather
than simply "!command".  Works if you have previously SET LINE.

Tye sent in lots of other changes too, but I think most of them are covered
already by contributions from Kristoffer, Bo, and Warren.

Changed ckutio.c to always put permission of lockfile at 444.  Nobody knew of
any reason why it should be 644.  Let's see who hollers.

Changed ckutio.c to call offgetty for the ATT7300 BEFORE it opens the device,
rather than after, as JRD suggested in msg of 14 Mar 90.  Also added code to
put getty back on the line in case the open() fails.  I have no idea if this
will make the UNIX PC work again.  Joe?

Added code to tthang() to hang up a network connection.  Previously, hangup
was a no-op for network connections.  ckutio.c.

Banged on sliding windows a bit.  Found one case where they would consistently
fail, namely when the receive packet-length is adjusted downwards if the
window slots are increased.  It wasn't being adjusted far enough, so the
receiver was asking for more characters than it could store in its buffers.
This is now fixed.

In response to a complaint from Kristoffer that C-Kermit once core-dumped in
nack() because of a reference to r_pkt[j] when j was badly out of range, put a
test in getsbuf() to catch when it is called with an invalid argument.  Found
several other cases where a bad array or structure index could be used on the
packet data structures, including the bit in nack() where a bad index was used
to access the packet structure retry count.  Hopefully, all of these are fixed.
ckufn[23].c.

Further investigation showed that C-Kermit, when told to change its window
size or its receive packet length, would sometimes calculate a new receive
packet length that was longer than its receive packet buffer, which would
cause horrible protocol failures.  Made this calculation more conservative,
and now the problem seems to have gone away.  ckuus3.c, ckcfns.c.

Started up a multi-file multi-megabyte sliding-window/long-packet transfer
with debug log on to see how long it would go before it failed.  Failure
occurred at 3/4 megabyte.  Found and fixed the cause: if C-Kermit got a
timeout waiting for the ACK to the last packet of a file, it would attempt to
resend all unACK'd packets.  But at this point, there is a slot allocated
for the Z packet, but the Z packet is not formed yet.  The attempt to transmit
this unformed packet caused the problem.  This is now fixed, I hope.  ckcfn2.c

More work with sliding windows.  Found several other sources of error.  For
example, if a NAK is received for a packet that hasn't been sent yet, Kermit
would give up.  Now it just ignores the NAK.  Several others too hard to
explain.  All fixed.  Transferred several megabytes successfully with 4 window
slots, packet length 746.

Commented out the code in ckuus3.c that prompts the user for a password when
she types REMOTE CD dirname.  The only computer that ever required a password
for changing directories was the DEC-20, and they're practically all gone now.
Add -DDIRPWDRP to your makefile entry if you want this behavior restored.

Added -j to command line options to request a network host (like SET HOST).

Changed zgtdir() to declare a static buffer in the Sys V case, to prevent Sys V
getcwd() from malloc'ing more memory each time it is called, and never freeing
it (Bo Kullmar, Warren Tucker).  ckufio.c.

------------------------------

5A(125) Fri Mar 23 19:39:41 1990

Tried to compile C-Kermit under the IBM AIX/370 v50 prerelease on an IBM 370
mainframe using "make bsd".  The AIX compiler (MetaWare High C), picked up a
lot of lint, which I fixed.  Found that AIX/370 is a lot like NeXT or SUNOS4
-- BSD, but with signal() type void rather than int, but also with getuid()
having a different type (unsigned long) than most other Unixes, and something
to do with dir.h and struct direct vs struct dirent.  Made a new makefile
entry, aix370.  Not finished, to be continued when/if AIX comes up again.

Changed ttsspd() to actually set the speed of the terminal device, provided
the speed is legal, and the device is not the controlling terminal.  Changed
ttgspd() to actually read the speed of the terminal device.  It looks like now
we can actually rely on knowing the transmission speed, at least in UNIX.
This business still needs a little cleaning up because the speed is still set
(redundantly but, I think, harmlessly) in some other places, like ttpkt() and
ttvt().  ckutio.c.

Added code to SET RECEIVE PACKET-LENGTH to adjust the receive timeout based on
the packet length and the (now known) transmission speed, and to issue a
message.  This alleviates the problem with insufficient timeout interval when
using very long packets.  ckuus3.c.

Discovered that MS-DOS Kermit 3.01 has a bug in which it sometimes sends
badly formed generic server commands.  For example, REMOTE SPACE and REMOTE
HELP send "^A# G,", i.e. a generic command without a command field.  C-Kermit
never expected this to happen and became terribly confused.  Added a couple
lines of defensive code to ckcpro.w to handle this case, and it now recovers
nicely.

Improved handling of errors in TAKE files and macros.  SET TAKE ERROR ON is
the default, meaning that TAKE files should be terminated upon any kind of
error.  Previously this occurred only upon parse errors.  Now it happens
whenever a command sets SUCCESS to zero.  Same deal for SET MACRO ERROR ON.
ckuus5.c.

Added changes to ckutio.c to better support background operation, from Tor
Lillqvist in Finland.  In his words: "At least on HP-UX, doing a TCSETAW
ioctl() when in background causes a SIGTTOU signal.  I put a test in concb()
to check if we are in a TAKE file.  I added testing for background operation
for HP-UX in the same manner as for BSD.  Additionally, IMHO, if we are
running under a job control shell, there is no need to ignore signals, as we
will not get them when we are not in the terminal's active process group."  I
moved Tor's take-file test out of concb, because ckutio.c must not depend on
external variables.  Also from Tor, in ckucmd.c: "If you suspend an
interactive Kermit, when you fg it again, getchar() returns -1 with errno ==
EINTR.  I check for this in gtword()".  I put this code under #ifdef EINTR
for portability.

------------------------------

5A(124) Wed Mar 14 22:29:55 1990

Edit 124 is confined to the addition of one new command:

  SET FILE COLLISION { APPEND, BACKUP, DISCARD, RENAME, REPLACE, UPDATE }

Nothing else was touched.  SET FILE COLLISION tells what to do if a file
arrives with the same name as an existing file.  See Christine Gianone's
specification in Info-Kermit V11 #1.

Step 1: Parse the command, add info to SHOW FILE.

Step 2: Implemented REPLACE, RENAME, and BACKUP (easy).  REPLACE is the same
as WARNING OFF, RENAME is the same as WARNING ON.  BACKUP (rename the existing
file, rather than the incoming file) required a change to ckcpro.w, to allow
for the case where rcvfil() fails to rename (haven't figured out how to
actually make this happen).  Used link() and unlink() library calls to do the
renaming, rather than the newer rename() call, which is not portable (some
systems don't have it, some systems reverse the order of the arguments).
Assume link() and unlink() are available in all C environments.  Coordinated
SET FILE WARNING and SET FILE COLLISION to take each other into account.

Step 3: Made BACKUP be the default collision action.  No more accidentally
destroyed files.  It's just like having DEC-20 or VAX/VMS generation numbers.

Step 4: Implemented DISCARD.  This one means: don't accept the incoming file
and don't touch the existing file.  This is very handy for resuming
interrupted wildcard transfers - only accept the ones that don't exist yet.
Seems to work fine in both the attribute and non-attribute cases.  But it
needs to be tested by sending files to it from a computer that does not
implement the file interruption mechanism (X in ACK to D packet).  For the
latter case, additional code was added to ckcpro.w to receive and acknowledge
the packets, but to not open, write to, or close the file.  If anyone tests
this and finds problems, let me know.  I also considered just replacing the
real filename by /dev/null, but then I would have to add system-dependent
names for the null device for each kind of system that C-Kermit supports, and
I have no idea how to do this for Macintosh, Data General, etc.

Step 5: Implemented APPEND.  This required definition of a new file
information structure which is set up in opena() and passed through openo() to
zopeno().  Kermits like VAX/VMS that want to use this information will have to
add this structure (as well as the attribute structure) to zopeno().  (The
filinfo structure contains all the VMS-like file attributes: type,
organization, blocksize, record length, etc, as well as disposition - new,
old, append.)  zopeno() should now be called with 4 arguments, and if you
don't have attribute and file info structures to call it with, then use NULL,
as in zopeno(n,name,NULL,NULL).  If you're working on ck?fio.c (where ? != u),
make sure that any internal references to these structures first check to make
sure the structure pointer is not NULL, otherwise, core dump city.

The APPEND option should be used with caution: appending a text file to a
binary file or vice versa, appending anything to an executable program image,
etc, could ruin things.  But it's also handy for accumulating data in log
files.

There is now yet another new header file: ckcfil.h.  This contains the symbols
for values of the file-related variables (organization, carriage control,
disposition, etc).  Updated the makefile dependencies, etc.

Step 6. SET FILE COLLISION UPDATE.  This turned out to be a lot easier than
I expected, thanks to code Bo Kullmar contributed for setting the file date
from the attribute packet.  I simply made a minor modification to this
function, zstime(), adding a third argument which is a function code.  If 0,
it sets the file's creation date (as now).  If 1, it compares the creation
date of the given file with the one in the attribute packet, and returns the
result of the comparison as the value of the function.  The function is called
in this new way from gattr() in ckcfn3.c.  Preliminary tests show it to work
just fine, even if the sender does not get an attribute refusal (because then
the file interruption mechanism kicks in).  The date comparison for UNIX is
done by simply comparing the two internal date formats (time_t data items)
arithmetically.  This works properly on the SUN in the BSD environment, but
needs testing elsewhere.

------------------------------

5A(123) Mon Mar 12 13:55:21 1990

The news from Sweden is good, the various pointer referencing/dereferencing
foulups are fixed.  In ckutio.c, removed a redundant second copy of the
"close( open() ) magic" in ttopen(), which was causing problems, and added
parity stripping to ttxin(), which apparently was lost in the previous
activity.

Added fixes from Jay Rouman at U of Michigan for Tandy/TRS16/16000 Xenix 3.0.

Added fixes to the makefile for SCO/UNIX 3.2 from Warren Tucker.

Generalized the network support structure, so that whoever adds in ATT streams
or DECnet support will have an easier time -- the commands are already there,
and a new header file, ckunet.h, was added to make the network type symbols
available to all modules.

Made SET BLOCK use cmnum() instead of cmkey().

Added CLS command (clear screen), for use in interactive scripts.

Added SET DEBUG SESSION to display control characters graphically.  Also, on
telnet connections, to display telnet negotiation characters rather than act
on them.  Works like in MS-DOS Kermit: A = A, ^A = Ctrl-A, ~A = A with 8th bit
set, ~^A = Ctrl-A with 8th bit set.  Screen output is one long line, so we
must rely on the terminal to wrap (this can be fixed later).  This display
can, of course, be ambiguous (e.g. is ^^ Ctrl-^ or is it two ^'s in a row?).
Later maybe we can make some use of termcap to use various kinds of
highlighting.

Experimented with telnet some more, still can't figure out why connections to
the IBM mainframe don't work right.  I don't see the ECHO negotiation...  How
does UNIX telnet know it's supposed to echo?  Logging its negotiations didn't
show anything about the Telnet ECHO option.  Added WONT ECHO to initial
options sent by netopen().  Added lots of debug log information in doopt() in
ckucon.c, but it doesn't help.  Maybe echo setting occurs in the telnet
subnegotiations, but the log doesn't reveal any subnegotiations!  Also,
another problem with telnetting to IBM mainframes: blank lines (e.g. when you
type two carriage returns in a row) are not sent at all.  You have to type a
space first, then carriage return.  If you do this, and also SET DUPLEX HALF
before telnetting to an IBM mainframe, it'll work pretty much OK.

Added { SET, REMOTE SET } ATTRIBUTES to control all the individual attributes
that C-Kermit supports, as in [ REMOTE ] SET ATTRIBUTE DATE OFF.  See
Christine Gianone's article in Info-Kermit V11 #1 for a description.  Did not
make separate cases for IN and OUT (this is compatible with MS-DOS Kermit),
even though the variables are set up that way internally.  Also added SHOW
ATTRIBUTES.  Also added server end of REMOTE SET ATTRIBUTES.  Also added code
to MAIL and REMOTE PRINT commands to give a parse error if the DISPOSITION
attribute (or all attributes) are set to OFF...  A lot of harmless busy-work.
Did some testing with packet log on, and it seems to work right; more testing
needed.  REMOTE SET ATTRIBUTES is not implemented very well; since the IN /
OUT cases are not separated, the "IN" case is chosen.  Worry about this later.

------------------------------

5A(122) Sun Mar 11 12:00:22 1990

In Sweden, the compilers were upset by "if (*f)" in the ckucmd.c functions,
where they are checking to see if they were called with a pointer to a
preprocessing function.  Changing this to "if (f)" seems to fix it.

Fixed GOTO label parser to not allow space or dot after :, nor to allow a
label that consists only of a colon.  The dot is reserved for future use
(internal labels for use with FOR/WHILE loops, etc).

Add fancy file system support via new parameters to SET FILE and REMOTE
SET FILE commands:

Command                                                  Variable
   ORGANIZATION { INDEXED, RELATIVE, SEQUENTIAL }         forg
   FORMAT { FIXED, RCW, STREAM, UNDEFINED, VARIABLE }     frecfm
   CARRIAGE-CONTROL { FORTRAN, NEWLINE, MACHINE, NONE }   fcctrl
   BLOCKSIZE number                                       fblksiz
   RECORD-LENGTH number                                   frecl

1. Symbols defined in ckuusr.h.
2. Global variables declared to ckuusr.c and extern'd in ckuus*.c where needed.
3. Keyword tables and parse routines added to ckuus3.c.
4. Display added to shoparf() in ckuus4.c (screen space is getting tight!).
5. Added handling of blocksize when reading or sending attribute packets.
   Unfortunately, the attribute mechanism does not really allow for any of
   the other file parameters.  The Kermit protocol will have to be extended
   before we can do this.  ckcfn3.c.
6. Added server end of REMOTE SET for the new file variables in ckcfns.c.
   Had to define new codes for some of them on the fly!

So now the file parameter information can get into and out of the program.
I'll leave it to Mark Buda to actually make use of it in the VMS version.  In
UNIX, none if it does anything.  Later, all the code and commands for these
things will be ifdef'd for VMS only, so as not to clog up memory on UNIX
needlessly, or throw UNIX users into a panic.

Also, added SET NETWORK { DECNET, TCP }.  For now, it just sets a variable,
nettype, and if you say DECNET, it won't let you SET HOST or CONNECT.  Mark
can fill in the DECNET support for VMS if he wants to, and maybe somebody else
could fill in DECNET support for Ultrix (I wonder if it uses the sockets
interface...).

More help from Sweden.  Turns out that an innocent-looking debug() statement
in xxstring() was causing core dumps.  Don't know why, but I removed it and
the core dumps went away.

Various people complained that CBREAK was undefined when compiling on an
AT&T-based system.  My fault, I put a reference to it in a bad place in
ckutio.c.  Removed, fixed, apologies.

Added SET CARRIER { ON, OFF } command.  The intention is to tell Kermit
whether to pay attention to carrier.  Default should be ON, as it behaves
presently.  If OFF, Kermit should not refuse to communicate in the absence of
a carrier signal on the SET LINE device (CLOCAL mode in Sys V, not sure how to
do this in BSD).  For now this command does nothing.

Removed side effects of SET LANGUAGE (i.e. the setting of file and transfer
character sets).  Too confusing.

Added SET and SHOW TRANSMIT commands.  SET TRANSMIT FILL allows a fill
character to be specified for empty lines, LINEFEED says send linefeeds too,
PROMPT specifies the host turnaround character to wait for.  Problem: if file
type is TEXT, but last line of file does not end with linefeed, then last line
is not sent.  Fix later.

Added optional numeric operand to INCREMENT and DECREMENT, so now you can
add or subtract any number (not just 1) to/from any variable.  The operand
can be positive or negative, e.g. INC \%a, DEC \%a 100, INC \%a -33.

Added two new variables, "xitsta" (exit status, initially zero) and "what"
(what I was doing).  The latter can be SENDing (1), RECEIVING or GETTING (2),
or REMOTEing (4).  If any of these fails, the "what" that failed is OR'd into
the exit status, except for VAX/VMS which has its own wierd set of program
exit status codes.  So now UNIX Kermit exits with 0 if all protocol operations
worked, 1 if one or more SENDs failed, 2 if one or more RECEIVEs or GETs
failed, and 4 if one or more REMOTE commands failed, and if more than one kind
of command failed, their what's are OR'd together (is this English?), just
like in MS-DOS Kermit.  For VMS, if any of the failure bits are set in xitsta,
Kermit exits with BAD_EXIT.  Mark B. can figure out what to do about the
message and other fields that go into the VMS return code.

Spent the rest of the evening moving the code to a NeXT, an Encore, a
VAX/Ultrix system, and a VAX/VMS system, and compiling it on each one, and
removing minor compilation problems at each step.  Updated CKVKER.COM to
compile all the new modules that have appeared since 4E.  Meanwhile, another
report of core dumps arrived from Bo Kullmar in Sweden, who is compiling the
program on an AT&T System V system.  Thanks to his digging, it turned out the
culprit was (once again) xxstring() in ckuus4.c.  Constructions like *(*s2)++
and (*n)-- seemed to be causing memory faults on his system.

I finally managed to make the program compile and link on the SUN using the
/usr/5bin version of cc (the problem was that /usr/5include/ctype.h has some
very strange definitions for tolower() and toupper() -- see new makefile entry
for sunos4s5) and was then able to reproduce Bo's core dumps, but only in this
environment, not in any of the others.  Tentative diagnosis: the System V C
compiler must be generating different code for these references.  So I rewrote
xxstring() not to write to variables through pointers, and could no longer get
the core dumps.  I can't imagine why this would make a difference, and only
time will tell if it really does...

------------------------------

5A(121) Sat Mar 10 12:02:23 1990

Changes to ttres() in ckutio.c.  Restore separate stty() and ioctl() for
AT&T and BSD, respectively.  Also, in BSD versions there is a sleep(1) before
restoring the file descriptor to its old modes to allow pending i/o to finish
first, otherwise the stty() could cut it off.  What is really needed here is
an fflush() to force out all pending output, but fflush() wants a file
pointer, and we have a file descriptor.  For SUNOS4 only, which is what I have
here to work with, changed the sleep(1) to fflush(&_iob[ttyfd]).  If
everybody's stdio.h uses the same structure and names for file pointers, then
this will work elsewhere too.  If so, it can speed up exit from Kermit
noticeably.

In ckucon.c (CONNECT command), pause() if coninc() returns -1 to prevent
endless loop when Kermit run from cron jobs and gets EOF on stdin.  This
should do no narm, as there was already another pause() elsewhere in this
function.

Began adding in Kristoffer Eriksson's recent changes.  First, remove the
business about errno 9999 from the CONNECT command.  According to Kristoffer,
ttinc() now should return -1 only upon a real error, in which case the CONNECT
session should be terminated.  In other words, ttinc() should now always
behave like a blocking read().

Next, a new ttchk() which takes myread() buffers into account, and which uses
the rdchk() system call on systems where it is available: currently, only
known to be available on Xenix/286 and Xenix/386, so a new symbol RDCHK is
defined in the makefile for them and used in ttchk().

Next, in ttinc(), in the untimed-read case for network connections, return -1
immediately if an error is encountered.

Next, extensive changes to ttopen().  Probably still far from done, but at
least I hope this brings local code in sync with Kristoffer.  Sent him the
changes so far.  Now, hands off system-dependent code for a while.

Fixed REMOTE SET BLOCK-CHECK.

Change xxstring to take a length argument, and all calls to it to pass a
length argument.  Since it's recursive, we have to pass the address of a
common int that each incarnation of xxstring can update.  If the evaluated
string has reached the end of the expansion buffer, xxstring returns -1.
Seems to work.  ckucmd.c functions changed to return -2 whenever xxstring
returns -1, so user gets the usual parse error message (?Invalid).  Not
terribly informative, but better than a core dump.

Add new doopt() function to ckucon.c, within #ifdef NETCONN conditionals, to
read and process telnet negotiation options, so that they don't appear on the
screen as curly braces and similar noise-like characters.  This might cause
problems if the user has set host to a service other than telnet, but this is
an undocumented feature, and other services probably don't use telnet IACs
anyway.  Also, add telnet protocol to send BREAK to ckutio.c ttsndb().
Tested, it works.

The doopt() function makes a minimal attempt to read and reply to telnet
negotiation options from the host.  In particular, it tries to set the duplex
flag according to the host's WILL/WONT ECHO command.  However, in the one
place where we really need this to work, it doesn't seem to: telnetting to an
IBM mainframe.  For some reason, some (not all!) of the IACs come across with
their 8th bit lopped off, so the WONT ECHO command is not recognized at all
(see fancy "telnet" entries in debug.log).  Oh well, it's better than it was
before.

Fix SHOW MACROS to (a) change comma into comma-dash-newline, and (b) give
a "more?" prompt after each screenful.  Might also need to give this treatment
to some other SHOW commands.

Added WRITE command: WRITE { DEBUGGING, PACKET, SESSION, TRANSACTION } string
Different from MS-DOS Kermit's version: no extra keywords (like DATE,
DIRECTORY, etc) are required because you can imbed \V(xxx) variables in the
string.  Like in MS-DOS Kermit, WRITE does not add a newline at the end.

------------------------------

5A(120) Thu Mar  8 22:22:41 1990

Fix parsing of TRANSLATE command.  It was core dumping, thanks to a typo.
Also, change function cmofi() in ckucmd.c to not object to opening the
job's controlling terminal as an output file (just skip the check for write
permission if the filename is equal to CTTNAM as defined in ckcdeb.h).

Found and fixed a missing closing comment delimiter in ckcxla.c, which was
causing Latin-1 to ASCII translations to come out as total garbage.

Add to xxstring() the ability to expand environment variables.  Syntax:
\$(name), e.g. \$(TERM), \$(HOME), etc.  This was done in ckuus4.c using
getenv().  I'm assuming that any C compiler that builds a C-Kermit that uses
the ckuu*.* modules will have a getenv() function (it's even in the C book).
If not, it can be conditionally compiled, or even moved to ck*fio.c.  Should
also actually produce results for VMS, OS/2, and DOS, as well as UNIX.

Added builtin named variables.  Syntax is \V(name), where 'name' is one of:
argc, count, date, directory, time, version.  The name is case independent,
and can be abbreviated like other keywords: \V(ARGC), \v(argc), \v(Cou), etc.
The contents of the parens are taken literally and not further expanded.  For
example, you can't "define \%a count" and then "echo \v(\%a)".  The \V()'s are
read-only variables, expanded by xxstring().  Their values can, of course, be
assigned to ordinary read/write variables.  Later, it might be worth expanding
this capability to many more of Kermit's built-in variables, like block check
type, receive packet length, parity, speed, etc.

------------------------------

5A(119) Fri Mar  2 13:35:34 1990

Discovered that having command-parsing functions run xxstring ruined macro
argument grouping via braces, because xxstring was stripping enclosing
brackets from its argument.  Removed the code from xxstring that does this.
There's no reason to do it anyway, except that MS-DOS Kermit does (compare
"echo {oofa}").

Changed variable rules to allow \%0...\%9 to be global variables when no
macros are active.  Within macros, each macro level still has its private set
of \%0..\%9 arguments on the stack, so the only difference is these variable
names are now available at top level too (in interactive commands or take
files).

In ckutio.c, changed congm() (get console tty modes) to open CTTNAM (typically
"/dev/tty") and get its modes, rather than using file descriptor 0.  This
should solve the problems with restoring improper tty modes after running with
standard i/o redirected.  Suggested by Frank Prindle.

Put changes into ckufio.c and ckutio.c from Warren Tucker for SCO UNIX 3.2,
and added an entry to the makefile.

Other minor cleanups to ckutio.c.

NOTE: I did NOT get around to doing anything with Kristoffer's ckutio code,
myread(), etc.  It is still in place as originally sent.  In particular, no
changes were made to the business about how errors and communications
disconnect are returned to the conect() function (terminal emulator).

------------------------------

5A(118) Thu Mar  1 18:51:47 1990

Changed the rules a bit for backslash codes: \\ now becomes one backslash
rather than remaining two.  This allows for constructions like the following,
in which variable names can be constructed on the fly, as in the following
macro that displays its arguments (a poor person's substitute for arrays or a
shell-style FOR loop):

  def xx set count argc,def %c 0,-
  :loop,-
  increment %c,-
  assign %a \\%\%c,-
  echo \\%\%c = "\%a",-
  if count goto loop

The use of backslash to quote special characters, introduce variable names,
command line continuation, etc, is pretty inconvenient for OS/2 or DOS users,
where backslash is a directory separator.  So I changed all references to
backslash as a quote character from literal '\\' to the symbol CMDQ, which is
defined in ckcdeb.h.  So the OS/2 version can have a different quote character
like, for instance, accent grave or circumflex (but not ampersand, percent,
star, question mark, atsign, pound sign, brace, etc., which all have other
uses already, or may soon).  It would also be possible to introduce a runtime
command like SET COMMAND-QUOTE to let the user specify it herself, but this
could easily lead to inconsistent and unportable Kermit command files.  The
best solution to this problem might be to change calls to cmofi() and cmifi()
from the OS/2 version to use an expansion function other than xxstring() --
this way backslashes can be used for quoting everywhere but in filenames.

Discovered that Ctrl-R redisplay gets in trouble from the quoting mechanism.
Example: Type a\^Bc (where ^B is the character Ctrl-B).  This echoes as a\c
but is stored in the buffer as a^Bc, so when you redispay the buffer by typing
Ctrl-R, all you see is ac, even though there are 3 characters there.  So when
you delete backwards, you get an inaccurate display of what was deleted.  Of
course, typing Ctrl-R again gives you a corrected picture.

Added command synonyms for MS-DOS Kermit compatibility: PUSH and RUN are
synonyms for ! (shell escape), REPLAY = TYPE, POP = END.

Fix command parser not to show the top-level token table when "?" typed and
user has already typed some characters.  Removed % from the token table as a
comment introducer, because this conflicts with variable names.  We still have
! = shell escape, # and ; as comment introducers, & = echo, and : to introduce
a label.

Added the DISABLE and ENABLE commands for the server, plus SHOW SERVER to
display their status, along with the current SERVER TIMEOUT.  Moved the SHOW
command to ckuus5.c, to trim ckuusr.c a little more.

Added REMOTE SET command.  Support was already in the server, this is the
client end.  Rather than have a whole new tree of commands and keywords,
used the doprm() function for this, and added a second parameter to the
dorprm() call, 0 = SET, 1 = REMOTE SET.  Some of the commands seem to work,
some don't (REMOTE SET BLOCK-CHECK apparently doesn't, and there is some kind
of protocol foulup after using it, see ~/packet.log).  More testing & fixing
needed.

------------------------------

5A(117) Wed Feb 28 23:57:10 1990

Change OUTPUT command to work in both remote and local mode.  Move OUTPUT
command code from ckuusr.c to ckuus5.c (ckuusr.c weight reduction program).
Add code to OUTPUT command to accept \b or \B in the output string to send a
BREAK.

Change ttopen() to also clear the CBREAK bit in the ttold structure if
standard i/o is redirected.  Kermit has no way of obtaining the real tty mode
bits when stdio is redirected because the shell changed them before it started
Kermit, and apparently does not restore them when Kermit exits.  This solution
is inadequate.  Another possibility might be to not manipulate the tty bits at
all if stdio redirected, on the assumption that raw unprocessed characters are
used in that case anyway???  Might have to make separate cases for standard
input and output.  Worry about this later.

Frank Prindle noticed that 'kermit -k' is VERY SLOW on a loaded system (I
didn't notice because my system isn't).  There is a 'setbuf(stdout,NULL)' in
concb() to make writes to the console be unbuffered, so that the interactive
command parser will work right and dots will show up promptly during
local-mode file transfer.  But this turns file-transfer writes to stdout into
single-character write()'s, which cause the process to be dismissed, in the
worst case, after every character on a loaded system.  Several solutions are
possible; Frank suggested changing the fwrite() in ckufio.c: zoutdump() to
fflush() followed by write().  He reports that this makes 'kermit -k' FIVE
TIMES faster on his loaded system, and that Kermit's CPU time (as reported by
lastcomm) went down by the same factor.  No difference seen on the local
(unloaded) SUN-4 between either the old and new strategy, or writing to a file
vs stdout, but when transferring files over a telnet ("set host") connection,
the improvement was about fourfold -- nearly 200,000 bps (fastest Kermit file
transfer yet!  not as fast as ftp, but ftp doesn't have to do per-character
quoting, etc).

Still some lingering problems in this area.  Can't seem to make things like:

  kermit -k < cmdfile > outfile

work, where cmdfile contains commands to set modem, speed, dial out, etc.
This just hangs my job.  Worry about this another day.

FINALLY... started work on the command parser.  The new strategy is to pass
a function pointer to each cm???() call, or else NULL.  If a function is
given, then the cm???() call will use that function to expand the atom buffer
before evaluating it.  In Kermit's case, it will expand variables and
translate backslash escapes.

Rewrote xxstring() and xxesc().  xxstring() is now a simple recursive
function, which is part of the Kermit application.  xxesc() was moved to the
command parser, so that backslash escapes are now an integral part of command
parsing, rather than something peculiar to the Kermit application.

Converted cmnum() to work like this:
 1. try to parse a string of decimal digits.
 2. if that fails, try to parse a backslash escape.
 3. if that fails, call the user-provided conversion function, if any.
 4. try again to parse a string of decimal digits.

The user-provided function is, of course, xxstring, which expands variables
via recursive descent.  So now once the cmnum() calls in the whole program are
converted, then users can type not only a decimal number, but also \nnn,
\Dnnn, \Onnn, or \Xnn, or \%x (variable name) as in MS-DOS Kermit. 

The specification for the user-provided function is:

  int fn(s1,&s2);

where s1 is the source string (to be processed), and &s2 is the address of
where to put the result, which the function can update in case it wants to
call itself.  The function must return a negative number on failure and 0 or a
positive number on success.

The new cmnum is not completely and totally general.  Here are some things
that you can and can't do (using SET DELAY as an example):

These Work:           These Don't:
  set delay 3          define %a \7
  define %a 7          set delay \%a
  set delay \%a        set delay \{\o77}
  set delay \23        set delay \{5}4
  set delay \x1f       set delay 4\{5}
  set delay \o33       set delay 4\5
  set delay \{42}      define %b 6
  set delay \{x0f}     set delay \1\%b

The incompatibility between C-Kermit and MS-DOS Kermit (the latter permits
some, but not all of the right-hand forms) is because the C-Kermit command
parser (ckucmd.c) must be kept independent of the Kermit application and
command set, so that it can be used for other applications.  Variables, macro
arguments, etc, are set and controlled by the Kermit application.

The particular difficulty with with cmnum is that xxesc (the backslash escape
sequence interpreter, which is part of the command package) cannot call the
variable expander (xxstring) because it's part of the Kermit application.  
The difficulty is compounded by the fact that a backslash escape is converted
to an int in the range 0-255, whereas xxstring builds a character string.  If
xxstring were the only one to process cmnum's input, then it would be
impossible to tell if it were returning an int (stored in a character string)
or a numeric character string.  For example, would a byte of value 48 be the
integer 48, or the numeric character '0'? 

The remaining command parsing functions were converted with much less trouble:
 . cmofi() (parse an output file -- now you can say "log debug \%a" etc.
 . cmifi() (input file -- works fine, but ESC and ? are a bit of a surprise)
 . cmdir() (directory, no problem)
 . cmfld() (arbitrary field, ok)
 . cmtxt() (line of text, ok) 
 . cmkey() (keyword...)

cmkey() also works, for example you can do:

  C-Kermit>def %a set
  C-Kermit>def %b block
  C-Kermit>def %c 3
  C-Kermit>\%a \%b \%c

but as with cmifi(), ESC and ? behave differently that in MS-DOS Kermit.  The
C-Kermit command parser leaves the characters that you type on the screen,
whereas the MS-DOS parser actually rewrites them out from under you.  C-Kermit
does not necessarily have this control (e.g. you might be running it on a
hardcopy terminal).  So in C-Kermit if you have the definitions above and
type:

  \%a \%b<ESC>

you will see

  \%a \%b-check

rather than

  set block-check

Not a big deal, I think, since very few people will use variables
interactively this way.

The other major difference is that you can't define a variable to stand for
more than one word in a command.  For example, you can't do this (as you can
in MS-DOS Kermit):

  define \%e echo this is pretty neat

and then give \%e as a command.  Only the first word ("echo" in this case) is
executed.  But this is not a big deal either, because that's what macros are
for.

After designing, coding, and testing the various cm*() functions, I went
through all the cku*.c modules and changed every invocation of each of these
functions to include either xxstring as a variable expander, or else NULL when
variable expansion was not desired, for example in the command:

  define %a echo foo

the variable name "%a" should NOT be expanded.

Obviously these fundamental change in the user interface will need a lot of
testing and refining.

Finally, fix a couple problems pointed out by Frank Prindle: (1) the use of
the symbol O_NDELAY needed to be conditionalized on its existence in ckutio.c
(4.1BSD doesn't have it), and (2) a malloc() was removed from the setatm()
function in ckucmd.c last week, without the corresponding free() also being
removed!

------------------------------

5A(116) Mon Feb 26 11:28:45 1990

Change ttopen() in ckutio.c to use stdin (ttyfd = 0) if not local AND if
standard i/o is not redirected, so that UNIX idle-time monitors won't think
that Kermit is idle while it is transferring files over the job's controlling
terminal.  To accomplish this, ckutio sets a flag "fdflag" if (!isatty(0) ||
!isatty(1)).  Then, if ttopen() determines that Kermit is in remote mode, it
substitutes file descriptor 0 for the one obtained by open() but only if
fdflag == 0.  Suggested in a different form by Frank Prindle,
<prindle@NADC.ARPA>.

Discovered that there's something wrong with sending from stdin, as in 'kermit
-s -'.  If there's no .kermrc file, everything works fine.  If there is a
.kermrc file, something in ckucmd.c sends several hundred beeps, then sends an
empty file.  Discovered this is because of the code that checks for keyboard
interruption during take-file execution.  Changed this code to not read from
the "keyboard" if !isatty(0).  Everything seems to work now, except:

'kermit -k | command' works, but leaves the terminal in no-echo mode after it
exits.  Spent many hours tracking this down.  Finally realized it was because
gtty(ttyfd,&ttold) (or in Sys V ioctl(ttyfd,TCGETA,&ttold)) sees the ECHO bit
turned off when standard output is redirected, and so upon exit restoring the
tty mode bits gotten in this way turns off the echo bit.  So ttopen now tests
isatty(0) and isatty(1) to see if stdio is redirected, and if so, it ORs in
the ECHO bit.

So now, 5A works as it should when sending from standard input or receiving to
standard output, and restores the terminal properly upon exit.  It also can
read its commands from redirected stdin, as in 'kermit < commandfile'.  AND,
unlike previously, file descriptor 0 is used in remote mode for file transfers
except when stdio is redirected, so now UNIX idle-line monitors won't be
fooled into thinking that file transfer == inactivity.  Whew!

And now on to the INPUT command.  It wasn't really interruptible from the
keyboard after all.  Changed the entire strategy.  Now, instead of having the
input command within a timer, INPUT calls the character input functions with
1-second timers that add up to the total input timeout.  This allows the
program to sample the keyboard every second so the user can interrupt the
INPUT.  An interrupted INPUT fails, as it should.  Also I noticed and fixed
two other related problems.  The INPUT search string, after case conversion,
was not properly terminated, and the OUTPUT command was not working at all
because it was outputting the wrong character from its string (the old ++
mistake).

Moved this version to the NeXT and compiled it.  The NeXT compiler found an
unterminated string constant in ckudia.c, within #ifdef's that it shouldn't
even have been looking at the contents of.  Wow, what a compiler.

Added the MAIL and REMOTE PRINT commands.  The receiving end was already
present.  Now C-Kermit can mail or print to itself.  Both commands take either
a single file or multiple files.  The client end just uses the SEND code,
but sets special flags so that the right stuff is put into the Attribute
packet.  Also added code to make sure that an A-packet isn't sent that is
longer than the receiver's declared buffer size.  But this whole business
needs to be generalized to allow long attribute data to be split up into
multiple A packets.

------------------------------

5A(115) Sun Feb 25 22:15:19 1990

Add ASKQ (ask quietly, don't echo what user types) command.

Let WAIT parse material after timeout, but still don't do anything with it.

Let WAIT and PAUSE be interrupted from keyboard.  BSD, any keystroke; AT&T,
Ctrl-\.  Gobble up whatever characters were typed so that upon return to
command prompt, extraneous characters are not left in command buffer (needs
testing on Sys V).  Set SUCCESS if PAUSE or WAIT completes its time, set
FAILURE if interrupted from keyboard.  For now, WAIT always fails, since it
cannot sense the modem signals.  Make WAIT an invisible keyword.

Add SHOW STATUS command to show the status (SUCCESS or FAILURE) of the most
recent command.

Went through ckuusr.c and had each command set success/failure appropriately.
All parse errors set success = 0.  Making this work involved changing the
return codes of many functions that are called from here, particularly
conect(), login(), ckdial(), transmit(), dotype(), xlate(), etc.  In general,
it is no longer a good idea for an action routine to return -2 upon failure,
because that makes it look like a parse error.  From now on, action routines
should return 0 on failure, 1 on success.  It will probably take some time to
get this consistent throughout the program.

There is no explicit setting of success in protocol-related commands.  That is
done in ckcpro.w.

JRD reports that new code works great on ATT 7300 -- very fast windowed
transfers, etc.  BUT...  When dialing out, it gets a "communications
disconnect" immediately upon ttinc() via myread() not getting any characters.
In other words, the distinction which used to be made between no chars
available (as in EWOULDBLOCK) and carrier loss seems not to be working in the
new code.  Message sent to Kristoffer about this.

Tested JRD's complaint on SUN4 in Sys V R3 environment.  Connect worked just
fine, no problem with "communications disconnect" at all.  But EXIT command
hung forever.  Traced problem to msleep(), which is called from tthang().  My
guess is that this problem is peculiar to SUNOS4/SysV, so added a special
symbol -DSUN4S5 to makefile entry, and within msleep() replace fancy system
calls by a busy loop.  (Tracking this down and fixing it took hours, grrrrr.)

Changed INPUT command to let it work in remote mode, for testing the timeout
and string matching code.  Everything seems to be OK, but Chris Armstrong
reported some problems with INPUT in OS/2.

Fix protocol bug noticed by JRD: When sending a file, and the receiver 
requests cancellation by putting 'X' in the ack to the data packet, C-Kermit
would properly stop sending the file, but would fail to put a 'D' in the data
field of the Z packet.  This was because the cxseen flag was being reset in
clsif(), before it could be tested in the protocol module.  Moved clearing of
this flag to the protocol module, state <seof>Y.  Tested, works, and also
confirmed that success flag is set correctly.

File creation date now set for incoming files when they arrive with a date
attribute, and attributes are not set to OFF.  Changes from Bo Kullmar, Kista,
Sweden <bk@kullmar.se>.  ckcpro.w, ckcfns.c (in these two, the function reof()
had the filename added as a new first argument); ckufio.c (new function
zstime() added).  Tested in in BSD and Sys V environments on the SUN, works
fine (BSD version needed some changes).

Added @echo messages to makefile.

Added VERSION command.

------------------------------

5A(114) Sat Feb 24 12:51:07 1990

Fixed UNIX DIRECTORY command, which was changed a while back to use cmdir()
rather than cmtxt() to allow for tilde expansion.  After this change, it did
not wait for user to confirm the command before executing it, and it didn't
copy the resulting string out of the atom buffer before calling cmcfm(), so
the string would be wiped out if the user typed something like "dir xyz  <cr>"
instead of "dir xyz<cr>".

Fixed program to quit properly from current macro or take file if INPUT
command fails, and input timeout-action is set to QUIT.  Fix program not to
print a spurious syntax error message if INPUT fails.  Make INPUT and REINPUT
print a "failed" message only if the failure causes the program to pop to top
command level.

Started putting "success =" statements in various parts of the program.  In
ckcpro.w, added them anywhere that a file transfer concluded.  Put one in
errpkt() in ckcfn2.c.  This should allow IF SUCCESS/FAILURE to work after
SEND, RECEIVE, GET, and similar commands.

Changed the SET SPEED command to complain if the current "line" is a network
host connection.

To remove confusion about what symbol gets defined where for ASCII control
characters (previously some were defined in ckuker.h, others in ckucmd.h),
I moved all of them into a single file, ckcasc.h, which is included in
addition to the other include files by all modules that need these symbols.

Fix an #endif that still had trailing text in ckuus3.c.  Correct the grouping
of SET TERMINAL commands within/outside #ifdef OS2.  Add OS/2-specific forward
declaration of zfindfile() in ckuus5.c.  (Chris Armstrong)

Get rid of compile-time symbol ATT3BX.  Add explicit -DHDBUUCP definitions
to each entry in the makefile for versions that use Honey-DanBer UUCP lockfile
conventions.  Now it's easy to add this for others, just include -DHDBUUCP in
any makefile entry.

Add bsd210ov entry to makefile, to make Kermit for 2.10 BSD on small PDP-11
without separate I&D space by using overlays; from Dennis Flaherty.  Probably
will not work, since many modules have been added or increased in size since
he sent in this submission (based on version 4F).  This might also help for
MINIX, if its linker supports overlays.

In ckufio.c for Masscomp/Concurrent RTU 4.0 or later,
#include "/usr/lib/ndir.h" rather than <sys/dir.h>.

In ckutio.c add conditionals for #ifndef is68k (whatever that is) to not
include sys/file.h or fcntl.h (from Ray Moody <ray@maxwell.physics.purdue.edu).

Made massive and profound changes to ckutio.c, from Kristoffer Eriksson,
Peridot Konsult AB, Oerebro, Sweden.  As I had recoded ttinl() for sliding
windows in 5A(100), it did not work well with System V, because it depended
upon ttchk() being able to look in the system's input buffer to see if any
characters were waiting, but System V can't do that without myread(), so it
wound up always doing single-character read()'s -- very bad for performance.
Kristoffer, with advice from Warren Tucker, Tridom Corp, Mt Park, GA, on
BSD/ATT tty driver differences, reinstated myread() as a macro a`la zinchar()
and made it apply to both AT&T and BSD based systems.  Still in experimental
form.  Preliminary tests show that the changes work (SYS5R3 is the System V R3
environment on the SUN under SUNOS 4.x):
			     SUNOS4    SYS5R3   ATT7300
  compile                      OK        OK        OK
  set line  / connect          OK        OK        OK
  set host  / connect          OK       (no)      (no) <-- (no telnet)
  send file / window 1         OK        OK        OK
  send file / window 4         OK        OK        OK
  rcv file  / window 1         OK        OK        OK
  rcv file  / window 4         OK        OK        OK

Also tested the program in the BSD environment with MYREAD defined and
undefined, works OK.  JRD's tests on ATT7300 in remote mode show a threefold
(!) speed improvement when myread() is used on a Starlan network (where
RS-232 is not the bottleneck).

Added function ttgspd() to ckutio.c to return the speed of the currently
selected tty line, so that better timeouts could be calculated, and SHOW SPEED
command in ckuusr.c to call it.  Doesn't work.  In normal remote mode (no SET
LINE given), always returns -1.  After SET LINE, it returns an actual speed,
but not the real speed.  Apparently it always returns the line's nominal speed
from /etc/ttytab.  Even if you SET SPEED to something else, this function
doesn't notice.  Anybody know the secret of getting the real, actual speed?
Reminds me of the old PDP-11 DH11 multiplexer in which the line speed was
stored in a write-only register...  Made SHOW SPEED an invisible command.

Fixes from Steve Walton <ecphssrw@afws.csun.edu>: Put signal(SIGINT,...)
calls, which are already within #ifndef OS2 conditionals, also within #ifndef
AMIGA conditionals.  Fix a bad print statement in ckuus2 (two %s's, only one
string to print).  Fix blank-line bug in TRANSMIT command.  Fix conflicting
definitions of string buffers in ckuus3.c.  Change "if (nambuf) ..." in
ckufio.c zsattr() function to "if (*nambuf) ...".

Changes to ckudia.c from Peter Mauzey to improve support for AT&T modems.

Add support for Silicon Graphics System V R3 with BSD file system (IRIS)
from Robert Adsett, U of Waterloo <semicon@watsci.uwaterloo.ca>.  ckufio.c,
makefile.

------------------------------

5A(113) Thu Feb 22 12:00:18 1990

Increase maximum receive packet size from 1K to 2K.  Use at your own risk!
Many UNIX systems have small terminal input buffers.  Always use block check
type 2 or 3 with long packets.

Add code to spar() and rpar() to automatically increase timeout interval if
(a) we know the line speed, (b) the connection is not on a network, and (c)
the product of the speed and the timeout is less than the packet size.  But
with packet length of 2000 and unknown speed, it's still very easy to have a
too-short timeout, in which case nary a data packet will ever get through.

If user types SET SEND or RECEIVE PACKET-LENGTH n, where n > 1000, issue
warnings about timeout and block check type if they have not already set
these appropriately, and not in take file, macro, or background.

Change outer loop in ttinl() to terminate if received packet is longer than
the receive-buffer length.  And in ttinc(), make sure parity is stripped in
all cases.  Thanks to Kristoffer Eriksson for both these fixes.

Also from Kristoffer: several malloc's were done based on strlen() of the
string for which the space was being allocated, which didn't leave room for
the trailing null byte.  Fixed these to be like malloc(strlen(x) + 1).
(This apparently fixes the memory protection violation problems for OS/2!)

Kristoffer's fixes were based on his experiences building the program on
SCO Xenix/386, so that's a good sign.

From Chris Armstrong: Various changes to many modules to accommodate OS/2.
Mainly switching order of include files (again), addition of SET TERMINAL
TYPE { VT100, TEK4010 }.

------------------------------

5A(112) Wed Feb 21 15:54:58 1990

Today was a day of testing on different systems, with the minor cleanups and
fixes that were necessary.  Still waiting for the final verdict on OS/2, and
we haven't even begun to look at this program on Xenix or other PC-based
UNIXes.

Tried to build on VAX/Ultrix 2.0.  Found two symbols from netopen() in
ckutio.c (new network support) undefined.  Added some extra #ifndef's and
#ifdef's and it compiled and worked just fine, including set host (telnet).

Tried to build on NeXT, got several pages of compilation errors.  The NeXT C
compiler is almost as good as lint, and picked up many typos that slipped by
the SUN and VAX compilers.  In particular, NULL (the null pointer) was used in
several places where NUL (the null character, i.e.'\0') should have been.
Also, removed the "-fwriteable-strings" from the NeXT makefile entry (because
Kermit no longer has the typo that caused it to write into string constants).
Fixed compilation errors, defined a -DNEXT symbol for the NeXT, and in
ckcdeb.h typedef'd signal-related things to be void rather than int, like Sys
V R3.  This made most of the signal-related compiler warnings go away.  Also,
added a special version herald for NeXT.  Tested in remote and local mode,
works fine.  Tested with "set host" (telnet) and that works too.

Built the program on an Encore 510 with Umax 4.3 using "make bsd43".
Compiled, linked, and ran without a hitch.  Tested briefly in remote mode
(tty), and with "set host" over Ethernet.  Both worked OK.

Built it on a SUN-4 using the AT&T System V R3 environment, using "make
sys5r3".  No problems, except some warnings about compiler switches being
ignored.  Tested it with sliding windows, and it worked fine.  No telnet
support in this version.  

JRD tested it on his AT&T 7300 UNIX PC.  No compiler or linker complaints
and it ran fine at 9600 bps, but had some problems at 19200.

------------------------------

5A(111) Tue Feb 20 21:08:46 1990

Version 5A cannot be built in the OS/2 environment without using certain
obscure undocumented compiler and linker options.  Even then it seems to crash
during execution when malloc() is called.  Removed the malloc() call from
ckucmd.c, so the whole program does not depend on it, at the cost of yet
another 1/4 KB buffer.  Remaining calls to malloc() are in ckuus4.c (INPUT and
REINPUT commands) and ckuus5.c (all over the place in anything related to
macros or variables).  All malloc() calls are checked for failure.  In the
UNIX version, there are also malloc's in ckutio.c and ckufio.c (but they've
been there forever).

Also, for the benefit of OS/2, changed all ck*.c files except cku[tf]io.c
to #include all system files (#include <file>) before non-system files
(#include "file"), so that the OS/2 code can #undef puts() and then define a
new one.

Next frontier seems to be that there is too much initialized data in the
program for some C compilers or linkers to cope with, e.g. on PC-based systems
the initialized data might actually have to fit into a 64K segment (e.g. OS/2
linker says "DGROUP exceeds 64k").  Not clear yet whether this is per module
or for the whole program.  Presently there are tons of initialized data in
ckuusr.c (command tables) and ckcxla.c (character translation tables).

------------------------------

5A(110) Mon Feb 19 18:51:24 1990
 
ckuusr.c has become much too big, causing problems with some C compilers and
UNIX linkers (e.g. AT&T's on the UNIX PC, Microsoft on OS/2, etc).  Moved
functions from ckuusr.c to ckuus4 until the latter grew to about the same size
as ckuus2 and ckuus3 (as reported by "size ck*.o").  Then created ckuus5.c and
moved everything left in ckuusr.c to it except the major command keyword
tables and the docmd() function.  Results (as seen on SUN-4):

		BEFORE           AFTER
	      text   data     text   data
  ckuusr.c   36816  11464    20880   9576  (smaller)
  ckuus2.c    4905  15616     4905  15616  (no change)
  ckuus3.c   16528   4656    16528   4656  (no change)
  ckuus4.c   14016   3112    19056   4024  (bigger)
  ckuus5.c       0      0    10944    976  (new, infinitely bigger)

There still could be some problems here.  First, those who attempt to compile
and link the new files should add whatever compiler/linker options are
available to use the 'large', 'huge', or 'humongous' model.  If that doesn't
help, the next thing to do would be to move some pure code from the modules
that have large text sizes (like ckuusr.c and ckuus4.c) into those that have
small text sizes (like ckuus2.c).  The only way to move code out of ckuusr.c
at this point is to convert in-line code into function calls, and move the
code into new functions that are defined elsewhere.

Added support for TCP/IP connections using Berkeley UNIX sockets, from Ken Yap
at the University of Rochester (ken@cs.rochester.edu).  Changes confined to
ckutio.c, enclosed within #ifdef NETCONN ... #endif brackets.  New syntax
allows SET LINE hostname or SET LINE hostname:service, where service can be a
named service (like smtp) or a socket number (like 119 for nntp).  If the
service is omitted, it defaults to telnet (23).  Makefile changed to add
-DNETCONN for some of the BSD variants.  Initial tests between a SUN-4 and
various VAX, SUN and Encore (UNIX), VAX (VMS), and IBM mainframe (VM/CMS)
systems show the basic code to be working, but there are several glitches:

 1. Speed is spuriously reported as 38400, when in fact it's "unknown".
 2. If user has a symbolic link from an ordinary filename (like "foo") to
    a terminal device (like "/dev/tty05"), this code will try to open a
    network connection to host "foo" instead of following the symbolic link.
 3. A short burst of garbage appears upon initially connecting.  This is the
    telnet option negotiation, which is ignored.
 4. Since telnet options (like ECHO) not negotiated, you must use SET commands
    (like SET DUPLEX) just as you would for ordinary tty-style connections.
 5. Can't send BREAK.   
 6. Various problems in telnetting to half-duplex systems like VM/CMS, like
    "blank lines" are not transmitted (workaround: type SP CR instead of CR).
 7. Error messages are uninformative.

File transfer with various kinds of hosts seems to work OK, using all
defaults, except that IBM mainframe Kermits behave strangely when sending
files over a telnet connection (they receive files OK).  Initial tests from a
SUN-4 show effective data rates in the 25-55 Kbps range.  Support for
AT&T-based TCP/IP implementations must still be added (streams instead of
sockets).

Later, change user interface to fix glitches 1 and 2 above.  Add new command,
SET HOST <hostname>, to prevent misinterpretation of a symbolic link to a tty
device name as a network host name.  SET HOST with no args is just like SET
LINE with no args (puts Kermit back to default, normal line & mode).  Changed
SHOW and CONNECT commands to report network vs tty connection appropriately,
and to ignore speed setting for network connections.  For future expansion,
added a command SET NETWORK, so that the SET HOST command could know what kind
of network connection to open.  For now this command does nothing; eventually
it can be expanded when support for new networks (like DECnet) is added.
Note: To avoid adding new things to many files, made a sneaky change: when
calling ttopen(), set modem type to -1 if it's a network.

Another note: there is no way (and there *should* be no way) to set Kermit up
as a network file transfer server.  This opens up too many potential security
loopholes.

While I was in the area, added an invisible command SET PORT, which is just
a synonym for SET LINE (for compatibility with MS-DOS Kermit).

------------------------------

5A(109) Tue Feb 13 09:56:51 1990

Make sure all calls to malloc() are checked for error: ckuusr.c, ckuus4.c,
ckucmd.c.

Make sure all calls to free() are prechecked to not feed it a null pointer.
This was causing core dumps on ATT7300.

Add WAIT command.  For now, it's just a synonym for PAUSE, there only for
compatibility with MS-DOS Kermit.

Add EVALUATE command.  Takes its text argument, runs it through xxstring(),
stuffs it into the command buffer, and then tries to execute it as a Kermit
command.

Change scoping rules for GOTO.  Previously, GOTO could only find a label
in the current TAKE file (if invoked from a take file) or current macro (if
invoked from a macro).  Now, if it fails to find the given label in the
current command-source (take file or macro), it pops up to the invoking level
and looks there, and continues until the first occurrence of the label is
found, or level 0 (interactive command level) is reached.  So now you can
define macros that contain GOTOs into the mainline script program code, like

  define errexit echo Error: \%1, goto foo
  input 10 Login:
  if failure errexit {No login prompt}
  output myid\13
  input 10 password:
  if failure errexit {No login prompt}
  input 10 $\32
  echo Logged in!  
   ...
  :foo
   ...

Note: obviously, GOTO does not work in a command file which is directed into
Kermit's standard input, as in 'kermit < commandfile'.  This could be changed
to allow forward GOTOs only, but probably not worth it.

PROBLEM: Variable expansion does not occur everywhere within a macro body
when the macro is invoked.  For example:

  define errexit echo Error: \%1, goto \%2

It's up to the individual commands to expand their arguments.  Right now,
ECHO does, GOTO doesn't.  So "errexit {bad thing} foo" winds up printing
"Error: bad thing" and then saying "Can't find label :\%2".  Oops.

Solutions?  (a) Make GOTO and similar commands expand their args; (b) Make
macro expander expand variables that occur anywhere in macro definition during
macro execution; (c) push entire macro definition string through xxstring()
before execution.  None of these seems right.  (a) would miss a lot (like in
"define xx set \%1 \%2" -- certainly SET should not call xxstring() on its
parameter keyword and all arguments???); (b) would ruin certain statements
within macros (as in "define xx def \%a echo \%1" or "if defined \%1 echo foo")
and (c) would recursively grind any script into plain ascii characters...

Add ELSE command.  Effective only immediately after IF.  Tested ok
interactively, in TAKE file, and in macro execution.  Done as follows: define
two more variables on the command-level stack: ifcmd[] and iftest[].  They
have to be on the stack because the argument of an IF command can be a macro
invocation or a TAKE command.  The ifcmd[] variable counts the number of
statements that have been encountered since the IF clause.  When this is 1, we
are executing the THEN part.  If the THEN-part is another IF, it goes back to
1.  If the number is 1 or 2, then an ELSE can be parsed successfully, and this
sets it back to zero.  If it is 0 when an ELSE command is encountered, a parse
error occurs.  If it is 1 or greater and a non-ELSE, non-COMMENT, non-IF
command is encountered, it goes back to zero.  Simple, eh?  The iftest[]
variable carries the result of the IF-condition, so that the program knows
whether to execute the THEN-part or the ELSE-part, if any.  Formal syntax:

  IF [NOT] <condition> [ <command> ]
  ELSE [ <command> ]

ELSE must be on a separate line, and there is no word THEN.  <command> can be
any single command, or a macro invocation, or nothing at all.  And of course,
there need not be an ELSE at all.  You can also have multiple IFs to achieve
and AND effect:

  IF [NOT] <condition> IF [NOT] <condition> IF ... [ <command> ]
  ELSE [ <command> ]

And you can have cascaded IF-ELSE constructions:
 
  :loop
  ask %a Command\63\32
  IF eq \%a end end
  ELSE IF eq \%a stop stop
  ELSE goto loop

Since there is no block structure in this language (yet!), we don't have to
worry about matching ELSEs with IFs.  The ELSE always goes with the
immediately preceding IF.

One final syntax note: If an IF statement has a null THEN-part, then the
next command (ELSE or otherwise) is always executed:

  IF = 1 2
  ECHO foo

This echoes "foo", unlike "IF = 1 2 ECHO foo", which does not (same as MS-DOS
Kermit).  You can't say "IF = 1 2 ELSE echo foo" (well, you can, but it won't
do anything).  Also, the ELSE part can be empty:

  IF = 1 2 echo Impossible!
  ELSE

The ELSE command is presently invisible, to discourage use of IF-ELSE until it
is also supported by MS-DOS Kermit, so that we don't have a crop of C-Kermit
scripts that can't be easily adapted to MS-DOS Kermit (Chris's concern).

So finally, the really really formal syntax of the new IF command is (things
in UPPERCASE are taken literally, things in <brackets> are metasymbols,
+ means 1 or more repetition of, * means zero or more repetitions of, and
::= means "is replaced by"):

  <nl>     ::= newline (linefeed or CR or CRLF)
  <not>    ::= NOT
  <cmd>    ::= any C-Kermit command except ELSE, including no command at all
  <cond>   ::= EXISTS filename | < n1 n2 | = n1 n2 | EQUAL s1 s2 | etc etc
  <ifpart> ::= IF <not>* <cond>
  <ifcmd>  ::= <ifpart>+ <cmd> <nl> | <ifcmd> ELSE <cmd> <nl>

Note the left-recursive definition of <ifcmd>.  Now let's run this thru lex &
yacc and let them write this program for us!

------------------------------

5A(108) Mon Feb 12 21:59:24 1990

When reading commands from a file, convert tabs to spaces.  This is stupid,
but at least it allows normal use of tabs for aligning comments.  But it
will also affect ECHO strings, quoted tabs, etc.  Need a smarter approach.

Add help text for new commands.

Add SHOW SCRIPTS.

Allow user to type the single character x or X during TAKE file or macro
execution to stop and return to C-Kermit prompt level.

If any character is typed at the keyboard while an INPUT command is active,
cancel the INPUT command and set the FAILURE code.

Remove previous change; it doesn't work because it requires an alarm within an
alarm, which seems to wipe out the overall INPUT timer.  So for now, there's
no way to manually interrupt an INPUT command (but if it's being executed from
a macro or TAKE file, use 'X' to cause an interruption immediately after the
INPUT completes or times out).

Change chkint() to allow X, Z, etc, to interrupt file transfer, a`la MS-DOS
Kermit, so users don't have to type control characters for this.

Add IF EQUAL, string comparison for use with ASK, etc:

  Syntax: IF EQUAL <word1> <word2> <command>

where <word1> and <word2> contain no spaces.  They can be plain character
strings, variable names (but must begin with backslash), or strings containing
one or more variable names.  Variables within <word1> and <word2> may expand
to anything at all except null, which terminates the string.  The two
expanded <word>s may therefore contain embedded spaces.  They are compared as
follows: if their lengths are different, then they differ.  Otherwise, if
INPUT CASE is set to IGNORE, a case-independent comparison is done (using new
function xxstrcmp()).  Otherwise, an exact match is required.

Add IF <, IF =, and IF > for comparison of numeric strings.  Arguments can
be numeric strings, variables containing numeric strings, or the words COUNT,
VERSION, or ARGC.

Modify SET COUNT to accept numeric variables or ARGC as an argument, as well
as ordinary numbers.

Add INCREMENT, DECREMENT.  These work on \%1..9, \%a..z, but only if they
have numeric contents.

------------------------------

5A(107) Sun Feb 11 13:57:24 1990

Allow trailing comments.  This was a big production.  The major difficulty was
in finding the right place to trim trailing blanks off a command after the
comment had been removed, since the part before the command had already been
parsed.  This process uncovered a longstanding bug that nobody had ever
reported: cmtxt, which is used to parse all sorts of things (like the "set
line" device name) left trailing blanks on, so that if you said "set line
/dev/tt0a ", Kermit would tell you "no such device".  This is now fixed.

Rules for trailing comments:
 0. They may be used in interactive commands as well as take files. 
 1. They begin with semicolon (;) or pound-sign (#).
 2. The comment introducer (; or #) must have at least one space preceding it
    unless it's at the start of a command.  Note: space, not tab (see 6 below).
 3. If semicolon or pound sign is to be included in a command:
      a. Put it immediately after a non-space character, as in "get foo.x;17".
      b. Quote it with \, as in "echo oofa \; afoo".
      c. Enter numerically, as in "echo oofa \59 afoo".
 4. Backslash notation (like \7, \%1, etc) is ignored within comments.
 5. A comment, like any other command, can be continued by ending it with -.
    But all subsequent continued lines will be part of the same comment, since
    there is no "comment terminator" other than an unquoted CR or LF.  This
    means you can't put comments on each line of a multiline macro definition.
    But you can't do it in MS-DOS Kermit either.
 6. Sad to say, tabs cannot be used to line up comments.  You must use spaces. 
    This is because:
      a. It's not possible for this program to keep track of your cursor
         position, since it doesn't have control over the screen.  Therefore,
         editing (DEL, Ctrl-W, Ctrl-U) of commands containing tabs would mess
         up the screen display and confuse users horribly.
      b. Tab is already used for keyword and filename completion.  But even
         if it weren't, problem (a) would remain.
 7. Trailing comments can be used freely even on GOTOs, labels, and DEFINEs.

Other changes:

Turn SET PROMPT argument into an "xxstring", so that it can contain embedded
backslash escapes, including variables.  Now you can put VTxxx escape
sequences, etc, into your Kermit prompt for highlighting, color, sound
effects, confidence tests, etc.

Add SET TAKE ERROR ON/OFF.  Until now, any syntax error in a TAKE file would
terminate execution of the file and return to the level that invoked it.  This
is still the default behavior, but now you can say SET TAKE ERROR OFF and
Kermit will simply proceed to the next command, if any, in the take file.

Add SET MACRO ERROR ON/OFF.  If a statement in a macro is in error (fails at
the parse level), the macro normally proceeds to the next statement, if any,
in the definition (compatibly with MS-DOS Kermit).  SET MACRO ERROR ON makes
it quit the current macro and return to the level that invoked it.

Add SET INPUT { DEFAULT-TIMEOUT, TIMEOUT-ACTION, CASE, ECHO }.
DEFAULT-TIMEOUT currently has no effect because the timeout field must be
specified in the INPUT command.  The others seem to work OK, as in MS-DOS
Kermit, et al.

Add REINPUT.  Parses just like INPUT, timeout is required but it is not used
at all.  This command just looks in the circular buffer that INPUT has been
storing its characters in.  Seems to work OK.

Increase command buffer length, CMDBFL, from 256 to 1000, so that longer
macros can be defined.

------------------------------

5A(106) Sat Feb 10 13:01:34 1990

Add "none" as a synonym for "direct" in SET MODEM.

Remove explicit references to stdin/stdout and other file descriptors in
ckcpro.w, ckc*.c, and cku*.c (except ckutio.c and ckufio.c):
 - fputs --> printf in function hmsga() in ckuus2.c 
 - putc  --> printf (same place)
 - fprintf(stderr,...) -> printf in ckuusr.c functions ermsg(), fatal(), etc.
This should make it easier on OS/2, VMS, & other non-UNIX C-Kermit developers.

Add SET MACRO ECHO ON/OFF, separate from TAKE ECHO.  Note: presently, both
of these print commands when turned on, regardless of quiet or background
settings.  Should this be changed?

Move a lot of #ifdef's out of gtword() in ckucmd.c into new functions defined
at the end of that file, to make gtword be mostly system-independent and
easier to read.  This is only a first step.  Next step is to move these
functions to each and every ck?tio.c file.

Discovered & fixed bug that has been in command parser forever: If user types
a control character that is not an editing character, such as Ctrl-B, the
command parser silently puts it in the buffer, but since it does not echo on
the screen, subsequent erasures (DEL, BS, Ctrl-W, Ctrl-U) wipe too many
characters off the screen.  Now any non-quoted, non-editing control character
simply causes Kermit to beep.  gtword(): ckucmd.c.

Allow '-' at end of line as command continuation character in both TAKE files
and interactively.  '\' at end still works too.  If you really need a line
to end with '-', use \44.  ckuusr.c and ckucmd.c.

In ckucmd.c, simplified the character quoting mechanism.  Rules:
 1. The low-level command parser treats \ as a quote for control characters,
    space, and question mark only.  Removes the \, leaves the quoted char.
 2. If you follow \ by any other character, the \ and the following chars are
    left in for the higher level command-specific code to interpret, namely
    the xxstring() function.  This way commands like INPUT, OUTPUT, ECHO, ASK,
    etc, no longer require you to double the \. 

Changed xxstring(), whose purpose is to expand backslash codes embedded within
strings, to handle nested variable definitions via recursive descent.  Deeply
nested or circular definitions are caught and recovered from.

Added ASSIGN command, like MS-DOS Kermit.  When a variable is DEFINEd, the
names any other variables appearing in the definition are simply copied.  When
a variable is ASSIGNed, variable names on the right hand side are evaluated,
and their values assigned.  To demonstrate:
  def %a foo
  def %b \%a
  ass %c \%a
  def %a oofa
  echo \%b, \%c
This echoes "oofa, foo" because b's value changes with a's, but c's doesn't.

Tried to separate the system-independent and system-dependent aspects of the
character set translation.  Results are in ckcxla.h (supposedly system
independent), ckuxla.h (specific to UNIX and VAX/VMS), ckcxka.c (actual C
code, translation functions and tables).  This work is best completed by
somebody who is actually trying to make the character set stuff work in a
totally different environment, like OS/2 or Macintosh.  If this was done
right, then people would only have to (a) create a ck?xla.h file for any new
system that is to be supported, and (b) add any necessary translation
functions and/or tables to ckcxla.c.  But unfortunately it's not quite that
easy to separate this stuff.  At least it still compiles and runs...

Also, make C-Kermit send I6/100 as the transfer character set designator for
Latin-1, rather than I2/100.  The former is correct and works with patched
versions of MS-DOS Kermit 3.00, the latter is incorrect but it's the only one
that will work with unpatched MS-DOS Kermit 3.00.  Ugh!  Workaround for
unpatched 3.00: SET ATTR CHAR OFF, SET TRANSF CHAR LATIN1.

------------------------------

5A(105) Sun Jan 28 12:02:02 1990

Much work on macros and take files today, almost entirely in ckuusr.c.

Debug macro argument assignment.  Here are the rules:
 0. name of macro is assigned to %0.
 1. value of argument 1 is assigned to variable %1, arg 2 to %2, up to %9.
 2. arguments past 9 are ignored.
 3. leading spaces in args are stripped.
 4. arguments are separated by one or more spaces
 5. multiple words can be grouped into one arg by { using braces }.
 6. all spaces within braced args are preserved, but the braces are discarded.
 7. chars after closing brace of braced arg begin a new arg even if no space.
 8. interior braces within an arg are kept.
 9. %0..%9 are cleared at each macro invocation, before argument assignment.

Made a call stack for macro invocations.  %1..%9 are local to each macro.
Use the (invisible) TEST command (within a macro) to dump the macro stack.
Treat macro args, global variables, and macro definitions as three separate
kinds of variables.  Macro args are in the macro-arg stack; global variables
are in a direct-access table, and macro definitions are in a lookup table.

Rules for variable names:
 1. Start with %.
 2. Commands that parse variable names also allow them to start with \%,
    for compatibility with MS-DOS Kermit.  Internally the \ is discarded. 
 3. Only a single character can follow the %.
 4. If it's a digit 0-9 then it's a macro argument, on the stack.
 5. If it's any printable other than a digit, it's a global variable.
 6. Uppercase letters are lowered, so %a is the same variable as %A.
 7. Variable names embedded in strings must begin with \, like "echo A\%bC".

Maximum length for a macro definition is the command buffer length, CMDBL,
defined in ckucmd.h as 255.  This can be increased.

OK so now we have a TAKE-file stack and macro stack.  Next problem: a TAKE
command didn't work from within a macro.  Why? because the code says "I'm
executing a macro so that's where I look for the next command".  So we also
need a general command stack to record every TAKE file or macro invocation.
Every time we exit from or otherwise finish executing a macro or a take file,
we pop this stack so that we go back to the right place.

The COUNT variable used to be stacked for take-files.  Now it is stacked
by command level, since SET COUNT / IF COUNT can be used in both take files
and macros.  Note: COUNT-loops cannot be nested within the same take file
or macro (nor can they be in MS-DOS Kermit).

What if a deeply-nested take file or macro DEFINEs a new macro, thus changing
the macro table?  Will we return to the right places while popping up the
stack?  Yes - the command stack is totally independent of the macro table. 

Remove requirement to type DO before macroname in order to execute the macro.
This was done as follows: in the main parse loop, if ckmkey2 returns -2 (no
match on keyword), then look up the word in the macro table and if it is
found, stuff a "do" before it in the command buffer and reparse.  This didn't
work for macros without arguments, however, so yet another ugly modification
was required to ckmkey2(): if an invalid keyword is typed and terminated by CR
or LF, then return -6 rather than -2.  In that case, the main parse loop
stuffs "do" before it and CR after it.  ckmkey2() was also changed to not
print "invalid" when keywords don't match.  Leave that to the caller.  Doesn't
seem to work all the time: sometimes we get two "invalid" messages (e.g. "set
foo<cr>").  Built-in commands have precedence over macros with same name.  To
override this precedence, specify "do".  ckuusr.c, ckucmd.c.

Other changes today:

Add SET DEBUG ON as invisible synonym for LOG DEBUG.  ckuusr.c.

Added -d to the command-line switches looked for by prescan(), so that
debug() statements can be added to the startup sections of the code.

Added ASK command.  Only works at terminal, not from command files (same as
MS-DOS Kermit).  Allows backslash escapes in prompt.  No ASKQ yet, need to
modify cmd package for this.

Added help messages for tokens like !, #, &, etc.

Add POP as synonym for END for compatibility with MS-DOS Kermit.

------------------------------

5A(104) Sat Jan 27 15:13:43 1990

Removed restriction that prevented GET, BYE, FINISH, and REMOTE commands
from working in remote mode.  Now you can issue these commands from a TAKE
file on your remote system, escape back to your PC, put it in server mode,
and everything works.  ckuusr.c.

Or does it?  Discovered that GET, BYE, FINISH, and REMOTE commands don't work
at all!  Problem was in the very tricky (and stupid) area where packet numbers
are not incremented from 0 when a client sends an I packet, then a G or R
packet, then gets an S packet.  Had to put a couple window-specific statements
into ckcpro.w, in the <ipkt>Y case.  This is really ugly, because the
application layer should not have to know anything about transport-layer
issues.  The reverse alternative would have been just as bad.  There still
seems to be one case of a send-buffer not being freed after ACKing the S
packet, but no harm is done by it.  Will have to come back to all this later.
At least now it works.  ckcpro.w.

Changed the message "Unimplemented generic server function" to "Unimplemented
REMOTE command".  ckcpro.w.

Removed vestigial packet buffer management functions from ckcfn3.c.

When receiving a file, pass the attribute structure to opena() in ckcfn3.c,
which in turn passes it to openo() in ckcfn3.c, which in turn passes it to
zopeno() in ck*fio.c, so that the system-depended function that actually opens
the file can use any received attributes when deciding how to open it.  All
ck*fio files should be changed accordingly.  But probably no harm is done if
some are not, because this is an informational trailing argument, and only
"lint" will complain.  ckufio.c has this change, but the UNIX version of
zopeno() does not use the attribute information for anything.

Allow I6/100 as a designator for ISO Latin-1 in attribute packets.  Previously
only I2/100 was recognized, but in reality I6/100 is more correct (2 =
International Reference Version of ISO-646; 6 = US ASCII, which is indeed the
true left half of ISO 8859-x alphabets).  (untested)  ckcfn3.c.  

Add server-end support for REMOTE SET commands from PC client (new Kermit
protocol feature, specified in Info-Kermit Digest V11 #1 by Christine M.
Gianone, Jan 1990).  The C-Kermit server responds correctly to the following
REMOTE SET commands: ATTRIBUTES {IN, OUT} ALL { ON, OFF }; FILE TYPE,
FILE NAMES, FILE COLLISION (partially), FILE INCOMPLETE, BLOCK-CHECK, RECEIVE
PACKET-LENGTH, RECEIVE TIMEOUT, RETRY, SERVER TIMEOUT, TRANSFER CHARACTER-SET,
and WINDOW-SLOTS.  ckcfns.c.

Fill in HELP messages for new commands.  ckuus2.c.

Add expansion of variable names %0, %1, ... %9, %a, %b, ... %z, etc, to
xxstring, which is called by ECHO, INPUT, OUTPUT.  A variable is % followed by
any single character.  Uppercase letters are folded to lowercase.  You don't
have to (but you may) include the backslash in the DEFINE command, but you
must prefix the % by a backslash when referencing it (really, two
backslashes).  So far we're not doing this recursively.  ckuusr.c.

When a macro is invoked, assign its name to %0, and its arguments, if any,
to %1..%9.  As in MS-DOS Kermit, allow grouping of words into a single
argument using braces, as in "first {this is the second} third".  Unlike
MS-DOS Kermit, C-Kermit clears variables %0..%9 when a macro is invoked,
so that there are no leftover values to be misinterpreted.  ckuusr.c.

Add IF [NOT] DEFINED, so that macros can check which arguments they were
called with and which were left off, so they can supply defaults reliably.

------------------------------

5A(103) Sun Dec 31 20:19:55 1989

Add '-y' command-line option for specifying an alternate initialization file
name.  Argument to -y is assumed to be in current directory or else filename
must include path.  Changes in ckuusr.c for parsing command line including new
prescan() function, ckuus4.c for SHOW command, ckuus2.c for usage message,
ckcmai.c for call to prescan().

In SHOW command, display "unknown" for speed, rather than -1, when the speed
is less than zero.

Fix error in ckuscr.c, function recvSeq(), changed:
  got_it = (!strncmp(seq_buf, got, l) ) ;
to:
  got_it = (!strncmp(e, got, l) ) ;
Before this fix, an "expect" string longer than 7 characters could cause
problems: the function would compare the first 7 characters, rather than the
last 7 (from Pawan Misra, Bellcore).

------------------------------

5A(102) Mon Dec 25 16:59:37 1989

Remove "2" attribute, put the transfer character set into the encoding
attribute after "C" -- rule modified by concensus of ISO-Kermit group.
In gattr(), set rx to be the address of the input translation function
after getting the transfer character set from the attribute packet.
In ckcxla.c, correct an error in the Latin-1 to German NRC translation table.
Tested with MS-DOS Kermit 3.0 prerelease.  Picks up transfer character set
correctly when receiving files, and translates OK.  Also puts the appropriate
encoding attribute into outbound attribute packets.

------------------------------

5A(101) Mon Aug 28 22:33:16 1989

OK, time to start getting specific again.  Today's changes: Fill in and
correct translation tables in ckcxla.c.  Changed the symbols TC_LATIN1,
TC_LATIN2, etc, to TC_1LATIN, TC_2LATIN, etc, because some preprocessors
ignore past the 8th character.

Remove timeout alarm from tthang - it was causing core dumps, don't know why.

------------------------------

5A(100) July 14 - Aug 25, 1989

Version 5A has four major new features, and many minor ones.  The major ones
are sliding windows, international character sets, a regular Kermit-style
script language, and macros.

SLIDING WINDOWS

Changes too numerous to describe in detail.  Briefly: a new module, ckcfn3.c,
was added which includes the sliding window buffers and buffer management
functions.  ckuus*.c were modified to support the SET WINDOW <n> command.
ckcfn[s2].c contain numerous modifications; the biggest changes were to the
input() function in ckuus2.c, which effectively acts as Kermit's transport
layer by managing the sequencing, allocating and freeing packet buffers, and
feeding incoming packets in order to the application layer state switcher in
ckcpro.w, which needed only minor modification to support windowing.

Windowing occurs only during the transmission of data (D) packets.  This is
because (a) it cannot take place until after it is negotiated in the S/I/Y
packet exchange, and (b) because a file is preceded by Attribute (A) packets,
based upon which the file receiver may elect to refuse the file.  In ckcfn2.c,
the sdata() function was modified to send up to a windowful of packets at once,
instead of just one one packet.

The sliding window option is fully compatible with Kermit's other options,
including long packets.  The user may elect to have a window of any size, from
1 to 31, and packets of any length so long as the packet size times the window
size does not exceed the total buffer size BIGRBUFSIZ defined in ckuker.h
(this restriction could be relaxed in the future by using malloc to get buffer
space).  Window size takes precedence, so that if the user specifies packets
that are too long or too many window slots, the program will adjust the packet
size downwards.

Sliding windows tested locally against MS-DOS Kermit 3.0 prerelease, Crosstalk
Mk.4, ProComm, etc.  There is some minor performance increase.  Tested across
Telenet with Prime Kermit at The Source (just before The Source shut down for
good), and performance is dramatically better than stop-and-wait over the same
connection, as expected.  There was not time to make detailed measurements
before The Source was turned off.

INTERNATIONAL CHARACTER SETS
 
Addition of 'set file character-set', 'set transfer', and 'set language',
commands.  Installation of numerous translation functions and tables.
Addition of local 'translate' command to translate a local file according to a
given table.

Creation of new module, ckcxla.c and ckcxla.h, for international language
support.  Currently includes the various 7-bit ISO 646 National Replacement
Character sets (NRC's), plus regular ASCII, DEC MCS, and ISO Latin-1, as local
file character sets, and ASCII and Latin-1 as transfer character sets.

In gattr(), check incoming transfer character set designator if specified in
'2' attribute, and if not known, refuse the file, citing '2' in the attribute
refusal.  If it is known, set the the transfer character set accordingly.
(This may need more work -- e.g. after the transfer is over, should the
transfer character set revert to what the user said?)  (Note added later: this
approach was voted down by the ISO/Kermit committee - there is no longer a '2'
attribute; character set is given in the '*' encoding attribute.)

Some changes will probably be made as the iso/kermit proposal evolves.

Things to do:
 - Add Macintosh character set
 - Add commands to modify a translation table.
 - Add LOAD/DUMP/MODIFY/etc CHARACTER-SET facility.

SCRIPTS

Addition of INPUT, OUTPUT, PAUSE, IF, and GOTO commands, plus labels as
targets of GOTOs.  Works approximately as in MS-DOS Kermit, except timeout
parameter on INPUT statement is required, not optional.  If a goto is
encountered, nothing happens unless we're in a take file (or macro, see
below).  The take file is rewound and searched from the beginning for the
label.  The IF command currently has the options: NOT, COUNT, EXIST, SUCCESS,
and FAILURE.  The latter two correspond to the most recent INPUT command.
Operates slightly differently in TAKE files and interactively (like
MS-DOS Kermit).  IF commands can be combined, as in IF COUNT IF EXIST FOO.BAR
ECHO AHA!.

Also added SET COUNT <n>, SET TAKE ECHO { ON, OFF }, CLEAR, STOP, END, plus
SHOW COUNT.

Added a new function xxstring() in ckuus4.c, which interprets \-escapes in
strings similarly to MS-DOS Kermit -- allows radix specification, grouping 
inside braces, etc.  Made ECHO, INPUT, and OUTPUT command use it.  Thanks to
Christine Gianone for some of this code.

Wrote a complicated script and it didn't work.  After several hours of
debugging, figured out that there was no call to ttvt() or ttpkt() in
preparation for INPUT and OUTPUT.  For now, I put a call to ttvt() in both
INPUT and OUTPUT, and set a flag the first time it's called so it needn't be
called again.  Later, have to find a better way -- like just go ahead and set
the RAW and ~ECHO bits right inside of ttopen().  What harm can there be in
that?

Still to do:
 - Make sure it's ok for ttopen() to call ttvt(), then make this change.
 - Occasionally get core dumps with SET DEB ON and HANGUP (maybe fixed already)
 - Maybe allow some pattern matching in the INPUT string???

MACROS

Added DEFINE command, similar to MS-DOS Kermit.  "define <name> <string>"
defines the variable <name> as <string>.  "do <name>" executes the associated
string (on the assumption it is a valid command).  The <string> can be a comma
separated list of commands, and Kermit will do them one after the other,
replacing commas with carriage returns, and storing each command in the
command buffer as if the user had typed it.  A macro may invoke other macros,
up to a level defined by MACLEVEL (currently 20).  "define <name>" undefines
the macro.  One macro "ibm-linemode" is predefined.  "show macros" lists the
named macro, or if none named, all the defined macros.

All of the support for macros is in ckuusr.c and .h.  No changes were required
to ckucmd.c.  When macros are defined, space for the name and definition is
malloc'd, and they are inserted into an alphabetical keyword table.  When
undefined, they are removed from the table and the rest are moved up, so the
table is always sorted alphabetically and has no holes.

Special code was required in several places to handle GOTOs and IFs within
macros.

OTHER CHANGES

Also install attribute refusal for unknown file types (i.e. other than A
and B), unknown encodings (other than A and C), unknown dispositions (other
than M and P).

As part of the label-recognizing code, also found a way to allow a command
line to begin with a token, followed by arbitrary text without any intervening
spaces.  So now you can have "%foo", "!foo", etc, as well as ":foo" (the new
label syntax).  Added ; and # as synonyms for % (whole-line comment
introducer).  The way this works is really ugly -- if cmkey fails to match a
keyword, then it searches a string of single-character tokens, and then sets
the command buffer pointers & flags to allow reparsing of the text past the
token on the next call to gtword().  Actually, a special version of cmkey(),
called cmxkey or something like that, is used for this, leaving cmkey() more
or less the way it was.

Reorganization of many modules, to even out their sizes.  Movement of some
non-sliding-windows related functions to ckcfn3.c.  Creation of new ckuus4.c
and movement of many functions from the other ckuus*.c modules to it.
"size *.o" no longer shows several disproportionately huge object modules.

Decomposition of 'show' command in various subcommands -- 'show
communications', 'show protocol', 'show file', 'show languages', 'show
versions', 'show count', etc.

Addition of TYPE command, interruptible by Ctrl-C.

Addition of DELETE command (invokes system's delete function).

Add invisible synonyms: RM for DELETE, LS for DIRECTORY.

Total recoding of the ttinl() (packet reading) function in ckutio.c, to
make it as tight and efficient as possible, and not to read ahead
destructively as the old version used to (which would prevent successful
input of a chain of packets in sequence).  

More detailed statistics reporting.

Move system-dependent mail and print string-making into ckufio.c, into
new functions called zmail() and zprint().  These must be added to all the
other ck*fio.c files (they can just return the null string if they don't
do anything).  This is still not ideal, however.  Instead of mailing/printing
the file after it is received, the program should handle the disposition
attribute before receiving the file, and then (for Unix anyway) pipe the file
to the command.  That way, the receiver wouldn't need disk space/access, etc.
Unfortunately, not all operating systems have pipes, so this would not be
portable.

Allow 'set speed' command in remote mode as well as local.  In remote mode,
this lets you tell C-Kermit what your line speed is (as opposed to letting
you change it), so "percent efficiency" can be reported.  Later, this can
also be used to calculate better timeouts, etc.  (It might be preferable to
have the program ask the OS for the current speed.)

Make the terminal speeds into keywords, so now you can do "set sp 9<esc>"
to get 9600, etc.  (ckuus3.c)

------------------------------
*****************
End of CKU178.UPD