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 was backwards in setlin(). ckuus7.c. Extraneous "#include " 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 , 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 Z case, suggested by Manfred Prange. Added confirming message "Hanging up" when user types 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 [ [ ] ] 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 elimiate 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(): 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 "progamming 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 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 . 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 throught 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 ..." 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 , 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 . 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 . 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, DECstatsion/Ultrix, VAXstatsion/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 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 . 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 characer 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 , 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 , it is already defined in . 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 . 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 . 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 . 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, 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 . 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 -- R_OK, etc, are defined in instead. Made -DTERMIOX the default for System V R4 (i.e. what you get when you "make sys5r4"), meaning to use . Use "sys5r4nx" to omit it, or "sys5r4sx" to use . 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 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 file (a) exists practically nowhere, and (b) is sometimes found in , 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 gratuitious 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 " and so may wind up with double declarations -- but not all 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 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 : Fortune fixes, and also one for everybody: it seems 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 . 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 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 . 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 modifed (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 noticable 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 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 , 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() statment 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 surpressed.) 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 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 . 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 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 or or 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 ? - 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 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 noticable 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. .~~, where is a number from 1 to 9999 (previously it was simply ~). 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 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 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 paramater 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 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 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 wierd -- 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 0 and OK (returns 1); 4 or ERROR (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 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 . However, it does have a and an 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 " 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 . 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 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: imbedded 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 rather than ). 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 . 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, . ckvfio.c. 35. Corrected the problem where 2 nulls would be inserted into received binary files every 32Kb when DYNAMIC is defined. The zbuffers 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 , 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 . 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 ! KERMIT_FD=\v(ttyfd) run 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 " and it always translated from the current transfer character set to the current file character set, which was unreasonably limiting. Now it's: TRANSLATE [ ] 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 [ ] 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 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 "" to "", 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: 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, "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 (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 's when log files were viewed using an editor. ckvfio.c. UNIX-SPECIFIC CHANGES Added CONNECT-mode escape to suspend Kermit: Z or ^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 DECstatsions. 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 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 noticably 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 before . John Nall (new Minix tester) says it didn't work the other way. This change should only affect Minix, because the "#include " 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 occured, 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 message or not. This has been added as an optional trailing field to the SET MODEM command: SET MODEM [ { 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 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 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 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 synomym 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 X 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 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 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 for directory-related operations. -DDIRENT means . 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 { command [, command [, command ... ] ] ] } where 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 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 -- cancelling 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, 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 . 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 is included. Added -DNOFILEH to the makefile entries, and simply included unless NOFILEH was defined. Added a couple special cases because RTU, CIE, FT18, and BSD41 need to have 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 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 miscellanous 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. Does it beep? (It should.) 6. Type SEND af. 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 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 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 , -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, , and that would become obsolete. POSIX took this one step further, and does not even allow for the existence of (see IEEE Std 1003.1). (Historical note: reportedly, the 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: , , , , "/usr/lib/bsd/ndir.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 . Otherwise, if DIRENT is defined, we use . In all other cases we use . 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 , include one of the following switches: Header file CFLAGS switch -DNDIR -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 , 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: , open(), read(), close(). Pre-6.2 versions of HP-UX? hpuxlf: , opendir(), readdir(), etc (BSD style) hpuxde: , 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 rather than . 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 inferrable 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 . 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 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 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 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 , 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 existens 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 first, to pick up the local compiler's preferred definition, so that the 0L definition will only kick in if 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 concensus 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 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 noticable 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 , 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 { 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 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 philosphy 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 Comamnds 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 obstactle. 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 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 synomym 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 . 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 ambigous (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 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, . 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 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 . 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 " instead of "dir xyz". 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 . In ckutio.c add conditionals for #ifndef is68k (whatever that is) to not include sys/file.h or fcntl.h (from Ray Moody : 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 . 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 ) 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 initally 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 , 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] [ ] ELSE [ ] ELSE must be on a separate line, and there is no word THEN. 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] IF [NOT] IF ... [ ] ELSE [ ] 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 are metasymbols, + means 1 or more repetition of, * means zero or more repetitions of, and ::= means "is replaced by"): ::= newline (linefeed or CR or CRLF) ::= NOT ::= any C-Kermit command except ELSE, including no command at all ::= EXISTS filename | < n1 n2 | = n1 n2 | EQUAL s1 s2 | etc etc ::= IF * ::= + | ELSE Note the left-recursive definition of . 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 where and 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 and may expand to anything at all except null, which terminates the string. The two expanded 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 synomym 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"). 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 synomym 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 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 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 , 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 " defines the variable as . "do " executes the associated string (on the assumption it is a valid command). The 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 " 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" to get 9600, etc. (ckuus3.c) ------------------------------ ***************** End of CKU178.UPD